找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 17561|回复: 32
打印 上一主题 下一主题
收起左侧

STC15系列单片机RS-485通讯例程(带CRC校验)

  [复制链接]
跳转到指定楼层
楼主
ID:389303 发表于 2018-8-23 15:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STC15系列单片机RS-485通讯例程

单片机源程序如下:
  1. #include <uart.h>


  2. sbit bitCtrl_485Eable = P1^3;//
  3. sbit bitCtrl_485_2Eable = P7^3;//

  4. xdata unsigned char mod_comd[9]={0x01,0x04,0x75,0x31,0x02,0x00,0x00,0x08,0x09};
  5. unsigned char freq = 0;


  6. /****************************************************************************************/
  7. // unsigned char MyDeviceAddr _at_ 0x06000;
  8. // unsigned char PODeviceAddr _at_ 0x05999;
  9. unsigned char MyDeviceAddr;
  10. unsigned char PODeviceAddr;


  11. /*********************************
  12. 串口1变量定义
  13. **********************************/
  14. bit busy1 = 0;
  15. xdata unsigned char u8Uart1TxBuffer[USART1_TX_BUFFER_SIZE];
  16. xdata unsigned char u8Uart1RxBuffer[USART1_RX_BUFFER_SIZE];
  17. unsigned char  u8Rx1Head = 0;
  18. unsigned char  u8Rx1Tail = 0;
  19. unsigned char  u8Tx1Head = 0;
  20. unsigned char  u8Tx1Tail = 0;

  21. unsigned char  mdbs1_stat = 0;
  22. unsigned char  mdbs1_len = 0;
  23. unsigned char  mdbs1_cnt = 0;
  24. unsigned char  mdbs1_maxlen = 0;
  25. xdata unsigned char mdbs1_Rxbuf[16];
  26. xdata unsigned char mdbs1_Txbuf[16];
  27. unsigned char  mdbs1_pos = 0;
  28. unsigned char  mdbs1_timerflag = 0;
  29. unsigned char  mdbs1_overtime = 0;
  30. unsigned char  mdbs1_data_len = 0;
  31. /****************************************************************************************/

  32. /****************************************************************************************/
  33.    

  34. /*********************************
  35. 串口2变量定义
  36. **********************************/

  37. bit busy2 = 0;
  38. xdata unsigned char u8Uart2TxBuffer[USART2_TX_BUFFER_SIZE];
  39. xdata unsigned char u8Uart2RxBuffer[USART2_RX_BUFFER_SIZE];
  40. unsigned char  u8Rx2Head = 0;
  41. unsigned char  u8Rx2Tail = 0;
  42. unsigned char  u8Tx2Head = 0;
  43. unsigned char  u8Tx2Tail = 0;


  44. unsigned char  mdbs2_stat = 0;
  45. unsigned char  mdbs2_len = 0;
  46. unsigned char  mdbs2_cnt = 0;
  47. unsigned char  mdbs2_maxlen = 0;
  48. xdata unsigned char mdbs2_Rxbuf[16];
  49. xdata unsigned char mdbs2_Txbuf[16];
  50. unsigned char  mdbs2_pos = 0;
  51. unsigned char  mdbs2_timerflag = 0;
  52. unsigned char  mdbs2_overtime = 0;
  53. unsigned char  mdbs2_data_len = 0;
  54. /****************************************************************************************/


  55. /*定时器0初始化,采用16位自动重装技术模式*/

  56. void Timer0Init(void)                                //10毫秒@11.0592MHz                          //16位重装计数器
  57. {
  58.         AUXR &= 0x7F;                                        //定时器时钟12T模式
  59.         TMOD &= 0xF0;                                        //设置定时器模式
  60.                                 
  61.         TL0 = -(FOSC/12/100);                        //设置定时初值
  62.         TH0 = -(FOSC/12/100) >> 8;                //设置定时初值
  63. //        RL_TH0


  64.         TF0 = 0;                                                //清除TF0标志
  65.         TR0 = 1;                                                //定时器0开始计时
  66.         Timer0_InterruptFirst();
  67.         ET0 = 1;                                                //enable timer0 interrupt
  68. }
  69. /***定时器0中断服务函数**/
  70. void tm0_isr() interrupt 1  using 1
  71. {

  72.                                                                
  73.     TF0 = 0;                                            //清除TF0标志
  74.         TL0 = -(FOSC/12/100);                    //设置定时初值
  75.         TH0 = -(FOSC/12/100) >> 8;                //设置定时初值
  76.    
  77.          ++freq;  
  78.         

  79. }

  80. /************************************************************************/
  81.   //8位数据   波特率可变    无奇偶检验位    1位起始位  1位停止位
  82.   //使用定时器1作为波特率发生器
  83.    void Uart1Init(void)                                        //9600bps@11.0592MHz
  84. {
  85.         PCON &= 0x3F;                                        //波特率不倍速
  86.         SCON = 0x50;                                        //8位数据,可变波特率
  87.         AUXR &= 0xBF;                                        //定时器1时钟为Fosc/12,即12T  传统51速度
  88.         AUXR &= 0xFE;                                        //串口1选择定时器1为波特率发生器
  89. //        AUXR |=0X01;                                          //串口1选择定时器2为波特率发生器

  90.         TMOD &= 0x0F;                                        //清除定时器1模式位
  91.         TMOD |= 0x20;                                        //设定定时器1为8位自动重装方式

  92. //        TMOD &= 0xF0;                                        //清除定时器2模式位
  93. //        TMOD |= 0x02;                                        //设定定时器2为8位自动重装方式

  94.         TL1 = -(FOSC/12/32/BAUD);                //设定定时初值
  95.         TH1 = -(FOSC/12/32/BAUD);                //设定定时器重装值
  96. /*****

  97. 定时器2工作方式为固定16位自动重装载   装在值需重新计算
  98. */
  99. //        T2L = -(FOSC/12/32/BAUD);                //设定定时初值
  100. //        T2H = -(FOSC/12/32/BAUD);                //设定定时器重装值


  101.         ET1 = 0;                                                //禁止定时器1中断
  102.         TR1 = 1;                                                //启动定时器1
  103. //        S1_USE_P36P37();                        //定义串口1管脚
  104.         UART1_InterruptFirst();                  //中断优先级设定
  105.         ES = 1;                                 //????????


  106.    bitCtrl_485Eable=0;
  107. }
  108. /******************        *****************************************************/
  109. /*************串口2初始化************/
  110. /************************************************************************/

  111. //#define                S3_Int_en()                        IE2   |=  8
  112. void Uart2Init(void)                                //10毫秒@11.0592MHz
  113. {
  114. /*        
  115.         T2MOD = 0;                                                //初始化模式寄存器
  116.         T2CON = 0;                                                //初始化控制寄存器
  117.         TL2 = -(FOSC/12/100);                        //设置定时初值
  118.         TH2 = -(FOSC/12/100) >> 8;                //设置定时初值
  119.         RCAP2L = -(FOSC/12/100);                //设置定时重载值
  120.         RCAP2H = -(FOSC/12/100) >> 8;        //设置定时重载值
  121.         TR2 = 1;                                            //定时器2开始计时
  122.         ET2 = 1;                                                //enable timer2 interrupt
  123. */        
  124.         
  125. //        Timer2_12T();
  126. //        Timer2_AsTimer();
  127. //        T2L = -(FOSC/12/100);                        //设置定时初值
  128. //        T2H = -(FOSC/12/100) >> 8;                //设置定时初值
  129. //        Timer2_Run();
  130. //        Timer2_InterruptEnable();
  131.         //Timer2_InterruptDisable();
  132.         
  133.         S2CON = 0x50;
  134.         Timer2_12T();
  135.         T2L = (65536-(FOSC/4/12/BAUD));
  136.         T2H = (65536-(FOSC/4/12/BAUD))>> 8;
  137.         Timer2_Run();
  138.         Timer2_InterruptDisable();
  139. //        S2_USE_P10P11();//使用默认端口        
  140.         S2_Int_en();        //中断允许
  141.         
  142. //        S3CON = 0x10;
  143. //        Timer2_12T();
  144. //        T2L = -(FOSC/12/4/BAUD);
  145. //        T2H = -(FOSC/12/4/BAUD) >> 8;
  146. //        Timer2_Run();
  147. //        Timer2_InterruptDisable();
  148. //        S3_USE_P50P51();        
  149. //        S3_Int_en();
  150.           bitCtrl_485_2Eable = 0;
  151.         
  152.         InternalRAM_enable();                        ////禁止外部XRAM,允许使用内部1024RAM
  153. }
  154. /****************************************************************************************/


  155.   /****************************************************************************************/
  156.   /**串口1中断服务函数!!!!!!!!!!!!!!!
  157.   !!!!!!!!!!!!*/
  158.   /*******************************
  159.   接收数据缓存区满时,丢弃接收到的数据,数据处理后释放数据缓存区
  160.   ********************************/

  161.    void Uart1_Isr() interrupt 4 using 2
  162. {
  163. // EA = 0;

  164.     if (RI==1)
  165.     {
  166.        RI = 0;               //Clear receive interrupt flag

  167.                
  168.          if(u8Rx1Head+1 != u8Rx1Tail)
  169.                 {
  170.                         u8Uart1RxBuffer[u8Rx1Head++] = SBUF;
  171.                         u8Rx1Head &= USART1_RX_BUFFER_MASK;
  172.                 }


  173.     }
  174.     if (TI==1)
  175.     {
  176.         TI=0;            //Clear transmit interrupt flag
  177.         busy1 = 0;           //Clear transmit busy flag
  178.                 if(u8Tx1Head != u8Tx1Tail)
  179.                 {
  180.                 bitCtrl_485Eable =1;
  181.                         SBUF = u8Uart1TxBuffer[u8Tx1Tail++];
  182.                         u8Tx1Tail &= USART1_TX_BUFFER_MASK;
  183.                 }
  184.                 else
  185.                 {
  186.                 bitCtrl_485Eable =0;
  187.                 }
  188.     }
  189. //        EA = 1;
  190. }


  191. /********串口2中断服务函数******/
  192.   /*******************************
  193.   接收数据缓存区满时,丢弃接收到的数据,数据处理后释放数据缓存区
  194.   ********************************/
  195. #define        S2RI  0x01
  196. #define        S2TI  0x02
  197. void Uart2_Isr() interrupt 8 using 2
  198. {
  199. // EA = 0;

  200.     if (S2CON&S2RI)
  201.     {
  202.         S2CON &= ~S2RI;             //Clear receive interrupt flag

  203.                
  204.          if(u8Rx2Head+1 != u8Rx2Tail)
  205.                 {
  206.                         u8Uart2RxBuffer[u8Rx2Head++] = S2BUF;
  207.                         u8Rx2Head &= USART2_RX_BUFFER_MASK;
  208.                 }


  209.     }
  210.     if (S2CON&S2TI)
  211.     {
  212.         S2CON &= ~S2TI;            //Clear transmit interrupt flag
  213.         busy2 = 0;           //Clear transmit busy flag
  214.                 if(u8Tx2Head != u8Tx2Tail)
  215.                 {
  216.                         bitCtrl_485_2Eable = 1;
  217.                         S2BUF = u8Uart2TxBuffer[u8Tx2Tail++];
  218.                         u8Tx2Tail &= USART2_TX_BUFFER_MASK;
  219.                 }
  220.                 else
  221.                 {
  222.                         bitCtrl_485_2Eable = 0;
  223.                 }
  224.     }
  225. //        EA = 1;
  226. }

  227. /********************************************************************************************/
  228. /*******读串口1缓冲区1字节函数********************************************************
  229. 读取一个字节的接收缓存数据 ,释放一个字节的缓存空间        读取的数据存放在*pdat
  230. 返回0,表示缓存区有未读数据
  231. 返回-1,表示缓存区没有未读数据
  232. ****************************/

  233. BYTE Recv1Data(BYTE *pdat)        
  234. {
  235.     if(u8Rx1Head != u8Rx1Tail)   //有未处理数据
  236.         {
  237.                 *pdat = u8Uart1RxBuffer[u8Rx1Tail++];
  238.                 u8Rx1Tail &= USART1_RX_BUFFER_MASK;
  239.                 return 0;
  240.         }
  241.         return -1;
  242. }
  243. /****************************************************************************************/


  244. /********************************************************************************************/
  245. /**********读串口2缓冲区1字节函数*****************************************************
  246. 读取一个字节的接收缓存数据 ,释放一个字节的缓存空间        读取的数据存放在*pdat
  247. 返回0,表示缓存区有未读数据
  248. 返回-1,表示缓存区没有未读数据
  249. ****************************/
  250. BYTE Recv2Data(BYTE *pdat)        
  251. {
  252.     if(u8Rx2Head != u8Rx2Tail)   //有未处理数据
  253.         {
  254.                 *pdat = u8Uart2RxBuffer[u8Rx2Tail++];
  255.                 u8Rx2Tail &= USART2_RX_BUFFER_MASK;
  256.                 return 0;
  257.         }
  258.         return -1;
  259. }
  260. /****************************************************************************************/

  261. /* Send a byte data to UART
  262. Input: dat (data to be sent)
  263. Output:None        
  264. 串口1发送一个字节的数据
  265. u8UartTxBuffer 用于发送数据的缓存  防止数据未及时发送时的数据堆积
  266. ----------------------------*/
  267.   


  268. BYTE Send1Data(BYTE dat)
  269. {
  270.         if((u8Tx1Head == u8Tx1Tail) && (0 == busy1))
  271.         {
  272.                          busy1 = 1;
  273.         bitCtrl_485Eable =1;
  274.         
  275. //                S3BUF = dat;
  276. //                S2BUF = dat;
  277.                 SBUF = dat;
  278.                 return 0;
  279.         }
  280.         if(u8Tx1Head+1 == u8Tx1Tail)
  281.         {
  282.                 return -1;        // full
  283.         }
  284.         u8Uart1TxBuffer[u8Tx1Head++] = dat;         //如果发送繁忙  则数据保存在发送缓存区
  285.         u8Tx1Head &= USART1_TX_BUFFER_MASK;
  286.         return 1;
  287. }


  288. /****************************************************************************************/
  289. /****************************************************************************************/


  290. /* Send a byte data to UART
  291. Input: dat (data to be sent)
  292. Output:None        
  293. 串口2发送一个字节的数据
  294. u8UartTxBuffer 用于发送数据的缓存  防止数据未及时发送时的数据堆积
  295. ----------------------------*/
  296. BYTE Send2Data(BYTE dat)
  297. {
  298.         if((u8Tx2Head == u8Tx2Tail) && (0 == busy2))
  299.         {
  300.                 busy2 = 1;
  301.                 bitCtrl_485_2Eable = 1;
  302. //                S3BUF = dat;
  303.                 S2BUF = dat;
  304. //                SBUF = dat;
  305.                 return 0;
  306.         }
  307.         if(u8Tx2Head+1 == u8Tx2Tail)
  308.         {
  309.                 return -1;        // full
  310.         }
  311.         u8Uart2TxBuffer[u8Tx2Head++] = dat;         //如果发送繁忙  则数据保存在发送缓存区
  312.         u8Tx2Head &= USART2_TX_BUFFER_MASK;
  313.         return 1;
  314. }
  315. /****************************************************************************************/
  316. /****************************************************************************************/




  317. /****************************************
  318.           从串口1数据缓存区读取数据函数
  319. 读取数据缓存区数据,释放缓存空间 读取的数据保存在mdbs_Rxbuf中!!
  320. 并判断接收数据 的有效性        (本地地址校验,读写位校验,数据长度校验,CRC校验)
  321. 返回0,表示已接收完成一组有效数据
  322. 返回-1,表示,缓存区没有数据或数据不完整!          或与本机地址不匹配
  323. !!!如果缓存中有数据,单数据不完整,则把已有数据保存在 mdbs_Rxbuf中,下次进入此函数,数据继续保存
  324.     mdbs1_Rxbuf[]          接收数据存储区
  325.         mdbs1_len          接收数据长度
  326.         mdbs1_maxlen  接收指令数据区的长度
  327.         mdbs1_stat          接收状态
  328.         mdbs1_pos          数据存储地址
  329.         mdbs1_overtime 接收超时标志
  330.         mdbs1_timerflag 连续接收标志
  331.         freq          时钟节拍
  332. 如果中间有数据错误,则重新寻找数据开始位置!!!
  333. ************************************************/
  334. unsigned char link_recv1_pkt(void)                  
  335. {
  336.         unsigned char u8dat;
  337.         if(mdbs1_timerflag)
  338.         {
  339.                 if(freq - mdbs1_overtime >= 10)
  340.                 {
  341.                         Link1ClearState();
  342.                 }
  343.         }
  344.         while(0 == Recv1Data(&u8dat))//
  345.         {
  346.                 switch(mdbs1_stat)  //初次进入  mdbs_stat=0
  347.                 {
  348.                         case 0:
  349.                         {
  350.                                 if(u8dat > 256)        //地址不能大于247?        255?
  351.                                 {
  352.                                         break;
  353.                                 }
  354.                                 if(PODeviceAddr!=u8dat)         return -1;           //不是目标地址返回-1
  355.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  356.                                 mdbs1_len++;
  357.                                 mdbs1_stat = 1;
  358.                                 freq=mdbs1_overtime;
  359.                                 mdbs1_timerflag = 1;
  360.                                 
  361.                         } break;

  362.                         case 1:           //功能码
  363.                         {
  364.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  365.                                 mdbs1_len++;
  366.                                 if((READ_INPUT == u8dat)||(WRITE_INPUT==u8dat))
  367.                                 {
  368.                                         mdbs1_stat = 2;
  369.                                         //mdbs_cnt = 0;
  370.                                         //mdbs_maxlen = 4;
  371.                                        
  372.                                 }
  373.                                 else
  374.                                 {
  375.                                         Link1ClearState();
  376.                                         break;                                
  377.                                 }
  378.                                 freq=mdbs1_overtime;
  379.                                 mdbs1_timerflag = 1;
  380.                         } break;

  381.                         case 2:          //标识码高字节,不做处理直接保存
  382.                         {
  383.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  384.                                 mdbs1_len++;
  385.                                 mdbs1_stat = 3;
  386.                                 freq=mdbs1_overtime;
  387.                                 mdbs1_timerflag = 1;
  388.                         } break;
  389.                         case 3:         //标识码底字节,不做处理直接保存
  390.                         {
  391.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  392.                                 mdbs1_len++;
  393.                                 mdbs1_stat = 4;
  394.                                 freq=mdbs1_overtime;
  395.                                 mdbs1_timerflag = 1;
  396.                         
  397.                         } break;
  398.                         
  399.                         case 4:         //数据长度
  400.                         {
  401.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  402.                                 mdbs1_len++;
  403.                              mdbs1_cnt++;
  404.                                 //if(mdbs_cnt >= mdbs_maxlen)
  405.                                 //{
  406.                                         mdbs1_stat = 5;
  407.                                         mdbs1_cnt = 0;
  408.                                         mdbs1_maxlen = u8dat;
  409.                                         if(u8dat==0)  //如果数据长度为0          只剩下CRC校验数据
  410.                                         {
  411.                                                 mdbs1_stat = 100;
  412.                                                 mdbs1_cnt = 0;
  413.                                                 mdbs1_maxlen = 2;
  414.                                         }
  415.                                 //}
  416.                                 freq=mdbs1_overtime;
  417.                                 mdbs1_timerflag = 1;
  418.                                 
  419.                         } break;
  420.                         case 5:        //数据长度不为0,继续接收有效数据
  421.                         {
  422.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  423.                                 mdbs1_len++;
  424.                                 mdbs1_cnt++;
  425.                                 if(mdbs1_cnt >= mdbs1_maxlen)
  426.                                 {
  427.                                         mdbs1_stat = 100;
  428.                                         mdbs1_cnt = 0;
  429.                                         mdbs1_maxlen = 2;
  430.                                 }
  431.                                 freq=mdbs1_overtime;
  432.                                 mdbs1_timerflag = 1;
  433.                         } break;
  434.                         
  435.                         case 100:  //CRC校验位
  436.                         {
  437.                                 mdbs1_Rxbuf[mdbs1_pos++] = u8dat;
  438.                                 mdbs1_len++;
  439.                                 mdbs1_cnt++;
  440.                                 if(mdbs1_cnt >= mdbs1_maxlen)
  441.                                 {
  442.                                         mdbs1_timerflag = 0;
  443.                                         mdbs1_data_len = mdbs1_len;
  444.                                         if((CRC16(mdbs1_Rxbuf, mdbs1_len) == 0) && (PODeviceAddr == mdbs1_Rxbuf[0]))         
  445.                                         {
  446.                                                 Link1ClearState();
  447.                                                 return 0;
  448.                                         }
  449.                                         Link1ClearState();
  450.                                 }
  451.                                 freq=mdbs1_overtime;
  452.                                 mdbs1_timerflag = 1;
  453.                         } break;

  454.                         default:
  455.                                 Link1ClearState();
  456.                                 break;
  457.                 }
  458.         }
  459.         return -1;
  460. }

  461. /****************************************************************************************/


  462. /****************************************
  463.           从串口2数据缓存区读取数据函数
  464. 读取数据缓存区数据,释放缓存空间 读取的数据保存在mdbs2_Rxbuf中!!
  465. 并判断接收数据 的有效性        (本地地址校验,读写位校验,数据长度校验,CRC校验)
  466. 返回0,表示已接收完成一组有效数据
  467. 返回-1,表示,缓存区没有数据或数据不完整!          或与本机地址不匹配
  468. !!!如果缓存中有数据,单数据不完整,则把已有数据保存在 mdbs_Rxbuf中,下次进入此函数,数据继续保存
  469.     mdbs2_Rxbuf[]          接收数据存储区
  470.         mdbs2_len          接收数据长度
  471.         mdbs2_maxlen  接收指令数据区的长度
  472.         mdbs2_stat          接收状态
  473.         mdbs2_pos          数据存储地址
  474.         mdbs2_overtime 接收超时标志
  475.         mdbs2_timerflag 连续接收标志
  476.         freq          时钟节拍
  477. 如果中间有数据错误,则重新寻找数据开始位置!!!
  478. ************************************************/

  479. unsigned char link_recv2_pkt(void)                  
  480. {
  481.         unsigned char u8dat;
  482.         if(mdbs2_timerflag)
  483.         {
  484.                 if(freq - mdbs2_overtime >= 10)
  485.                 {
  486.                         Link2ClearState();
  487.                 }
  488.         }
  489.         while(0 == Recv2Data(&u8dat))//
  490.         {
  491.                 switch(mdbs2_stat)  //初次进入  mdbs_stat=0
  492.                 {
  493.                         case 0:
  494.                         {
  495.                                 if(u8dat > 256)        //地址不能大于247?        255?
  496.                                 {
  497.                                         break;
  498.                                 }
  499.                                 if(MyDeviceAddr!=u8dat)         return -1;           //不是目标地址返回-1
  500.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  501.                                 mdbs2_len++;
  502.                                 mdbs2_stat = 1;
  503.                                 freq=mdbs2_overtime;
  504.                                 mdbs2_timerflag = 1;
  505.                         } break;

  506.                         case 1:           //功能码
  507.                         {
  508.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  509.                                 mdbs2_len++;
  510.                                 if((READ_INPUT == u8dat)||(WRITE_INPUT==u8dat))
  511.                                 {
  512.                                         mdbs2_stat = 2;
  513.                                         //mdbs_cnt = 0;
  514.                                         //mdbs_maxlen = 4;
  515.                                 }
  516.                                 else
  517.                                 {
  518.                                         Link2ClearState();
  519.                                         break;                                
  520.                                 }
  521.                                 freq=mdbs2_overtime;
  522.                                 mdbs2_timerflag = 1;
  523.                         } break;

  524.                         case 2:          //标识码高字节,不做处理直接保存
  525.                         {
  526.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  527.                                 mdbs2_len++;
  528.                                 mdbs2_stat = 3;
  529.                                 freq=mdbs2_overtime;
  530.                                 mdbs2_timerflag = 1;
  531.                         } break;
  532.                         case 3:         //标识码底字节,不做处理直接保存
  533.                         {
  534.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  535.                                 mdbs2_len++;
  536.                                 mdbs2_stat = 4;
  537.                                 freq=mdbs2_overtime;
  538.                                 mdbs2_timerflag = 1;
  539.                         } break;
  540.                         
  541.                         case 4:         //数据长度
  542.                         {
  543.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  544.                                 mdbs2_len++;
  545.                              mdbs2_cnt++;
  546.                                 //if(mdbs_cnt >= mdbs_maxlen)
  547.                                 //{
  548.                                         mdbs2_stat = 5;
  549.                                         mdbs2_cnt = 0;
  550.                                         mdbs2_maxlen = u8dat;
  551.                                         if(u8dat==0)  //如果数据长度为0          只剩下CRC校验数据
  552.                                         {
  553.                                                 mdbs2_stat = 100;
  554.                                                 mdbs2_cnt = 0;
  555.                                                 mdbs2_maxlen = 2;
  556.                                         }
  557.                                 //}
  558.                                 freq=mdbs2_overtime;
  559.                                 mdbs2_timerflag = 1;
  560.                         } break;
  561.                         case 5:        //数据长度不为0,继续接收有效数据
  562.                         {
  563.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  564.                                 mdbs2_len++;
  565.                                 mdbs2_cnt++;
  566.                                 if(mdbs2_cnt >= mdbs2_maxlen)
  567.                                 {
  568.                                         mdbs2_stat = 100;
  569.                                         mdbs2_cnt = 0;
  570.                                         mdbs2_maxlen = 2;
  571.                                 }
  572.                                 freq=mdbs2_overtime;
  573.                                 mdbs2_timerflag = 1;
  574.                         } break;
  575.                         
  576.                         case 100:  //CRC校验位
  577.                         {
  578.                                 mdbs2_Rxbuf[mdbs2_pos++] = u8dat;
  579.                                 mdbs2_len++;
  580.                                 mdbs2_cnt++;
  581.                                 if(mdbs2_cnt >= mdbs2_maxlen)
  582.                                 {
  583.                                         mdbs2_timerflag = 0;
  584.                                         mdbs2_data_len = mdbs2_len;
  585.                                         if((CRC16(mdbs2_Rxbuf, mdbs2_len) == 0) && (MyDeviceAddr == mdbs2_Rxbuf[0]))         
  586.                                         {
  587.                                                 Link2ClearState();
  588.                                                 return 0;
  589.                                         }
  590.                                         Link2ClearState();
  591.                                 }
  592.                                 freq=mdbs2_overtime;
  593.                                 mdbs2_timerflag = 1;
  594.                         } break;

  595.                         default:
  596.                                 Link2ClearState();
  597.                                 break;
  598.                 }
  599.         }
  600.         return -1;
  601. }


  602. /******************************/
  603. /**************************************************/
  604. /*****串口1发送数据函数***********/
  605. /*******发送指定长度的数据*****/


  606. void link1_send_pkt(unsigned char *buf, unsigned char len)
  607. {
  608.         unsigned char i,k;
  609.         for(i=0; i<len; i++)
  610.         {
  611.                 k = Send1Data(buf[i]);
  612.         }
  613. }



  614. /****************************************************************************************/
  615. /*****串口2发送数据函数***********/
  616. /*******发送指定长度的数据*****/
  617. void link2_send_pkt(unsigned char *buf, unsigned char len)
  618. {
  619.         unsigned char i,k;
  620.         for(i=0; i<len; i++)
  621.         {
  622.                 k = Send2Data(buf[i]);
  623.         }
  624. }

  625. /*****串口2发送数据函数
  626. 对指定长度的数据加CRC校验,并发送
  627. *********//*(发送串口1接收的的数据)*/


  628. void svr1_msg(unsigned char *command_buf,unsigned char sentlen)
  629. {
  630.         unsigned int crc;        
  631.         if(sentlen < 4)                   //指令长度不应小于4,否则是无效数据
  632.         {
  633.                 return;        
  634.         }        
  635. //        if(0 == sentlen)return;
  636.         crc = CRC16(command_buf,sentlen);
  637.         command_buf[sentlen]=crc>>8;
  638.         sentlen++;
  639.         command_buf[sentlen]=crc;
  640.         sentlen++;               
  641.         link1_send_pkt(command_buf,sentlen);
  642. }


  643. /******************************************************************************/
  644. /*****串口2发送数据函数
  645. 对指定长度的数据加CRC校验,并发送
  646. *********//*(发送串口1接收的的数据)*/
  647. void svr2_msg(unsigned char *command_buf,unsigned char sentlen)
  648. {
  649.         unsigned int crc;        
  650.         if(sentlen < 4)                   //指令长度不应小于4,否则是无效数据
  651.         {
  652.                 return;        
  653.         }        
  654. //        if(0 == sentlen)return;
  655.         crc = CRC16(command_buf,sentlen);
  656.         command_buf[sentlen]=crc>>8;
  657.         sentlen++;
  658.         command_buf[sentlen]=crc;
  659.         sentlen++;               
  660.         link2_send_pkt(command_buf,sentlen);
  661. }





  662. /*16位CRC校验表*/
  663. code const unsigned char auchCRCHi[]={
  664. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  665. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  666. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  667. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  668. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  669. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  670. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  671. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,

  672. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  673. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  674. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  675. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  676. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,
  677. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  678. 0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,
  679. 0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xc1,0x81,0x40
  680. };
  681. code const unsigned char auchCRCLo[]={
  682. 0x00,0xc0,0xc1,0x01,0xc3,0x03,0x02,0xc2,0xc6,0x06,0x07,0xc7,0x05,0xc5,0xc4,0x04,
  683. 0xcc,0x0c,0x0d,0xcd,0x0f,0xcf,0xce,0x0e,0x0a,0xca,0xcb,0x0b,0xc9,0x09,0x08,0xc8,
  684. 0xd8,0x18,0x19,0xd9,0x1b,0xdb,0xda,0x1a,0x1e,0xde,0xdf,0x1f,0xdd,0x1d,0x1c,0xdc,
  685. 0x14,0xd4,0xd5,0x15,0xd7,0x17,0x16,0xd6,0xd2,0x12,0x13,0xd3,0x11,0xd1,0xd0,0x10,
  686. 0xf0,0x30,0x31,0xf1,0x33,0xf3,0xf2,0x32,0x36,0xf6,0xf7,0x37,0xf5,0x35,0x34,0xf4,
  687. 0x3c,0xfc,0xfd,0x3d,0xff,0x3f,0x3e,0xfe,0xfa,0x3a,0x3b,0xfb,0x39,0xf9,0xf8,0x38,
  688. 0x28,0xe8,0xe9,0x29,0xeb,0x2b,0x2a,0xea,0xee,0x2e,0x2f,0xef,0x2d,0xed,0xec,0x2c,
  689. 0xe4,0x24,0x25,0xe5,0x27,0xe7,0xe6,0x26,0x22,0xe2,0xe3,0x23,0xe1,0x21,0x20,0xe0,

  690. 0xa0,0x60,0x61,0xa1,0x63,0xa3,0xa2,0x62,0x66,0xa6,0xa7,0x67,0xa5,0x65,0x64,0xa4,
  691. 0x6c,0xac,0xad,0x6d,0xaf,0x6f,0x6e,0xae,0xaa,0x6a,0x6b,0xab,0x69,0xa9,0xa8,0x68,
  692. 0x78,0xb8,0xb9,0x79,0xbb,0x7b,0x7a,0xba,0xbe,0x7e,0x7f,0xbf,0x7d,0xbd,0xbc,0x7c,
  693. 0xb4,0x74,0x75,0xb5,0x77,0xb7,0xb6,0x76,0x72,0xb2,0xb3,0x73,0xb1,0x71,0x70,0xb0,
  694. 0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
  695. 0x9c,0x5c,0x5d,0x9d,0x5f,0x9f,0x9e,0x5e,0x5a,0x9a,0x9b,0x5b,0x99,0x59,0x58,0x98,
  696. 0x88,0x48,0x49,0x89,0x4b,0x8b,0x8a,0x4a,0x4e,0x8e,0x8f,0x4f,0x8d,0x4d,0x4c,0x8c,
  697. 0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40
  698. };


  699. /****************************************************************************************/
  700. /*----------------------------
  701. ***********************************************/

  702. /*LRC校验子程序
  703. unsigned char LRC(unsigned char *auchMsg, unsigned char usDataLen)
  704. {
  705.         unsigned char uchLRC = 0;
  706.         while (usDataLen--) { uchLRC += *auchMsg++ ; }
  707. //        return ((uint8)(~uchLRC+1));
  708.         return ((unsigned char)(-((char)uchLRC)));
  709. }*/

  710. /*16位CRC校验子程序*/
  711. unsigned int CRC16(unsigned char* puchMsg, unsigned char usDataLen)
  712. {
  713.         unsigned char uchCRCHi=0xff;
  714.         unsigned char uchCRCLo=0xff;
  715.         unsigned char uIndex;
  716.         while(usDataLen--)
  717.         {
  718.                 uIndex=uchCRCHi^*(puchMsg++);
  719.                 uchCRCHi=uchCRCLo^auchCRCHi[uIndex];
  720.                 uchCRCLo=auchCRCLo[uIndex];
  721.         }
  722.         return uchCRCHi<<8|uchCRCLo;
  723. }



  724. //
  725. //void Timer0Init(void)                                //10毫秒@11.0592MHz
  726. //{
  727. //        AUXR &= 0x7F;                                        //定时器时钟12T模式
  728. //        TMOD &= 0xF0;                                        //设置定时器模式
  729. //        //TMOD |= 0x01;                                        //设置定时器模式
  730. //        TL0 = -(FOSC/12/100);                        //设置定时初值
  731. //        TH0 = -(FOSC/12/100) >> 8;                //设置定时初值
  732. //        TF0 = 0;                                                //清除TF0标志
  733. //        TR0 = 1;                                                //定时器0开始计时
  734. //        Timer0_InterruptFirst();
  735. //        ET0 = 1;                                                //enable timer0 interrupt
  736. //}

  737. /********************************************\

  738. /****************************************************************************************/

  739. /****************************************************************************************/

  740. /*

  741. */
  742. unsigned char MODbus_flag=0;//接收到指令标志
  743. unsigned long int MODbus_flag_time=0;
  744. unsigned long int MODbus_flag_Rtime=0;
  745. unsigned int MODbus_flag2=0;


  746. void Modbus_task(void)
  747. {
  748.   

  749.      unsigned int crc1;
  750.         unsigned char  i;



  751.         if(0 == link_recv2_pkt()) //串口2接收到有效命令
  752.         {
  753.            for(i=0;i<16;i++)
  754.            {
  755.            mdbs1_Txbuf[i]=mdbs2_Rxbuf[i];
  756.            
  757.            }
  758.                 mdbs1_Txbuf[0]=PODeviceAddr;        //本机地址改为目标地址

  759.             svr1_msg(mdbs1_Txbuf, mdbs2_data_len-2) ;  //发送更改后的数据                  //svr1_msg只能发送1ci?

  760.                 MODbus_flag=1;
  761.         }

  762.         if(MODbus_flag==1)
  763.         {   
  764.             
  765.             MODbus_flag_time++;
  766.                 if(0==link_recv1_pkt())  //串口2接收应答   进行数据校验  存储   
  767.                 {
  768.         

  769.                   for(i=0;i<16;i++)
  770.                    {
  771.                    mdbs2_Txbuf[i]=mdbs1_Rxbuf[i];
  772.                   
  773.                    }
  774.                         mdbs2_Txbuf[0]=        MyDeviceAddr;        //本机地址改为目标地址
  775.                   
  776.                    svr2_msg(mdbs2_Txbuf, mdbs1_data_len-2) ;  //发送更改后的数据
  777.                   
  778.                    MODbus_flag=0;
  779.                    MODbus_flag_time=0;
  780.                 }
  781.            else if(MODbus_flag_time>50000)
  782.                 {
  783.                   svr1_msg(mdbs1_Txbuf, mdbs2_data_len-2) ;
  784.                 // svr2_msg(mdbs1_Rxbuf, mdbs1_data_len-2) ;  //chongxin发送更改后的数据
  785.                  MODbus_flag_time=0;
  786.                 }

  787.           }
  788.         else
  789.         {         
  790.             MODbus_flag_Rtime++;
  791.            if(MODbus_flag_Rtime%500==0)
  792.         {
  793.                   bitCtrl_485Eable = 1;
  794.                   mod_comd[0]=PODeviceAddr;


  795.                         crc1 = CRC16(mod_comd,7);
  796.                 mod_comd[7]=crc1>>8;
  797.                  mod_comd[8]=crc1;

  798.              link1_send_pkt(mod_comd,9);        
  799.                   MODbus_flag2=1;
  800.                   MODbus_flag_Rtime=0;
  801.             }
  802.                  if(MODbus_flag2==1)
  803.                  {  
  804.                      Delay_nMS(10);
  805.                  bitCtrl_485Eable = 0;
  806.                          delay(20);
  807.                     if(0==link_recv1_pkt())
  808.                         {
  809.                     //  TM_CloseAllDisplay();
  810.                     DisplayTem(mdbs1_Rxbuf[5],mdbs1_Rxbuf[6]) ;//湿度
  811.               DisplayRH(mdbs1_Rxbuf[7],mdbs1_Rxbuf[8]) ;//温度
  812.                         MODbus_flag2=0;
  813.                         MODbus_flag_time=0;
  814.                         }
  815.         

  816.                         else
  817.                         {
  818.                             MODbus_flag_time++;
  819.                                 if(MODbus_flag_time>2000)
  820.                                 {
  821.                                 MODbus_flag_time=0;
  822.                           TM_OpenAllDisplay();
  823.                                 
  824.                           }
  825.                         }
  826.                 }
  827.    }
  828. }


  829. /*****************************************************************************************/
  830. /**根据modbus1接收区的数据指令,赋值modbus的发送区数据***/
  831. /**返回指令长度***/
  832. /*data_num接收区指令的数据长度
  833.   ack_num  发送区的指令长度
  834.   data_start 接收区标识码
  835. /****************************************************************************************/
  836. /*
  837. unsigned int modbus_data(unsigned char *command_buf, unsigned char *ack_buf)
  838. {
  839.         unsigned int data_start;
  840.         unsigned char data_num;
  841.         unsigned char ack_num;
  842.         unsigned char tempdata;                          
  843.         switch(command_buf[1])
  844.         {
  845.                 case READ_INPUT:        //读输入寄存器值读3区
  846.                         ack_buf[0]=command_buf[0];
  847.                         ack_buf[1]=command_buf[1];
  848.                         ack_buf[2]=command_buf[2];
  849.                         ack_buf[3]=command_buf[3];
  850.                         data_start=(command_buf[2]<<8)+command_buf[3];        //标识码
  851.                         //data_num=(command_buf[4]<<8)+command_buf[5];
  852.                         data_num = command_buf[4];                                                 //数据长度
  853.                         if(data_num>2) data_num=2;        //防止数据超界  //接收的指令数据长度要么是0要么是2
  854.                         //ack_buf[2]=data_num*2;
  855.                         ack_num=5;                                                                                 //应答信号从ack_buf【5】数据开始,        ack_buf【4】中要存放数据长度
  856.                         if(Addr_RH_Start == data_start)
  857.                         {
  858.                                 ack_buf[ack_num]=Sensor_Data[0];         ack_num++;
  859.                                 ack_buf[ack_num]=Sensor_Data[1];        ack_num++;         //7???
  860.                                 ack_buf[4] = 2;                 //应答指令数据长度
  861.                                 if(2 == data_num)
  862.                                 {
  863.                                         ack_buf[ack_num]=Sensor_Data[2];         ack_num++;
  864.                                         ack_buf[ack_num]=Sensor_Data[3];        ack_num++;
  865.                                         ack_buf[4] = 4;         //应答指令数据长度
  866.                                 }
  867.                                 
  868.                         }
  869.                         if(Addr_Temp_Start == data_start)
  870.                         {
  871.                                 ack_buf[ack_num]=Sensor_Data[2];         ack_num++;
  872.                                 ack_buf[ack_num]=Sensor_Data[3];        ack_num++;
  873.                                 ack_buf[4] = 2;
  874.                         }
  875.                         //modify by cjt 2016-07-08
  876.                         if(Addr_RHSet_Start == data_start)
  877.                         {
  878.                                 ack_buf[ack_num]=0;                         ack_num++;
  879.                                 ack_buf[ack_num]=u8DefaultRH;        ack_num++;
  880.                                 ack_buf[4] = 2;
  881.                         }
  882.                         if(Addr_TempSet_Start == data_start)
  883.                         {
  884.                                 ack_buf[ack_num]=0;                         ack_num++;
  885.                                 ack_buf[ack_num]=u8DefaultTemp;        ack_num++;
  886.                                 ack_buf[4] = 2;
  887.                         }
  888.                         if(Addr_RDTemp_Start == data_start)
  889.                         {
  890.                                 ack_buf[ack_num]=0;                         ack_num++;
  891.                                 ack_buf[ack_num]=u8ds18b20_temp;        ack_num++;
  892.                                 ack_buf[4] = 2;
  893. ……………………

  894. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
RS-485.rar (7.05 KB, 下载次数: 606)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏14 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:279575 发表于 2018-9-18 15:53 | 只看该作者
请放一个完整的代码, 不然看的太累了
回复

使用道具 举报

板凳
ID:343707 发表于 2019-5-20 16:15 | 只看该作者
不错的东西,下来试试
回复

使用道具 举报

地板
ID:466896 发表于 2019-5-20 17:42 来自手机 | 只看该作者
⊙⊙!牛逼啊
回复

使用道具 举报

5#
ID:90212 发表于 2019-6-5 22:29 | 只看该作者
调用方法也得简单写一个啊,这样得完全消化才行
回复

使用道具 举报

6#
ID:43342 发表于 2019-6-6 20:36 | 只看该作者
谢谢楼主,牛人!
回复

使用道具 举报

7#
ID:442681 发表于 2019-6-28 08:04 | 只看该作者
楼主 自己调试过吗
回复

使用道具 举报

8#
ID:49198 发表于 2019-7-17 17:14 | 只看该作者
感谢楼主分享,正好用的到,谢谢
回复

使用道具 举报

9#
ID:57896 发表于 2019-7-18 18:26 | 只看该作者
这个程序看不懂,有没有完整的工程
回复

使用道具 举报

10#
ID:607998 发表于 2019-9-24 22:54 来自手机 | 只看该作者
谢谢,学习学习
回复

使用道具 举报

11#
ID:340655 发表于 2019-10-11 14:07 | 只看该作者
确实很棒
回复

使用道具 举报

12#
ID:340655 发表于 2019-10-11 14:08 | 只看该作者
牛人,这代码确实很棒
回复

使用道具 举报

13#
ID:59423 发表于 2019-10-11 18:04 | 只看该作者
代码写的太流畅了,逻辑清晰。
回复

使用道具 举报

14#
ID:59423 发表于 2019-10-12 08:51 | 只看该作者
已经下载,正在研读,准备用在项目上。
回复

使用道具 举报

15#
ID:631173 发表于 2019-10-28 13:59 | 只看该作者
这个帖子不错!
回复

使用道具 举报

16#
ID:653902 发表于 2019-12-15 20:09 | 只看该作者
正好在用15的片子,拿来学习一下。感谢楼主的代码。
回复

使用道具 举报

17#
ID:703942 发表于 2020-3-7 11:10 | 只看该作者
感谢楼主的分享,想学一下485通信有时间研究一下。
回复

使用道具 举报

18#
ID:459415 发表于 2020-3-11 19:13 | 只看该作者
不错的东西,下来试试
回复

使用道具 举报

19#
ID:739137 发表于 2020-5-19 18:31 | 只看该作者
谢谢分享!!!
回复

使用道具 举报

20#
ID:187802 发表于 2020-5-20 10:33 | 只看该作者

谢谢分享
回复

使用道具 举报

21#
ID:174969 发表于 2020-8-8 06:00 | 只看该作者
正需要,下载来看看,谢谢楼主!
回复

使用道具 举报

22#
ID:564550 发表于 2020-11-18 23:56 | 只看该作者
程序都不全,没什么参考价值
回复

使用道具 举报

23#
ID:165291 发表于 2020-11-23 09:28 | 只看该作者
支持一个,不知道好用不!
回复

使用道具 举报

24#
ID:255482 发表于 2020-12-20 16:00 | 只看该作者
能多机通讯吗?
回复

使用道具 举报

25#
ID:879060 发表于 2021-1-20 08:32 | 只看该作者
这个是标准的MODBUS RTU吗?可以和PLC通信吗?PLC地址如何设置呢?
回复

使用道具 举报

26#
ID:390416 发表于 2021-1-20 10:39 | 只看该作者
标题错误,485只是一个硬件。具体什么协议,最好说清楚。我用485芯片做过的协议,最少20多种了
回复

使用道具 举报

27#
ID:911776 发表于 2021-7-5 09:43 | 只看该作者
人人学会单片机 发表于 2021-1-20 10:39
标题错误,485只是一个硬件。具体什么协议,最好说清楚。我用485芯片做过的协议,最少20多种了

20多种协议???定制的?还是都是通用标准的哦
回复

使用道具 举报

28#
ID:911371 发表于 2021-7-29 14:20 | 只看该作者
真需要  研究一下
回复

使用道具 举报

29#
ID:886238 发表于 2021-8-21 13:27 | 只看该作者
学习中,感谢贡献
回复

使用道具 举报

30#
ID:99525 发表于 2022-5-25 15:34 | 只看该作者
看代码好像是modbus协议,接收和校验了modbus指令,没进行指令解析。
回复

使用道具 举报

31#
ID:334781 发表于 2022-8-22 10:59 | 只看该作者
感谢楼主的分享,想学一下485通信有时间研究一下,只是如果有一点程序方面的说明就更好了。
回复

使用道具 举报

32#
ID:284226 发表于 2023-9-9 12:35 | 只看该作者
好东西必回贴
回复

使用道具 举报

33#
ID:1093459 发表于 2023-9-13 18:58 | 只看该作者
好东西 一定要看看 研究一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表