modbus_host.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. /*
  2. ****************************************************************************
  3. ModBus主机协议
  4. ****************************************************************************
  5. */
  6. // #define DBG_TAG "modbus"
  7. // #define DBG_LVL DBG_LOG
  8. // #include <rtdbg.h>
  9. #include <rtthread.h>
  10. #include "main.h"
  11. #include "modbus_host.h"
  12. #include "loar.h"
  13. #include "Host.h"
  14. #include "bsp_date.h"
  15. #define TIMEOUT 800 /* 接收命令超时时间, 单位ms */ // 部分传感器返回时间较长,由500改为800
  16. #define NUM 1 /* 循环发送次数 */
  17. MODH_T g_tModH;
  18. LOAR_Tx loar_t;
  19. uint8_t g_modh_timeout = 0;
  20. static void MODH_RxTimeOut(void);
  21. static void MODH_AnalyzeApp(uint8_t sort);
  22. // static void MODH_Read_01H(void);
  23. // static void MODH_Read_02H(void);
  24. void MODH_Read_03H(uint8_t sort);
  25. // static void MODH_Read_04H(void);
  26. // static void MODH_Read_05H(void);
  27. // static void MODH_Read_06H(void);
  28. // static void MODH_Read_10H(void);
  29. static void MODH_ReciveNew(uint8_t _data);
  30. VAR_T g_tVar;
  31. // 需要连接的外部接口函数
  32. extern void (*RS485_ReceiveData)(uint8_t); // 接受数据,在串口中断接受到的数传递到此函数即可
  33. extern void RS485_SendBuf(uint8_t *_ucaBuf, uint16_t _usLen, UART_HandleTypeDef *uart); // 发送数据
  34. extern void bsp_StartHardTimer(uint32_t timeout, void *_pCallBack); // 开始计时3.5个字节的时间,单位为us
  35. // 以下两个函数用来测量间隔时间
  36. extern uint32_t bsp_GetRunTime(void); // 返回当前时间,单位ms
  37. extern uint32_t bsp_CheckRunTime(int32_t _LastTime); // 返回与之前间隔的时间
  38. extern uint8_t uart3_tx_buf[64];
  39. extern uint8_t uart3_tx_count;
  40. /*
  41. *********************************************************************************************************
  42. * 函 数 名: MODH_SendAckWithCRC
  43. * 功能说明: 发送应答,自动加CRC.
  44. * 形 参: 无。发送数据在 g_tModH.TxBuf[], [g_tModH.TxCount
  45. * 返 回 值: 无
  46. *********************************************************************************************************
  47. */
  48. static void MODH_SendAckWithCRC(void)
  49. {
  50. uint16_t crc;
  51. crc = CRC16_Modbus(g_tModH.TxBuf, g_tModH.TxCount);
  52. g_tModH.TxBuf[g_tModH.TxCount++] = crc >> 8;
  53. g_tModH.TxBuf[g_tModH.TxCount++] = crc;
  54. RS485_SendBuf(g_tModH.TxBuf, g_tModH.TxCount, &huart2);
  55. }
  56. /*
  57. *********************************************************************************************************
  58. * 函 数 名: LOAR_SendAckWithCRC
  59. * 功能说明: 发送应答,自动加CRC.
  60. * 形 参: 无。发送数据在 g_tModH.TxBuf[], [g_tModH.TxCount
  61. * 返 回 值: 无
  62. *********************************************************************************************************
  63. */
  64. void LOAR_SendAckWithCRC(void)
  65. {
  66. uint16_t crc;
  67. crc = CRC16_Modbus(loar_t.TxBuf, loar_t.TxCount);
  68. loar_t.TxBuf[loar_t.TxCount++] = crc >> 8;
  69. loar_t.TxBuf[loar_t.TxCount++] = crc;
  70. RS485_SendBuf(loar_t.TxBuf, loar_t.TxCount, &huart3);
  71. loar_t.TxCount = 0;
  72. }
  73. /*
  74. *********************************************************************************************************
  75. * 函 数 名: MODH_AnalyzeApp
  76. * 功能说明: 分析应用层协议。处理应答。
  77. * 形 参: 无
  78. * 返 回 值: 无
  79. *********************************************************************************************************
  80. */
  81. static void MODH_AnalyzeApp(uint8_t sort)
  82. {
  83. switch (g_tModH.RxBuf[1]) /* 第2个字节 功能码 */
  84. {
  85. /* case 0x01: 读取线圈状态
  86. MODH_Read_01H();
  87. break;*/
  88. /* case 0x02: 读取输入状态
  89. MODH_Read_02H();
  90. break;*/
  91. case 0x03: /* 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值 */
  92. MODH_Read_03H(sort);
  93. break;
  94. // case 0x04: /* 读取输入寄存器 */
  95. // MODH_Read_04H();
  96. // break;
  97. /* case 0x05: 强制单线圈
  98. MODH_Read_05H();
  99. break;*/
  100. // case 0x06: /* 写单个寄存器 */
  101. // MODH_Read_06H();
  102. // break;
  103. // case 0x10: /* 写多个寄存器 */
  104. // MODH_Read_10H();
  105. // if(g_tModH.RxBuf[2] == 0x00)g_tModH.fAck10add = 1;/*接收到应答,非本库,后续添加(00 10 00 7C)*/
  106. // PrintBuf(g_tModH.RxBuf,5);
  107. /* break;*/
  108. /* case 0x20: 读取地址
  109. g_tVar.ADD = g_tModH.RxBuf[2];
  110. g_tModH.fAck20inquire = 1;*/
  111. /*接收到应答,非本库,后续添加(00 20 address CRCH CRCL)*/
  112. // PrintBuf(g_tModH.RxBuf,5);
  113. /* break;
  114. case 0xEE: 读取地址
  115. g_tModH.fAckEE = 1;接收到应答,非本库,后续添加(00 10 00 7C)
  116. rt_kprintf("日照时数传感器写入时间成功!\n");
  117. break;*/
  118. default:
  119. // rt_kprintf("no match\n");
  120. break;
  121. }
  122. }
  123. /*
  124. *********************************************************************************************************
  125. * 函 数 名: MODH_Send01H
  126. * 功能说明: 发送01H指令,查询1个或多个保持寄存器
  127. * 形 参: _addr : 从站地址
  128. * _reg : 寄存器编号
  129. * _num : 寄存器个数
  130. * 返 回 值: 无
  131. *********************************************************************************************************
  132. */
  133. // void MODH_Send01H(uint8_t _addr, uint16_t _reg, uint16_t _num)
  134. //{
  135. // g_tModH.TxCount = 0;
  136. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  137. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x01; /* 功能码 */
  138. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  139. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  140. // g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
  141. // g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */
  142. //
  143. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  144. // g_tModH.fAck01H = 0; /* 清接收标志 */
  145. // g_tModH.RegNum = _num; /* 寄存器个数 */
  146. // g_tModH.Reg01H = _reg; /* 保存03H指令中的寄存器地址,方便对应答数据进行分类 */
  147. // }
  148. /*
  149. *********************************************************************************************************
  150. * 函 数 名: MODH_Send02H
  151. * 功能说明: 发送02H指令,读离散输入寄存器
  152. * 形 参: _addr : 从站地址
  153. * _reg : 寄存器编号
  154. * _num : 寄存器个数
  155. * 返 回 值: 无
  156. *********************************************************************************************************
  157. */
  158. // void MODH_Send02H(uint8_t _addr, uint16_t _reg, uint16_t _num)
  159. //{
  160. // g_tModH.TxCount = 0;
  161. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  162. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x02; /* 功能码 */
  163. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  164. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  165. // g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
  166. // g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */
  167. //
  168. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  169. // g_tModH.fAck02H = 0; /* 清接收标志 */
  170. // g_tModH.RegNum = _num; /* 寄存器个数 */
  171. // g_tModH.Reg02H = _reg; /* 保存03H指令中的寄存器地址,方便对应答数据进行分类 */
  172. // }
  173. /*
  174. *********************************************************************************************************
  175. * 函 数 名: MODH_Send03H
  176. * 功能说明: 发送03H指令,查询1个或多个保持寄存器
  177. * 形 参: _addr : 从站地址
  178. * _reg : 寄存器编号
  179. * _num : 寄存器个数
  180. * 返 回 值: 无
  181. *********************************************************************************************************
  182. */
  183. void MODH_Send03H(uint8_t _addr, uint16_t _reg, uint16_t _num)
  184. {
  185. g_tModH.TxCount = 0;
  186. g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  187. g_tModH.TxBuf[g_tModH.TxCount++] = 0x03; /* 功能码 */
  188. g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  189. g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  190. g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
  191. g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */
  192. /*
  193. rt_kprintf("g_tModH.TxBuf :%x %x %x %x %x %x %x %x ",
  194. g_tModH.TxBuf[0],g_tModH.TxBuf[1],
  195. g_tModH.TxBuf[2],g_tModH.TxBuf[3],
  196. g_tModH.TxBuf[4],g_tModH.TxBuf[5],
  197. g_tModH.TxBuf[6],g_tModH.TxBuf[7]);
  198. */
  199. MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  200. g_tModH.fAck03H = 0; /* 清接收标志 */
  201. g_tModH.RegNum = _num; /* 寄存器个数 */
  202. g_tModH.Reg03H = _reg; /* 保存03H指令中的寄存器地址,方便对应答数据进行分类 */
  203. }
  204. extern LOAR_Parameter loar_par; // 这里面存放loar的参数和ID
  205. extern Loar_Device Slave_list[]; // 存放已配对的从机的各种信息
  206. extern uint8_t Freq; // 存放拨码开关读取到的频段号
  207. extern Sensor sensor[MAX_SENSOR_NUM];
  208. extern RTC_TimeTypeDef GetTime;
  209. extern uint8_t ReFlash_RTC(void);
  210. // 输入从机地址 即可发送对从机的配置包
  211. void LOAR_SEND_DATA(uint8_t address, uint8_t Inclued_Sensor)
  212. {
  213. // LOG_I("LOAR_SEND_DATA address:%d", address);
  214. address--;
  215. // RTC_TimeTypeDef Get_real_Time;
  216. // uint32_t Timestamp = 0;
  217. if (address < 0 || address > MAX_Slave_NUM)
  218. {
  219. rt_kprintf("Addr ×");
  220. return;
  221. }
  222. if (loar_t.TxCount != 0)
  223. {
  224. loar_t.TxCount = 0;
  225. }
  226. ReFlash_RTC();
  227. /***********************************************************************************************/
  228. /* 下发数据的消息定义 */
  229. // 例: 5A datalen address ID(4字节) TFREQ RFREQ interval SF Hour Min Sec
  230. // 00 01 02 03 04 05 06 07 08 09 10 11 12 13
  231. // 5A 固定的消息头
  232. // datalen 除帧头 CRC datalen之外的数据字节数
  233. // address 从机地址 配网时分配
  234. // ID 模块的ID 占用4字节
  235. // TFREQ 发送频段标号
  236. // RFREQ 接收频段标号
  237. // interval 下发数据间隔1
  238. // SF 扩频因子
  239. // CRCH/L CRC校验 消息尾
  240. // RTC 对时 时分秒
  241. /// 5A 0C 06 13 12 40 80 00 00 0A 10 hour min sec
  242. /***********************************************************************************************/
  243. loar_t.TxBuf[loar_t.TxCount++] = 0x5A; // 固定数据头
  244. loar_t.TxCount += 1; // 留一位给数据长度
  245. // LOG_I("Slave_number : %d", address);
  246. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[address].Address; // 写入从机地址
  247. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[address].ID[0]; // 把从机的ID填充到预发送buff
  248. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[address].ID[1];
  249. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[address].ID[2];
  250. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[address].ID[3];
  251. loar_t.TxBuf[loar_t.TxCount++] = Freq; // 写入发送频段
  252. loar_t.TxBuf[loar_t.TxCount++] = Freq; // 写入接收频段
  253. loar_t.TxBuf[loar_t.TxCount++] = sys_info.interval; // 写入上报数据的时间间隔
  254. loar_t.TxBuf[loar_t.TxCount++] = loar_par.SF; // 写入扩频因子
  255. loar_t.TxBuf[loar_t.TxCount++] = GetTime.Hours; // 写入当前时间
  256. loar_t.TxBuf[loar_t.TxCount++] = GetTime.Minutes;
  257. loar_t.TxBuf[loar_t.TxCount++] = GetTime.Seconds;
  258. if (Inclued_Sensor == One)
  259. {
  260. for (uint8_t a = 0; a < MAX_SENSOR_NUM; a++)
  261. {
  262. if (sensor[a].cfged == 1)
  263. {
  264. loar_t.TxBuf[loar_t.TxCount++] = 's';
  265. loar_t.TxBuf[loar_t.TxCount++] = a + 0x30;
  266. loar_t.TxBuf[loar_t.TxCount++] = sensor[a].sensor_addr;
  267. loar_t.TxBuf[loar_t.TxCount++] = (uint8_t)(sensor[a].start_reg >> 8);
  268. loar_t.TxBuf[loar_t.TxCount++] = (uint8_t)(sensor[a].start_reg & 0x00FF);
  269. loar_t.TxBuf[loar_t.TxCount++] = sensor[a].count;
  270. loar_t.TxBuf[loar_t.TxCount++] = sensor[a].d_pos;
  271. loar_t.TxBuf[loar_t.TxCount++] = sensor[a].d_length;
  272. }
  273. }
  274. }
  275. loar_t.TxBuf[1] = (loar_t.TxCount - 2); // 写完数据统计数据长度 并加到长度的位置
  276. for (uint8_t b = 0; b < loar_t.TxCount; b++)
  277. {
  278. rt_kprintf("%02X ", loar_t.TxBuf[b]);
  279. if ((b + 1) % 16 == 0)
  280. {
  281. rt_kprintf("\n");
  282. }
  283. }
  284. LOAR_SendAckWithCRC(); // 添加CRC并发送
  285. rt_thread_mdelay(999);
  286. }
  287. /*
  288. *********************************************************************************************************
  289. * 函 数 名: Loar_Send_Broadcast
  290. * 功能说明: laor配置模式下发送广播包
  291. * 形 参: 无
  292. * 返 回 值: 无
  293. *********************************************************************************************************
  294. */
  295. void Loar_Send_Broadcast(void)
  296. {
  297. loar_t.TxCount = 0; // 给txcount清零
  298. loar_t.TxBuf[loar_t.TxCount++] = 0x5A; // 放入帧头
  299. loar_t.TxBuf[loar_t.TxCount++] = 0x05; // 放入数据长度
  300. loar_t.TxBuf[loar_t.TxCount++] = loar_par.Address; // 放入数据长度
  301. loar_t.TxBuf[loar_t.TxCount++] = loar_par.ID[0]; // 放入ID第一位
  302. loar_t.TxBuf[loar_t.TxCount++] = loar_par.ID[1]; // 放入ID第二位
  303. loar_t.TxBuf[loar_t.TxCount++] = loar_par.ID[2]; // 放入ID第三位
  304. loar_t.TxBuf[loar_t.TxCount++] = loar_par.ID[3]; // 放入ID第四位
  305. // rt_kprintf("Send broadcast packet\r\n");
  306. LOAR_SendAckWithCRC(); // 添加CRC并发送
  307. }
  308. /*
  309. *********************************************************************************************************
  310. * 函 数 名: Loar_Send_CMD
  311. * 功能说明: 唤醒从机并发送指令
  312. * 形 参: Address 命令指向的从机地址
  313. * 形 参: Cmd 命令类型
  314. * type 1 阀控1 开
  315. * type 2 阀控1 关
  316. * type 3 阀控2 开
  317. * type 4 阀控2 关
  318. * 返 回 值: 无
  319. *********************************************************************************************************
  320. */
  321. void Loar_Send_CMD(uint8_t Address, uint8_t Cmd)
  322. {
  323. /*
  324. uint8_t time_count = 0;
  325. if (Cmd == 0xFF)
  326. {
  327. loar_t.TxCount = 0; // 给txcount清零
  328. loar_t.TxBuf[loar_t.TxCount++] = 0x9A; // 放入帧头
  329. }
  330. else
  331. {
  332. loar_t.TxCount = 0; // 给txcount清零
  333. loar_t.TxBuf[loar_t.TxCount++] = 0x9A; // 放入帧头
  334. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[Address - 1].ID[0]; // 放入ID第一位
  335. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[Address - 1].ID[1]; // 放入ID第二位
  336. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[Address - 1].ID[2]; // 放入ID第三位
  337. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[Address - 1].ID[3]; // 放入ID第四位
  338. loar_t.TxBuf[loar_t.TxCount++] = Slave_list[Address - 1].Address; // 放入数据长度
  339. switch (Cmd)
  340. {
  341. case 1:
  342. loar_t.TxBuf[loar_t.TxCount++] = 0xA1;
  343. break;
  344. case 2:
  345. loar_t.TxBuf[loar_t.TxCount++] = 0xA0;
  346. break;
  347. case 3:
  348. loar_t.TxBuf[loar_t.TxCount++] = 0xB1;
  349. break;
  350. case 4:
  351. loar_t.TxBuf[loar_t.TxCount++] = 0xB0;
  352. break;
  353. default:
  354. break;
  355. }
  356. }
  357. rt_kprintf("-->CMD %02X\r\n", Cmd);
  358. if (Cmd < 16)
  359. {
  360. LOAR_SendAckWithCRC(); // 添加CRC并发送
  361. }
  362. else
  363. {
  364. // for (uint8_t i = 0; i < loar_t.TxCount; i++)
  365. // {
  366. // rt_kprintf(" %02X\r\n", loar_t.TxBuf[i]);
  367. // }
  368. HAL_UART_Transmit(&huart3, loar_t.TxBuf, loar_t.TxCount, 1000);
  369. }
  370. while (1)
  371. {
  372. rt_thread_mdelay(30);
  373. time_count++;
  374. if (HAL_GPIO_ReadPin(TX_STU_GPIO_Port, TX_STU_Pin) == GPIO_PIN_RESET)
  375. break;
  376. }
  377. // 小于30ms 说明此时lora模块已经休眠了 先唤醒再用
  378. if (time_count == 1)
  379. {
  380. rt_kprintf("<30 ms\r\n", Cmd);
  381. wakeup_lora();
  382. HAL_UART_Transmit(&huart3, loar_t.TxBuf, loar_t.TxCount, 1000);
  383. while (1)
  384. {
  385. rt_thread_mdelay(30);
  386. time_count++;
  387. if (HAL_GPIO_ReadPin(TX_STU_GPIO_Port, TX_STU_Pin) == GPIO_PIN_RESET)
  388. break;
  389. }
  390. rt_kprintf("with %d ms rty\r\n", time_count * 30);
  391. }
  392. else
  393. rt_kprintf("with %d ms\r\n", time_count * 30);
  394. */
  395. }
  396. /*
  397. *********************************************************************************************************
  398. * 函 数 名: MODH_Send04H
  399. * 功能说明: 发送04H指令,读输入寄存器
  400. * 形 参: _addr : 从站地址
  401. * _reg : 寄存器编号
  402. * _num : 寄存器个数
  403. * 返 回 值: 无
  404. *********************************************************************************************************
  405. */
  406. // void MODH_Send04H(uint8_t _addr, uint16_t _reg, uint16_t _num)
  407. //{
  408. // g_tModH.TxCount = 0;
  409. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  410. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x04; /* 功能码 */
  411. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  412. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  413. // g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
  414. // g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */
  415. //
  416. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  417. // g_tModH.fAck04H = 0; /* 清接收标志 */
  418. // g_tModH.RegNum = _num; /* 寄存器个数 */
  419. // g_tModH.Reg04H = _reg; /* 保存03H指令中的寄存器地址,方便对应答数据进行分类 */
  420. // }
  421. /*
  422. *********************************************************************************************************
  423. * 函 数 名: MODH_Send05H
  424. * 功能说明: 发送05H指令,写强置单线圈
  425. * 形 参: _addr : 从站地址
  426. * _reg : 寄存器编号
  427. * _value : 寄存器值,2字节
  428. * 返 回 值: 无
  429. *********************************************************************************************************
  430. */
  431. // void MODH_Send05H(uint8_t _addr, uint16_t _reg, uint16_t _value)
  432. //{
  433. // g_tModH.TxCount = 0;
  434. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  435. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x05; /* 功能码 */
  436. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  437. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  438. // g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8; /* 寄存器值 高字节 */
  439. // g_tModH.TxBuf[g_tModH.TxCount++] = _value; /* 寄存器值 低字节 */
  440. //
  441. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  442. //
  443. // g_tModH.fAck05H = 0; /* 如果收到从机的应答,则这个标志会设为1 */
  444. // }
  445. /*
  446. *********************************************************************************************************
  447. * 函 数 名: MODH_Send06H
  448. * 功能说明: 发送06H指令,写1个保持寄存器
  449. * 形 参: _addr : 从站地址
  450. * _reg : 寄存器编号
  451. * _value : 寄存器值,2字节
  452. * 返 回 值: 无
  453. *********************************************************************************************************
  454. */
  455. // void MODH_Send06H(uint8_t _addr, uint16_t _reg, uint16_t _value)
  456. //{
  457. // g_tModH.TxCount = 0;
  458. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  459. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x06; /* 功能码 */
  460. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  461. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  462. // g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8; /* 寄存器值 高字节 */
  463. // g_tModH.TxBuf[g_tModH.TxCount++] = _value; /* 寄存器值 低字节 */
  464. //
  465. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  466. //
  467. // g_tModH.fAck06H = 0; /* 如果收到从机的应答,则这个标志会设为1 */
  468. // }
  469. /*
  470. *********************************************************************************************************
  471. * 函 数 名: MODH_Send10H
  472. * 功能说明: 发送10H指令,连续写多个保持寄存器. 最多一次支持23个寄存器。
  473. * 形 参: _addr : 从站地址
  474. * _reg : 寄存器编号
  475. * _num : 寄存器个数n (每个寄存器2个字节) 值域
  476. * _buf : n个寄存器的数据。长度 = 2 * n
  477. * 返 回 值: 无
  478. *********************************************************************************************************
  479. */
  480. // void MODH_Send10H(uint8_t _addr, uint16_t _reg, uint8_t _num, const uint16_t *_buf)
  481. //{
  482. // uint16_t i;
  483. //
  484. // g_tModH.fAck10H = 0; //将应答标志位置0
  485. // g_tModH.TxCount = 0;
  486. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
  487. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x10; /* 从站地址 */
  488. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
  489. // g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
  490. // g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
  491. // g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */
  492. // g_tModH.TxBuf[g_tModH.TxCount++] = 2 * _num; /* 数据字节数 */
  493. //
  494. // for (i = 0; i < _num; i++)
  495. // {
  496. // if (g_tModH.TxCount > H_RX_BUF_SIZE - 3)
  497. // {
  498. // return; /* 数据超过缓冲区超度,直接丢弃不发送 */
  499. // }
  500. // g_tModH.TxBuf[g_tModH.TxCount++] = (uint8_t)((*_buf)>>8);
  501. // g_tModH.TxBuf[g_tModH.TxCount++] = (uint8_t)(*_buf);
  502. // _buf++;
  503. // }
  504. //
  505. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  506. // }
  507. /*
  508. *********************************************************************************************************
  509. * 函 数 名: MODH_ReciveNew
  510. * 功能说明: 串口接收中断服务程序会调用本函数。当收到一个字节时,执行一次本函数。
  511. * 形 参:
  512. * 返 回 值: 1 表示有数据
  513. *********************************************************************************************************
  514. */
  515. void MODH_ReciveNew(uint8_t _data)
  516. {
  517. /*
  518. 3.5个字符的时间间隔,只是用在RTU模式下面,因为RTU模式没有开始符和结束符,
  519. 两个数据包之间只能靠时间间隔来区分,Modbus定义在不同的波特率下,间隔时间是不一样的,
  520. 所以就是3.5个字符的时间,波特率高,这个时间间隔就小,波特率低,这个时间间隔相应就大
  521. 4800 = 7.297ms
  522. 9600 = 3.646ms
  523. 19200 = 1.771ms
  524. 38400 = 0.885ms
  525. */
  526. uint32_t timeout;
  527. // if(DBG_kprintf)rt_kprintf(" _data is %d\n",_data);
  528. g_modh_timeout = 0;
  529. timeout = 35000000 / HBAUD485; /* 计算超时时间,单位us*/
  530. /* 硬件定时中断,定时精度us 硬件定时器2用于MODBUS从机, 定时器3用于MODBUS从机主机*/
  531. bsp_StartHardTimer(timeout, (void *)MODH_RxTimeOut);
  532. if (g_tModH.RxCount < H_RX_BUF_SIZE)
  533. {
  534. g_tModH.RxBuf[g_tModH.RxCount++] = _data;
  535. // if(DBG_kprintf)rt_kprintf("buf[%d] : %d \n",g_tModH.RxCount - 1, g_tModH.RxBuf[g_tModH.RxCount -1]);
  536. }
  537. }
  538. /*
  539. *********************************************************************************************************
  540. * 函 数 名: MODH_RxTimeOut
  541. * 功能说明: 超过3.5个字符时间后执行本函数。 设置全局变量 g_rtu_timeout = 1; 通知主程序开始解码。
  542. * 形 参: 无
  543. * 返 回 值: 无
  544. *********************************************************************************************************
  545. */
  546. static void MODH_RxTimeOut(void)
  547. {
  548. g_modh_timeout = 1;
  549. }
  550. /*
  551. *********************************************************************************************************
  552. * 函 数 名: MODH_Poll
  553. * 功能说明: 接收控制器指令. 1ms 响应时间。
  554. * 形 参: 无
  555. * 返 回 值: 0 表示无数据 1表示收到正确命令
  556. *********************************************************************************************************
  557. */
  558. uint8_t MODH_Poll(uint8_t sort)
  559. {
  560. uint16_t crc1;
  561. // 没有超多3.5个字节的时间,继续接受
  562. if (g_modh_timeout == 0) /* 超过3.5个字符时间后执行MODH_RxTimeOut()函数。全局变量 g_rtu_timeout = 1 */
  563. {
  564. return 0;
  565. }
  566. // 接受时间超过3.5个字节,一帧数据接受结束,进行处理
  567. g_modh_timeout = 0;
  568. // 接受字节数小于4,接受错误
  569. if (g_tModH.RxCount < 4)
  570. {
  571. g_tModH.RxCount = 0;
  572. rt_memset(g_tModH.RxBuf, 0, 64);
  573. return 0;
  574. }
  575. /* 计算CRC校验和 */
  576. if (g_tModH.RxCount > 0)
  577. {
  578. crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount - 2);
  579. }
  580. if (((uint8_t)crc1 != g_tModH.RxBuf[g_tModH.RxCount - 1]) || (((uint8_t)(crc1 >> 8) != g_tModH.RxBuf[g_tModH.RxCount - 2])))
  581. {
  582. g_tModH.RxCount = 0;
  583. return 0;
  584. }
  585. /* 分析应用层协议 */
  586. // 对数据进行处理
  587. // for(uint8_t a = 0; a < 12 ; a++)
  588. // {
  589. // rt_kprintf("%02X ",g_tModH.RxBuf[a]);
  590. // }
  591. MODH_AnalyzeApp(sort);//接收到数据经常 功能码处理 ->其实就处理了一个 03
  592. // err_ret:
  593. g_tModH.RxCount = 0; /* 必须清零计数器,方便下次帧同步 */
  594. return 1;
  595. }
  596. /*
  597. *********************************************************************************************************
  598. * 函 数 名: LOARH_Poll
  599. * 功能说明: 接收控制器指令. 1ms 响应时间。
  600. * 根据MODH_Poll又抄了一份给loar用
  601. * 形 参: 无
  602. * 返 回 值: 0 表示无数据 1表示收到正确命令
  603. *********************************************************************************************************
  604. */
  605. // void LOARH_Poll(void)
  606. //{
  607. //
  608. // uint16_t crc1;
  609. // //没有超多3.5个字节的时间,继续接受
  610. // if (g_modh_timeout == 0) /* 超过3.5个字符时间后执行MODH_RxTimeOut()函数。全局变量 g_rtu_timeout = 1 */
  611. // {
  612. // return;
  613. // }
  614. // //接受时间超过3.5个字节,一帧数据接受结束,进行处理
  615. // g_modh_timeout = 0;
  616. //
  617. // //接受字节数小于4,接受错误
  618. // if (g_tModH.RxCount < 4)
  619. // {
  620. // if (DBG_kprintf)
  621. // rt_kprintf("(g_tModH.RxCount < 4)");
  622. // return;
  623. // }
  624. //
  625. // if (g_tModH.RxBuf[0] != g_tModH.slaveaddr)
  626. // {
  627. // // rt_kprintf("g_tModH.slaveaddr:%0x,%0x,%0x,%0x,%0x\r",g_tModH.RxBuf[0] , g_tModH.RxBuf[1], g_tModH.RxBuf[2], g_tModH.RxBuf[3], g_tModH.RxBuf[4], g_tModH.RxBuf[5], g_tModH.RxBuf[6], g_tModH.RxBuf[7]);
  628. // // rt_kprintf("g_tModH.slaveaddr:%0x\r",g_tModH.slaveaddr);
  629. // g_tModH.RxCount = 0;
  630. // rt_kprintf("(g_tModH.RxBuf[0] != g_tModH.slaveaddr)");
  631. // return;
  632. // }
  633. //
  634. // /* 计算CRC校验和 */
  635. // crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount - 2);
  636. // if (((uint8_t)crc1 != g_tModH.RxBuf[g_tModH.RxCount - 1]) || (((uint8_t)(crc1 >> 8) != g_tModH.RxBuf[g_tModH.RxCount - 2])))
  637. // {
  638. // g_tModH.RxCount = 0;
  639. // return;
  640. // }
  641. // /* 分析应用层协议 */
  642. // //对数据进行处理
  643. // MODH_AnalyzeApp(9);
  644. //
  645. // // err_ret:
  646. // g_tModH.RxCount = 0; /* 必须清零计数器,方便下次帧同步 */
  647. // }
  648. /*
  649. *********************************************************************************************************
  650. * 函 数 名: MODH_Read_01H
  651. * 功能说明: 分析01H指令的应答数据
  652. * 形 参: 无
  653. * 返 回 值: 无
  654. *********************************************************************************************************
  655. */
  656. // static void MODH_Read_01H(void)
  657. //{
  658. // uint8_t *p;
  659. // if(g_tModH.RxBuf[0] == g_tModH.slaveaddr)
  660. // {
  661. // p = &g_tModH.RxBuf[3];
  662. // g_tVar.D01 = BEBufToUint16(p); p += 2; /* 寄存器 */
  663. // if(g_tModH.RxBuf[2]>2)
  664. // {g_tVar.D02 = BEBufToUint16(p); p += 2;} /* 寄存器 */
  665. // if(g_tModH.RxBuf[2]>4)
  666. // {g_tVar.D03 = BEBufToUint16(p); p += 2;} /* 寄存器 */
  667. // if(g_tModH.RxBuf[2]>6)
  668. // {g_tVar.D04 = BEBufToUint16(p); p += 2;} /* 寄存器 */
  669. // g_tModH.fAck01H = 1;
  670. // }
  671. // }
  672. /*
  673. *********************************************************************************************************
  674. * 函 数 名: MODH_Read_02H
  675. * 功能说明: 分析02H指令的应答数据
  676. * 形 参: 无
  677. * 返 回 值: 无
  678. *********************************************************************************************************
  679. */
  680. // static void MODH_Read_02H(void)
  681. //{
  682. // uint8_t *p;
  683. // p = &g_tModH.RxBuf[3];
  684. // g_tVar.T01 = BEBufToUint16(p); p += 2; /* 寄存器 */
  685. // if(g_tModH.RxBuf[2]>2)
  686. // {g_tVar.T02 = BEBufToUint16(p); p += 2;} /* 寄存器 */
  687. // if(g_tModH.RxBuf[2]>4)
  688. // {g_tVar.T03 = BEBufToUint16(p); p += 2;} /* 寄存器 */
  689. // g_tModH.fAck02H = 1;
  690. // }
  691. /*
  692. *********************************************************************************************************
  693. * 函 数 名: MODH_Read_04H
  694. * 功能说明: 分析04H指令的应答数据
  695. * 形 参: 无
  696. * 返 回 值: 无
  697. *********************************************************************************************************
  698. */
  699. // static void MODH_Read_04H(void)
  700. //{
  701. // uint8_t *p;
  702. // p = &g_tModH.RxBuf[3];
  703. // g_tVar.A01 = BEBufToUint16(p); p += 2; /* 寄存器 */
  704. // g_tModH.fAck04H = 1;
  705. // }
  706. /*
  707. *********************************************************************************************************
  708. * 函 数 名: MODH_Read_05H
  709. * 功能说明: 分析05H指令的应答数据
  710. * 形 参: 无
  711. * 返 回 值: 无
  712. *********************************************************************************************************
  713. */
  714. // static void MODH_Read_05H(void)
  715. //{
  716. // g_tModH.fAck05H = 1; /* 接收到应答 */
  717. // }
  718. /*
  719. *********************************************************************************************************
  720. * 函 数 名: MODH_Read_06H
  721. * 功能说明: 分析06H指令的应答数据
  722. * 形 参: 无
  723. * 返 回 值: 无
  724. *********************************************************************************************************
  725. */
  726. // static void MODH_Read_06H(void)
  727. //{
  728. // g_tModH.fAck06H = 1; /* 接收到应答 */
  729. // }
  730. /*
  731. *********************************************************************************************************
  732. * 函 数 名: MODH_Read_03H
  733. * 功能说明: 分析03H指令的应答数据
  734. * 形 参: 无
  735. * 返 回 值: 无
  736. *********************************************************************************************************
  737. */
  738. extern uint16_t Read_data[MAX_SENSOR_NUM * 2];
  739. extern Sensor sensor[MAX_SENSOR_NUM];
  740. #define GPRS_ADDR 0x99
  741. void MODH_Read_03H(uint8_t sort)
  742. {
  743. uint8_t *p;
  744. p = &g_tModH.RxBuf[3];
  745. if(sort != GPRS_ADDR)
  746. {
  747. if (g_tModH.RxBuf[0] == sensor[sort].sensor_addr && g_tModH.RxBuf[2] == sensor[sort].count * 2)
  748. {
  749. for (uint8_t a = 1; a <= g_tModH.RxBuf[2]; a++)
  750. {
  751. if (a % 2 == 0)
  752. {
  753. Read_data[(a / 2) - 1] = BEBufToUint16(p);
  754. p += 2;
  755. g_tModH.RxCount += 2;
  756. }
  757. }
  758. g_tModH.fAck03H = 1;
  759. }
  760. else
  761. {
  762. g_tModH.fAck03H = 0;
  763. // rt_kprintf("Read_03H check fail\n");
  764. }
  765. }
  766. else
  767. {
  768. if (g_tModH.RxBuf[0] == GPRS_ADDR && g_tModH.RxBuf[1] == 0x03)
  769. {
  770. for (uint8_t a = 1; a <= g_tModH.RxBuf[2]; a++)
  771. {
  772. if (a % 2 == 0)
  773. {
  774. Read_data[(a / 2) - 1] = BEBufToUint16(p);
  775. p += 2;
  776. }
  777. }
  778. g_tModH.fAck03H = 1;
  779. }
  780. else
  781. {
  782. g_tModH.fAck03H = 0;
  783. // rt_kprintf("Read_03H check fail\n");
  784. }
  785. }
  786. }
  787. /*
  788. *********************************************************************************************************
  789. * 函 数 名: MODH_Read_10H
  790. * 功能说明: 分析10H指令的应答数据
  791. * 形 参: 无
  792. * 返 回 值: 无
  793. *********************************************************************************************************
  794. */
  795. // void MODH_Read_10H(void)
  796. //{
  797. // g_tModH.fAck10H = 1; /* 接收到应答 */
  798. // }
  799. /*
  800. *********************************************************************************************************
  801. * 函 数 名: MODH_ReadParam_01H
  802. * 功能说明: 单个参数. 通过发送01H指令实现,发送之后,等待从机应答。
  803. * 形 参: 无
  804. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  805. *********************************************************************************************************
  806. */
  807. // uint8_t MODH_ReadParam_01H(uint16_t slaveAddr,uint16_t _reg, uint16_t _num)
  808. //{
  809. // int32_t time1;
  810. // uint8_t i;
  811. //
  812. // g_tModH.slaveaddr = slaveAddr;
  813. // for (i = 0; i < NUM; i++)
  814. // {
  815. // MODH_Send01H (slaveAddr, _reg, _num); /* 发送命令 */
  816. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  817. //
  818. // while (1) /* 等待应答,超时或接收到应答则break */
  819. // {
  820. // MODH_Poll();
  821. //
  822. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  823. // {
  824. // break; /* 通信超时了 */
  825. // }
  826. //
  827. // if (g_tModH.fAck01H > 0)
  828. // {
  829. // break; /* 接收到应答 */
  830. // }
  831. // }
  832. //
  833. // if (g_tModH.fAck01H > 0)
  834. // {
  835. // break; /* 循环NUM次,如果接收到命令则break循环 */
  836. // }
  837. // }
  838. //
  839. // if (g_tModH.fAck01H == 0)
  840. // {
  841. // return 0;
  842. // }
  843. // else
  844. // {
  845. // return 1; /* 01H 读成功 */
  846. // }
  847. // }
  848. /*
  849. *********************************************************************************************************
  850. * 函 数 名: MODH_ReadParam_02H
  851. * 功能说明: 单个参数. 通过发送02H指令实现,发送之后,等待从机应答。
  852. * 形 参: 无
  853. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  854. *********************************************************************************************************
  855. */
  856. // uint8_t MODH_ReadParam_02H(uint16_t slaveAddr,uint16_t _reg, uint16_t _num)
  857. //{
  858. // int32_t time1;
  859. // uint8_t i;
  860. //
  861. // g_tModH.slaveaddr = slaveAddr;
  862. // for (i = 0; i < NUM; i++)
  863. // {
  864. // MODH_Send02H (slaveAddr, _reg, _num);
  865. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  866. //
  867. // while (1)
  868. // {
  869. // MODH_Poll();
  870. //
  871. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  872. // {
  873. // break; /* 通信超时了 */
  874. // }
  875. //
  876. // if (g_tModH.fAck02H > 0)
  877. // {
  878. // break;
  879. // }
  880. // }
  881. //
  882. // if (g_tModH.fAck02H > 0)
  883. // {
  884. // break;
  885. // }
  886. // }
  887. //
  888. // if (g_tModH.fAck02H == 0)
  889. // {
  890. // return 0;
  891. // }
  892. // else
  893. // {
  894. // return 1; /* 02H 读成功 */
  895. // }
  896. // }
  897. /*
  898. *********************************************************************************************************
  899. * 函 数 名: MODH_ReadParam_03H
  900. * 功能说明: 单个参数. 通过发送03H指令实现,发送之后,等待从机应答。
  901. * 形 参: 无
  902. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  903. *********************************************************************************************************
  904. */
  905. uint8_t MODH_ReadParam_03H(uint16_t slaveAddr, uint16_t _reg, uint16_t _num, uint8_t sort)
  906. {
  907. uint8_t i, count = 0;
  908. g_tModH.slaveaddr = slaveAddr;
  909. for (i = 0; i < NUM; i++)
  910. {
  911. MODH_Send03H(slaveAddr, _reg, _num);
  912. while (1)
  913. {
  914. MODH_Poll(sort);
  915. if (count++ > 50)
  916. {
  917. break;
  918. rt_kprintf("Waiting for data timeout\r\n");
  919. }
  920. if (g_tModH.fAck03H == 1)
  921. {
  922. break;
  923. }
  924. rt_thread_mdelay(10);
  925. }
  926. }
  927. if (g_tModH.fAck03H == 0)
  928. {
  929. // if(DBG_kprintf)rt_kprintf("通信超时了 ");
  930. return 0; /* 通信超时了 */
  931. }
  932. else
  933. {
  934. // if(DBG_kprintf)rt_kprintf("写入03H参数成功");
  935. return 1; /* 写入03H参数成功 */
  936. }
  937. }
  938. /*
  939. *********************************************************************************************************
  940. * 函 数 名: MODH_ReadParam_04H
  941. * 功能说明: 单个参数. 通过发送04H指令实现,发送之后,等待从机应答。
  942. * 形 参: 无
  943. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  944. *********************************************************************************************************
  945. */
  946. // uint8_t MODH_ReadParam_04H(uint16_t slaveAddr,uint16_t _reg, uint16_t _num)
  947. //{
  948. // int32_t time1;
  949. // uint8_t i;
  950. //
  951. // g_tModH.slaveaddr = slaveAddr;
  952. // for (i = 0; i < NUM; i++)
  953. // {
  954. // MODH_Send04H (slaveAddr, _reg, _num);
  955. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  956. //
  957. // while (1)
  958. // {
  959. // MODH_Poll();
  960. //
  961. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  962. // {
  963. // break; /* 通信超时了 */
  964. // }
  965. //
  966. // if (g_tModH.fAck04H > 0)
  967. // {
  968. // break;
  969. // }
  970. // }
  971. //
  972. // if (g_tModH.fAck04H > 0)
  973. // {
  974. // break;
  975. // }
  976. // }
  977. //
  978. // if (g_tModH.fAck04H == 0)
  979. // {
  980. // return 0; /* 通信超时了 */
  981. // }
  982. // else
  983. // {
  984. // return 1; /* 04H 读成功 */
  985. // }
  986. // }
  987. /*
  988. *********************************************************************************************************
  989. * 函 数 名: MODH_WriteParam_05H
  990. * 功能说明: 单个参数. 通过发送05H指令实现,发送之后,等待从机应答。
  991. * 形 参: 无
  992. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  993. *********************************************************************************************************
  994. */
  995. // uint8_t MODH_WriteParam_05H(uint16_t slaveAddr,uint16_t _reg, uint16_t _value)
  996. //{
  997. // int32_t time1;
  998. // uint8_t i;
  999. //
  1000. // g_tModH.slaveaddr = slaveAddr;
  1001. // for (i = 0; i < NUM; i++)
  1002. // {
  1003. // MODH_Send05H (slaveAddr, _reg, _value);
  1004. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  1005. //
  1006. // while (1)
  1007. // {
  1008. // MODH_Poll();
  1009. //
  1010. // /* 超时大于 TIMEOUT,则认为异常 */
  1011. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  1012. // {
  1013. // break; /* 通信超时了 */
  1014. // }
  1015. //
  1016. // if (g_tModH.fAck05H > 0)
  1017. // {
  1018. // break;
  1019. // }
  1020. // }
  1021. //
  1022. // if (g_tModH.fAck05H > 0)
  1023. // {
  1024. // break;
  1025. // }
  1026. // }
  1027. //
  1028. // if (g_tModH.fAck05H == 0)
  1029. // {
  1030. // return 0; /* 通信超时了 */
  1031. // }
  1032. // else
  1033. // {
  1034. // return 1; /* 05H 写成功 */
  1035. // }
  1036. // }
  1037. /*
  1038. *********************************************************************************************************
  1039. * 函 数 名: MODH_WriteParam_06H
  1040. * 功能说明: 单个参数. 通过发送06H指令实现,发送之后,等待从机应答。循环NUM次写命令
  1041. * 形 参: 无
  1042. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  1043. *********************************************************************************************************
  1044. */
  1045. // uint8_t MODH_WriteParam_06H(uint16_t slaveAddr,uint16_t _reg, uint16_t _value)
  1046. //{
  1047. // int32_t time1;
  1048. // uint8_t i;
  1049. //
  1050. // g_tModH.slaveaddr = slaveAddr;
  1051. // for (i = 0; i < NUM; i++)
  1052. // {
  1053. // MODH_Send06H (slaveAddr, _reg, _value);
  1054. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  1055. //
  1056. // while (1) //若等待100ms没有回应,则退出,通讯超时
  1057. // {
  1058. //
  1059. // MODH_Poll();
  1060. //
  1061. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  1062. // {
  1063. // break;
  1064. // }
  1065. //
  1066. // if (g_tModH.fAck06H > 0)
  1067. // {
  1068. // break;
  1069. // }
  1070. // }
  1071. //
  1072. // if (g_tModH.fAck06H > 0)
  1073. // {
  1074. // break;
  1075. // }
  1076. // }
  1077. //
  1078. // if (g_tModH.fAck06H == 0)
  1079. // {
  1080. // return 0; /* 通信超时了 */
  1081. // }
  1082. // else
  1083. // {
  1084. // return 1; /* 写入06H参数成功 */
  1085. // }
  1086. // }
  1087. /*
  1088. *********************************************************************************************************
  1089. * 函 数 名: MODH_WriteParam_10H
  1090. * 功能说明: 单个参数. 通过发送10H指令实现,发送之后,等待从机应答。循环NUM次写命令
  1091. * 形 参: 无
  1092. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  1093. *********************************************************************************************************
  1094. */
  1095. // uint8_t MODH_WriteParam_10H(uint16_t slaveAddr,uint16_t _reg, uint8_t _num, const uint16_t *_buf)
  1096. //{
  1097. // int32_t time1;
  1098. // uint8_t i;
  1099. //
  1100. // g_tModH.slaveaddr = slaveAddr;
  1101. // for (i = 0; i < NUM; i++)
  1102. // {
  1103. // MODH_Send10H(slaveAddr, _reg, _num, _buf);
  1104. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  1105. //
  1106. // while (1)
  1107. // {
  1108. // MODH_Poll();
  1109. //
  1110. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  1111. // {
  1112. // break;
  1113. // }
  1114. //
  1115. // if (g_tModH.fAck10H > 0)
  1116. // {
  1117. // break;
  1118. // }
  1119. // }
  1120. //
  1121. // if (g_tModH.fAck10H > 0)
  1122. // {
  1123. // break;
  1124. // }
  1125. // }
  1126. //
  1127. // if (g_tModH.fAck10H == 0)
  1128. // {
  1129. // return 0; /* 通信超时了 */
  1130. // }
  1131. // else
  1132. // {
  1133. // return 1; /* 写入10H参数成功 */
  1134. // }
  1135. // }
  1136. /*
  1137. *********************************************************************************************************
  1138. * 函 数 名: MODH_Poll_add(非本库原版,后续添加)
  1139. * 功能说明: 接收控制器指令. 1ms 响应时间,与void MODH_Poll(void)接收字节数的差别,地址为0
  1140. * 形 参: 无
  1141. * 返 回 值: 0 表示无数据 1表示收到正确命令
  1142. *********************************************************************************************************
  1143. */
  1144. // void MODH_Poll_add(void)
  1145. //{
  1146. // uint16_t crc1;
  1147. // //没有超多3.5个字节的时间,继续接受
  1148. // if (g_modh_timeout == 0) /* 超过3.5个字符时间后执行MODH_RxTimeOut()函数。全局变量 g_rtu_timeout = 1 */
  1149. // {
  1150. // /* 没有超时,继续接收。不要清零 g_tModH.RxCount */
  1151. // return ;
  1152. // }
  1153. // //接受时间超过3.5个字节,一帧数据接受结束,进行处理
  1154. // g_modh_timeout = 0;
  1155. //
  1156. // //接受字节数小于2,接受错误
  1157. // if (g_tModH.RxCount < 2)
  1158. // {
  1159. // return;
  1160. // }
  1161. //
  1162. // if(g_tModH.RxBuf[0] != 0x00)
  1163. // {
  1164. //// printf("g_tModH.slaveaddr:%0x,%0x,%0x,%0x,%0x\r",g_tModH.RxBuf[0] , g_tModH.RxBuf[1], g_tModH.RxBuf[2], g_tModH.RxBuf[3], g_tModH.RxBuf[4], g_tModH.RxBuf[5], g_tModH.RxBuf[6], g_tModH.RxBuf[7]);
  1165. //// printf("g_tModH.slaveaddr:%0x\r",g_tModH.slaveaddr);
  1166. // g_tModH.RxCount = 0;
  1167. // return;
  1168. // }
  1169. //
  1170. // /* 计算CRC校验和 */
  1171. // crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount-2);
  1172. // if (((uint8_t)crc1 != g_tModH.RxBuf[g_tModH.RxCount-1])||(((uint8_t)(crc1>>8) != g_tModH.RxBuf[g_tModH.RxCount-2])))
  1173. // {g_tModH.RxCount = 0;return;}
  1174. // /* 分析应用层协议 */
  1175. // //对数据进行处理
  1176. // MODH_AnalyzeApp();
  1177. //
  1178. ////err_ret:
  1179. // g_tModH.RxCount = 0; /* 必须清零计数器,方便下次帧同步 */
  1180. //}
  1181. /*
  1182. *********************************************************************************************************
  1183. * 函 数 名: MODH_Send10_add(非本库原版,后续添加)
  1184. * 功能说明: 发送10H指令修改传感器地址
  1185. * 形 参: _addr : 从站地址
  1186. * 返 回 值: 无
  1187. *********************************************************************************************************
  1188. */
  1189. // void MODH_Send10_add(uint8_t _addr)
  1190. //{
  1191. //
  1192. // g_tModH.fAck10H = 0; //将应答标志位置0
  1193. // g_tModH.TxCount = 0;
  1194. // g_tModH.TxBuf[g_tModH.TxCount++] = 00; /* 广播地址 */
  1195. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x10; /*10命令 */
  1196. // g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 寄存器编号 高字节 */
  1197. //
  1198. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  1199. // }
  1200. /*
  1201. *********************************************************************************************************
  1202. * 函 数 名: MODH_Send20_inquire(非本库原版,后续添加)
  1203. * 功能说明: 发送20H指令查询传感器地址
  1204. * 返 回 值: 无
  1205. *********************************************************************************************************
  1206. */
  1207. // void MODH_Send20_inquire(void)
  1208. //{
  1209. //
  1210. // g_tModH.fAck20inquire = 0; //将应答标志位置0
  1211. // g_tModH.TxCount = 0;
  1212. // g_tModH.TxBuf[g_tModH.TxCount++] = 00; /* 广播地址 */
  1213. // g_tModH.TxBuf[g_tModH.TxCount++] = 0x20; /*10命令 */
  1214. //
  1215. // MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */
  1216. // }
  1217. /*
  1218. *********************************************************************************************************
  1219. * 函 数 名: MODH_Poll_EE
  1220. * 功能说明: 接收EE指令
  1221. * 形 参: 无
  1222. * 返 回 值: 0 表示无数据 1表示收到正确命令
  1223. *********************************************************************************************************
  1224. */
  1225. // void MODH_Poll_EE(void)
  1226. //{
  1227. // uint16_t crc1;
  1228. // //没有超多3.5个字节的时间,继续接受
  1229. // if (g_modh_timeout == 0) /* 超过3.5个字符时间后执行MODH_RxTimeOut()函数。全局变量 g_rtu_timeout = 1 */
  1230. // {
  1231. // /* 没有超时,继续接收。不要清零 g_tModH.RxCount */
  1232. // return ;
  1233. // }
  1234. // //接受时间超过3.5个字节,一帧数据接受结束,进行处理
  1235. // g_modh_timeout = 0;
  1236. //
  1237. // //接受字节数小于4,接受错误
  1238. // if (g_tModH.RxCount < 2)
  1239. // {
  1240. // return;
  1241. // }
  1242. //
  1243. // if(g_tModH.RxBuf[0] != g_tModH.slaveaddr)
  1244. // {
  1245. //// printf("g_tModH.slaveaddr:%0x,%0x,%0x,%0x,%0x\r",g_tModH.RxBuf[0] , g_tModH.RxBuf[1], g_tModH.RxBuf[2], g_tModH.RxBuf[3], g_tModH.RxBuf[4], g_tModH.RxBuf[5], g_tModH.RxBuf[6], g_tModH.RxBuf[7]);
  1246. //// printf("g_tModH.slaveaddr:%0x\r",g_tModH.slaveaddr);
  1247. // g_tModH.RxCount = 0;
  1248. // return;
  1249. // }
  1250. //
  1251. // /* 计算CRC校验和 */
  1252. // crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount-2);
  1253. // if (((uint8_t)crc1 != g_tModH.RxBuf[g_tModH.RxCount-1])||(((uint8_t)(crc1>>8) != g_tModH.RxBuf[g_tModH.RxCount-2])))
  1254. // {g_tModH.RxCount = 0;return;}
  1255. // /* 分析应用层协议 */
  1256. // //对数据进行处理
  1257. // MODH_AnalyzeApp();
  1258. //
  1259. ////err_ret:
  1260. // g_tModH.RxCount = 0; /* 必须清零计数器,方便下次帧同步 */
  1261. //}
  1262. /*
  1263. *********************************************************************************************************
  1264. * 函 数 名: MODH_Writ_10_add(非本库原版,后续添加)
  1265. * 功能说明: 传感器写地址函数
  1266. * 形 参: 无
  1267. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  1268. *********************************************************************************************************
  1269. */
  1270. // uint8_t MODH_Writ_10_add(uint16_t slaveAddr)
  1271. //{
  1272. // int32_t time1;
  1273. //
  1274. // g_tModH.slaveaddr = slaveAddr;
  1275. //
  1276. // MODH_Send10_add(slaveAddr);
  1277. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  1278. //
  1279. // while (1)
  1280. // {
  1281. // MODH_Poll_add();
  1282. //
  1283. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  1284. // {
  1285. // break;
  1286. // }
  1287. //
  1288. // if (g_tModH.fAck10add > 0)
  1289. // {
  1290. // break;
  1291. // }
  1292. // }
  1293. //
  1294. // if (g_tModH.fAck10add == 0)
  1295. // {
  1296. // return 0; /* 通信超时了 */
  1297. // }
  1298. // else
  1299. // {
  1300. // return 1; /* 写入10H参数成功 */
  1301. // }
  1302. // }
  1303. /*
  1304. *********************************************************************************************************
  1305. * 函 数 名: MODH_Writ_20_inquire(非本库原版,后续添加)
  1306. * 功能说明: 查询传感器地址
  1307. * 形 参: 无
  1308. * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝)
  1309. *********************************************************************************************************
  1310. */
  1311. // uint8_t MODH_Writ_20_inquire(void)
  1312. //{
  1313. // int32_t time1;
  1314. //
  1315. // MODH_Send20_inquire();
  1316. // time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */
  1317. //
  1318. // while (1)
  1319. // {
  1320. // MODH_Poll_add();
  1321. //
  1322. // if (bsp_CheckRunTime(time1) > TIMEOUT)
  1323. // {
  1324. // break;
  1325. // }
  1326. //
  1327. // if (g_tModH.fAck20inquire > 0)
  1328. // {
  1329. // break;
  1330. // }
  1331. // }
  1332. //
  1333. // if (g_tModH.fAck20inquire == 0)
  1334. // {
  1335. // return 0; /* 通信超时了 */
  1336. // }
  1337. // else
  1338. // {
  1339. // return 1; /* 写入10H参数成功 */
  1340. // }
  1341. // }
  1342. void MODBUS_Init(void)
  1343. {
  1344. RS485_ReceiveData = MODH_ReciveNew;
  1345. }
  1346. INIT_APP_EXPORT(MODBUS_Init);