modbus_app.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "board.h"
  2. #include "modbus_encoder.h"
  3. #include "modbus_slave.h"
  4. #include "modbus_master.h"
  5. #include "variable.h"
  6. #include <string.h>
  7. #define MODBUS_APP_NUMBER 1
  8. typedef struct
  9. {
  10. unsigned char uart_no; //串口号
  11. unsigned char modbus_dir; //modbus方向,0是从机,1是主机
  12. //当做为从机时,master_or_slave保存modbus_slave_t 对象指针
  13. //当做为主机时,master_or_slave保存modbus_master_t 对象指针
  14. void *master_or_slave; //主站信息
  15. unsigned char count;
  16. unsigned char step; //状态步
  17. unsigned char rx_buffer[520];
  18. unsigned char tx_buffer[128];
  19. } modbus_status_t;
  20. static modbus_slave_t slaves[2];
  21. //modbus协议的一些状态信息
  22. static modbus_status_t modbus_status[MODBUS_APP_NUMBER] = {
  23. { 1, 0, &slaves[0], 2 }, //组1,ID1,串口3主站
  24. //{ 1, 0, &slaves[0], 1 }, //组0,ID2,串口2,从站
  25. };
  26. /**
  27. * 系统默认的回调函数
  28. *
  29. * @author lxz (2019/6/12/周三)
  30. *
  31. * @param address
  32. * @param number
  33. */
  34. static void slave1_on_comm(
  35. unsigned char id,
  36. unsigned char cmd,
  37. unsigned short address,
  38. unsigned short number) {
  39. //通知软件需要退出进入bootloader
  40. if (cmd == 0x23)
  41. {
  42. extern void app_save_parameter(void);
  43. //先保存参数
  44. //设置标志
  45. hw_noinit_write(0, 0xA5A5A5A5);
  46. //设置ID
  47. hw_noinit_write(3, id);
  48. INTX_DISABLE();
  49. //软件复位
  50. Sys_Soft_Reset();
  51. }
  52. }
  53. /**
  54. * modbus应用环境的初始化,包括了一些数据域的初始化注册
  55. *
  56. * @author lxz (2019/5/17/周五)
  57. */
  58. void mosbus_app_init(void) {
  59. modbus_slave_t *slave = &slaves[0];
  60. hw_noinit_write(1, 1);
  61. hw_noinit_write(3, 1);
  62. hw_noinit_write(5, 1);
  63. //从站初始化
  64. memset(&slaves[0], 0, sizeof(slaves));
  65. slave->id = 1; //设置从站ID
  66. slave->on_comm = slave1_on_comm; //设置从站通讯的回调函数
  67. //升级系统必须的命令
  68. modbus_slave_add_dataarea(slave,
  69. 0xFE, //数据类型为系统定制,升级时使用
  70. 0, //映射开始地址为0
  71. 512, //数据单位个数
  72. 0 //数据所在地址
  73. );
  74. //添加从站有效的数据域信息
  75. modbus_slave_add_dataarea(slave,
  76. 0x01, //数据类型为位
  77. 0, //映射开始地址为0
  78. MIDDLE_COILS_NUMBER, //数据单位个数
  79. (unsigned char *)&middle_coils[0] //数据所在地址
  80. );
  81. modbus_slave_add_dataarea(slave,
  82. 0x01, //数据类型为位
  83. 0x0800, //映射开始地址为0x800,用于兼容台达DVP协议的M码地址
  84. MIDDLE_COILS_NUMBER, //数据单位个数
  85. (unsigned char *)&middle_coils[0] //数据所在地址
  86. );
  87. modbus_slave_add_dataarea(slave,
  88. 0x03, //数据类型为16位数值
  89. 0x1000, //映射开始地址为0x1000,用于兼容台达DVP协议的D码地址
  90. USER_DATA_NUMBER, //数据单位个数
  91. (unsigned char *)&user_datas[0] //数据所在地址
  92. );
  93. modbus_slave_add_dataarea(slave,
  94. 0x03, //数据类型为16位数值
  95. 0, //映射开始地址为0x1000,用于兼容台达DVP协议的D码地址
  96. USER_DATA_NUMBER, //数据单位个数
  97. (unsigned char *)&user_datas[0] //数据所在地址
  98. );
  99. /* modbus_slave_add_dataarea(slave,
  100. 0x03, //数据类型为16位数值
  101. 0x9000, //映射开始地址为0x1000,用于兼容台达DVP协议的D码地址
  102. 5000 - 4096, //数据单位个数
  103. (unsigned char *)&user_datas[4096] //数据所在地址
  104. );*/
  105. //WIFI一些对应的通讯缓冲
  106. slave = &slaves[1];
  107. slave->id = 0x7F;
  108. //升级系统必须的命令
  109. modbus_slave_add_dataarea(slave,
  110. 0xFE, //数据类型为系统定制,升级时使用
  111. 0, //映射开始地址为0
  112. 512, //数据单位个数
  113. 0 //数据所在地址
  114. );
  115. modbus_slave_add_dataarea(slave,
  116. 0x01, //数据类型为系统定制,升级时使用
  117. 0x00, //映射开始地址为0
  118. 24, //数据单位个数
  119. (unsigned char *)&middle_coils[1000 >> 3] //数据所在地址
  120. );
  121. modbus_slave_add_dataarea(slave,
  122. 0x03, //数据类型为系统定制,升级时使用
  123. 0x00, //映射开始地址为0
  124. 128, //数据单位个数
  125. (unsigned char *)&user_datas[1600] //数据所在地址
  126. );
  127. }
  128. /**
  129. * modbus 从台应用代码
  130. *
  131. * @author lxz (2019/5/17/周五)
  132. *
  133. * @param status
  134. */
  135. static void modbus_slave_app(modbus_status_t *status) {
  136. int length;
  137. int index = 0;
  138. modbus_encoder_t *encoder;
  139. switch (status->step) {
  140. case 0:
  141. hw_dma_uart_begin_read(status->uart_no, &status->rx_buffer[0], sizeof(status->rx_buffer));
  142. status->step++;
  143. break;
  144. case 1:
  145. length = hw_dma_uart_read_finish(status->uart_no);
  146. if (length > 0) {
  147. status->step = 0;
  148. encoder = modbus_encoder_match(status->rx_buffer, length);
  149. if (encoder != (void *)0) {
  150. length = encoder->decode(&status->rx_buffer[0], &status->rx_buffer[0], length);
  151. if (length > 0) {
  152. while (index < status->count) {
  153. length = modbus_slave_run(
  154. &((modbus_slave_t *)status->master_or_slave)[index],
  155. &status->tx_buffer[0],
  156. &status->rx_buffer[0], encoder->type);
  157. if (length > 0) {
  158. length = encoder->encode(&status->tx_buffer[0], &status->tx_buffer[0], length);
  159. if (length > 0) {
  160. hw_dma_uart_begin_write(status->uart_no, (const char *)&status->tx_buffer[0], length);
  161. status->step = 2;
  162. }
  163. break;
  164. }
  165. index++;
  166. }
  167. }
  168. }
  169. }
  170. break;
  171. case 2:
  172. if (hw_dma_uart_write_finish(status->uart_no)) {
  173. status->step = 0;
  174. }
  175. break;
  176. }
  177. }
  178. /**
  179. * modbus应用的循环运行函数,根据自己需求编写
  180. *
  181. * @author lxz (2019/5/17/周五)
  182. *
  183. * @param void
  184. */
  185. void modbus_app_proc(void) {
  186. int index = 0;
  187. while (index < sizeof(modbus_status) / sizeof(modbus_status_t)) {
  188. if (modbus_status[index].modbus_dir == 0) {
  189. modbus_slave_app(&modbus_status[index]);
  190. }
  191. index++;
  192. }
  193. }