Modbus.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. #include "includes.h"
  2. unsigned char g_ucModbusRefreshEN;
  3. unsigned char g_ucModbusRefreshSHUTDOWN;
  4. unsigned short g_ucRegNumCount;
  5. unsigned short g_ucModbusRefreshTimeOut;
  6. //char SendData[850];
  7. // SUT_DEVICE--------->SUT_DEVICE_READ
  8. unsigned char device_vailable[MODBUS_REG_NUM_MAX];
  9. unsigned char SelfChek;
  10. SUT_DOWN Device_Down; //下行设置
  11. SUT_UP Device_Up; //上行汇报
  12. SUT_DEVICE_READ sut_device_read[MODBUS_REG_NUM_MAX]; //32
  13. SUT_DEVICE_WRITE sut_device_write;
  14. SUT_SYS_STATUS sut_sys_status;
  15. /**********************************************************************************************************
  16. *初始化寄存器列表
  17. ************************************************************************************************************/
  18. void Reg_Init()
  19. {
  20. unsigned char i,j;
  21. j=1;
  22. memset(sut_device_read,0,sizeof(SUT_DEVICE_READ)*MODBUS_REG_NUM_MAX);
  23. // /****************由鉴权工具下发可用从机个数****SlaveNum************/
  24. // SlaveNum=32;//测试
  25. for(i=0;i<SlaveNum;i++){
  26. sut_device_read[i].Addr=j++;
  27. }
  28. }
  29. /**********************************************************************************************************
  30. *更新寄存器列表参数
  31. ************************************************************************************************************/
  32. void ModbusRefreshValue(void)
  33. {
  34. static char chekcnt=0;
  35. unsigned char i;
  36. unsigned short cnt;
  37. /************************************自检********************************************/
  38. if(SelfChek==0){
  39. //存在一个问题第一次无法扫到第一个从机。不过后续都能扫描到第一个从机。
  40. if(g_ucModbusRefreshEN == 1)
  41. {
  42. g_ucModbusRefreshEN = 0;
  43. g_ucModbusRefreshTimeOut = 0;
  44. g_ucRegNumCount++; //
  45. if((MODBUS_REG_NUM_MAX - 1) < g_ucRegNumCount){
  46. //置位可上传FLAG
  47. //sut_sys_status.OnceFlag=1;
  48. g_ucRegNumCount = 0;
  49. //完成一次读取 需要一个标志位表示一次读取完成
  50. chekcnt++;
  51. if(chekcnt==4)SelfChek=1;
  52. }
  53. ModbusCmdReadOneValue(sut_device_read[g_ucRegNumCount].Addr); //从机地址
  54. }else
  55. {
  56. if(g_ucModbusRefreshTimeOut > 3)//
  57. {
  58. g_ucModbusRefreshEN = 1;
  59. g_ucModbusRefreshTimeOut = 0;
  60. //printf("time out\r\n");
  61. }
  62. g_ucModbusRefreshTimeOut++;
  63. }
  64. }else{
  65. if(g_ucModbusRefreshEN == 1)
  66. {
  67. g_ucModbusRefreshEN = 0;
  68. g_ucModbusRefreshTimeOut = 0;
  69. g_ucRegNumCount++; //实际个数
  70. while(device_vailable[g_ucRegNumCount]!=1){
  71. g_ucRegNumCount++;
  72. }
  73. if((MODBUS_REG_NUM_MAX - 1) < g_ucRegNumCount) {
  74. //置位可上传FLAG
  75. sut_sys_status.OnceFlag=1;
  76. g_ucRegNumCount = 0;
  77. //完成一次读取 需要一个标志位表示一次读取完成
  78. }
  79. ModbusCmdReadOneValue(sut_device_read[g_ucRegNumCount].Addr); //从机地址
  80. }else
  81. {
  82. if(g_ucModbusRefreshTimeOut > 3)//
  83. {
  84. g_ucModbusRefreshEN = 1;
  85. g_ucModbusRefreshTimeOut = 0;
  86. //printf("time out\r\n");
  87. }
  88. g_ucModbusRefreshTimeOut++;
  89. }
  90. }
  91. }
  92. /**********************************************************************************************************
  93. ModbusCmdReadOneValue()
  94. 发送请求,读取MODBUS设备指定一个寄存器地址的参数
  95. ADDR:代表寄存器列表里第几个元素
  96. 查询指令 AA BB CMD LEN ADDR 01 CRC1 CRC2 DD 55 //10
  97. ************************************************************************************************************/
  98. //SUT_DEVICE Devices[count];
  99. void ModbusCmdReadOneValue(unsigned short addr)
  100. {
  101. unsigned short CRC16;
  102. unsigned char Pack[10],i;
  103. unsigned char temp[3];
  104. Pack[0]=0xAA;
  105. Pack[1]=0xBB;
  106. Pack[2]=HOLDINGREG;
  107. Pack[3]=0x0A;
  108. Pack[4] =addr;
  109. Pack[5] =0x01;
  110. CRC16=crc16_calc(0xffff,Pack,6);
  111. Pack[6] = (unsigned char)(CRC16 & 0xff);
  112. Pack[7] = (unsigned char)(CRC16 >> 8);
  113. Pack[8]=0xdd;
  114. Pack[9]=0x55;
  115. // if(addr==1){
  116. // for(i=0;i<10;i++){
  117. // FEED_EXTWATCHDOG();
  118. // sprintf(temp, "%02x",Pack[i]);
  119. // SlwTrace(INF,temp);
  120. // }
  121. //}
  122. RS485_DIR_HIGH;
  123. for(i=0;i<10;i++)
  124. {
  125. USART_SendData(USART1,Pack[i]);
  126. while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  127. }
  128. RS485_DIR_LOW;
  129. }
  130. /**********************************************************************************************************
  131. *向MODBUS设备发送配置参数命令
  132. 数据格式
  133. 0xcc 0xdd cmd len(1) addr(1) data(4) crc(2) DD 55 //13
  134. ************************************************************************************************************/
  135. //SUT_DOWN.Devices[2];
  136. void ModbusCmdSetValue(SUT_DEVICE_WRITE *pMsg)
  137. {
  138. unsigned short crc,CRC16;
  139. unsigned char Pack[13],i;
  140. unsigned char temp=0x00;
  141. char buf[3];
  142. Pack[0]=0xCC;
  143. Pack[1]=0xDD;
  144. Pack[2] = WRITESINGLEREG;
  145. Pack[3]=sizeof(Pack);
  146. Pack[4] = pMsg->Addr;
  147. // 转化为4个字节发送
  148. temp=temp |((pMsg->STU_RGB[0].R)<<5);
  149. temp=temp |((pMsg->STU_RGB[0].G)<<6);
  150. temp=temp |((pMsg->STU_RGB[0].B)<<7);
  151. temp=temp | ((pMsg->STU_RGB[1].R)<<1);
  152. temp=temp |((pMsg->STU_RGB[1].G)<<2);
  153. temp=temp |((pMsg->STU_RGB[1].B)<<3);
  154. Pack[5]=temp;
  155. temp=0x00;
  156. temp=temp |((pMsg->STU_RGB[2].R)<<5);
  157. temp=temp |((pMsg->STU_RGB[2].G)<<6);
  158. temp=temp |((pMsg->STU_RGB[2].B)<<7);
  159. temp=temp | ((pMsg->STU_RGB[3].R)<<1);
  160. temp=temp |((pMsg->STU_RGB[3].G)<<2);
  161. temp=temp |((pMsg->STU_RGB[3].B)<<3);
  162. Pack[6]=temp;
  163. temp=0x00;
  164. temp=temp |((pMsg->STU_RGB[4].R)<<5);
  165. temp=temp |((pMsg->STU_RGB[4].G)<<6);
  166. temp=temp |((pMsg->STU_RGB[4].B)<<7);
  167. temp=temp |((pMsg->STU_RGB[5].R)<<1);
  168. temp=temp |((pMsg->STU_RGB[5].G)<<2);
  169. temp=temp |((pMsg->STU_RGB[5].B)<<3);
  170. Pack[7]=temp;
  171. temp=0x00;
  172. temp=temp |((pMsg->STU_RGB[6].R)<<5);
  173. temp=temp |((pMsg->STU_RGB[6].G)<<6);
  174. temp=temp |((pMsg->STU_RGB[6].B)<<7);
  175. temp=temp |((pMsg->STU_RGB[7].R)<<1);
  176. temp=temp |((pMsg->STU_RGB[7].G)<<2);
  177. temp=temp |((pMsg->STU_RGB[7].B)<<3);
  178. Pack[8]=temp;
  179. CRC16=crc16_calc(0xffff,Pack,9);
  180. Pack[9] = (unsigned char)(CRC16 & 0xff);
  181. Pack[10] = (unsigned char)(CRC16 >> 8);
  182. Pack[11]=0xdd;
  183. Pack[12]=0x55;
  184. if(Pack[4]==1){
  185. SlwTrace(INF,"/***********ADDR====1*************/\r\n");
  186. for(i=0;i<13;i++)
  187. {
  188. snprintf(buf,sizeof(buf),"%02x",Pack[i]);
  189. SlwTrace(INF,buf);
  190. }
  191. }
  192. SlwTrace(INF,"\r\n");
  193. RS485_DIR_HIGH;
  194. for(i=0;i<13;i++)
  195. {
  196. USART_SendData(USART1,Pack[i]);
  197. while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  198. }
  199. RS485_DIR_LOW;
  200. }
  201. /****************************************************************************
  202. ModbusRecvProcess
  203. pData格式:
  204. AA BB CMD LEN ADDR ERRNUM DT(1) CRC(2) DD 55 //len=11
  205. *****************************************************************************/
  206. //ModbusRecvProcess(pData, sut_deviceTemp[g_ucRegNumCount]);
  207. //Devices(count);
  208. int ModbusRecvProcess(unsigned char *pData) // 临时变量红外状态
  209. {
  210. char buf[30];
  211. int i;
  212. unsigned short crc,CRC16;
  213. int flag=0;
  214. int len=pData[3];
  215. //SlwTrace(DEBUG,"Decodec From MB OK!\r\n");
  216. g_ucModbusRefreshEN = 1; //收到一次
  217. //if(len < 5) return 0;//长度小于5的就不处理
  218. CRC16=crc16_calc(0xffff,pData,len-4);
  219. crc=((unsigned short)pData[len-3]&0xff)<<8;
  220. crc+=(unsigned short)pData[len-4]&0xff;
  221. if(crc != CRC16) return 0;//CRC校验不对,不处理
  222. tsk_lock ();//涉及到全局变量在不同任务中共享,就要加任务锁,避免修改全局变量未完成时切换到别的任务去调用全局变量,从而导致数据完整性问题。
  223. if(sut_device_read[g_ucRegNumCount].Addr==pData[4]){
  224. if(SelfChek==0){
  225. device_vailable[g_ucRegNumCount]=1;
  226. }
  227. sut_device_read[g_ucRegNumCount].Error=pData[5];
  228. for(i=0;i<8;i++){
  229. sut_device_read[g_ucRegNumCount].RID[i]=(pData[6]&0x80)>>7;
  230. pData[6]=pData[6]<<1;
  231. }
  232. }
  233. tsk_unlock ();
  234. // SlwTrace(INF,"\r\n");
  235. // sprintf(buf,"g_ucRegNumCount=====%d==\r\n",g_ucRegNumCount);
  236. // SlwTrace(DEBUG,buf);
  237. return 1;
  238. }
  239. //处理TCP下行数据
  240. int ProcessSetControl()
  241. {
  242. unsigned char i;
  243. unsigned int cnt;
  244. //收到下发数据等待查询完成稳定
  245. // for(cnt=0;cnt<500000;cnt++){
  246. // for(i=0;i<73;i++){
  247. //
  248. // __NOP();
  249. //
  250. // }
  251. // }
  252. //循环遍历设置
  253. for(i=0;i<MODBUS_REG_NUM_MAX;i++)
  254. {
  255. if(device_vailable[i]!=1) continue; //不在线直接跳过
  256. os_dly_wait(1);
  257. ModbusCmdSetValue(&Device_Down.sut_device_write[i]);
  258. }
  259. return 0;
  260. }
  261. //初步定为定时上传
  262. int ProcessTcpSend()
  263. {
  264. return 0;
  265. }