找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索

關(guān)于rs485主從機(jī)通信,主機(jī)為什么接收不到從機(jī)數(shù)據(jù)?

查看數(shù): 3080 | 評論數(shù): 15 | 收藏 0
關(guān)燈 | 提示:支持鍵盤翻頁<-左 右->
    組圖打開中,請稍候......
發(fā)布時間: 2022-12-26 17:38

正文摘要:

目的:以STM32f103為主機(jī),51單片機(jī)為從機(jī)建立通信 問題描述:目前硬件電路沒有問題,主機(jī)使用正點(diǎn)原子的RS485測試程序(通信程序在主程序while循環(huán)中),通過按下按鍵,STM32發(fā)送數(shù)據(jù),可以成功接收到51單片機(jī)的返 ...

回復(fù)

ID:384109 發(fā)表于 2022-12-28 15:05
樓主還沒完全理解串口通訊,就上手485通訊,出現(xiàn)這種情況是會比較難理解的
ID:1037582 發(fā)表于 2022-12-28 11:16
完整RS485通信代碼已經(jīng)上傳,請各位大神指點(diǎn)
ID:1037582 發(fā)表于 2022-12-28 11:14
  1. #include "sys.h"                    
  2. #include "rs485.h"         
  3. #include "delay.h"
  4. #include "CRC16.h"
  5. #include "math.h"
  6. #include "stdio.h"
  7. #define pi acos(-1)
  8. #ifdef EN_USART2_RX           //如果使能了接收
  9. //接收緩存區(qū)        
  10. u8 RS485_RX_BUF[64];          //接收緩沖,最大64個字節(jié).
  11. //接收到的數(shù)據(jù)長度
  12. u8 RS485_RX_CNT=0;   
  13. void USART2_IRQHandler(void)
  14. {
  15.         u8 res;            

  16.         if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到數(shù)據(jù)
  17.         {         
  18.                                   
  19.                 res =USART_ReceiveData(USART2);         //讀取接收到的數(shù)據(jù)
  20.                 if(RS485_RX_CNT<64)
  21.                 {
  22.                         RS485_RX_BUF[RS485_RX_CNT]=res;                //記錄接收到的值
  23.                         RS485_RX_CNT++;                                                //接收數(shù)據(jù)增加1
  24.                 }
  25.         }                                                                                           
  26. }
  27. #endif                                                                                 
  28. //初始化IO 串口2
  29. //pclk1:PCLK1時鐘頻率(Mhz)
  30. //bound:波特率          
  31. void RS485_Init(u32 bound)
  32. {  
  33.     GPIO_InitTypeDef GPIO_InitStructure;
  34.     USART_InitTypeDef USART_InitStructure;
  35.         NVIC_InitTypeDef NVIC_InitStructure;

  36.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);//使能GPIOA,D時鐘
  37.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2時鐘
  38.        
  39.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;                                 //PD7端口配置
  40.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽輸出
  41.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  42.         GPIO_Init(GPIOD, &GPIO_InitStructure);

  43.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //PA2
  44.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //復(fù)用推挽
  45.     GPIO_Init(GPIOA, &GPIO_InitStructure);
  46.    
  47.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  48.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
  49.     GPIO_Init(GPIOA, &GPIO_InitStructure);  

  50.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//復(fù)位串口2
  51.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止復(fù)位

  52.        
  53. #ifdef EN_USART2_RX                          //如果使能了接收
  54.         USART_InitStructure.USART_BaudRate = bound;//波特率設(shè)置
  55.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位數(shù)據(jù)長度
  56.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
  57.         USART_InitStructure.USART_Parity = USART_Parity_No;///奇偶校驗位
  58.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
  59.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收發(fā)模式

  60.   USART_Init(USART2, &USART_InitStructure); ; //初始化串口
  61.   
  62.         NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中斷
  63.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占優(yōu)先級2級
  64.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級2級
  65.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
  66.         NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器

  67.   USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開啟中斷
  68.    
  69.   USART_Cmd(USART2, ENABLE);                    //使能串口

  70. #endif

  71.   RS485_TX_EN=0;                        //默認(rèn)為接收模式

  72. }

  73. //RS485發(fā)送len個字節(jié).
  74. //buf:發(fā)送區(qū)首地址
  75. //len:發(fā)送的字節(jié)數(shù)(為了和本代碼的接收匹配,這里建議不要超過64個字節(jié))
  76. void RS485_Send_Data(u8 *buf,u8 len)
  77. {
  78.         u8 t;
  79.         RS485_TX_EN=1;                        //設(shè)置為發(fā)送模式
  80.           for(t=0;t<len;t++)                //循環(huán)發(fā)送數(shù)據(jù)
  81.         {                  
  82.                 while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);       
  83.                 USART_SendData(USART2,buf[t]);
  84.         }         

  85.         while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);               
  86.         RS485_RX_CNT=0;          
  87.         RS485_TX_EN=0;                                //設(shè)置為接收模式       
  88. }
  89. //RS485查詢接收到的數(shù)據(jù)
  90. //buf:接收緩存首地址
  91. //len:讀到的數(shù)據(jù)長度
  92. void RS485_Receive_Data(u8 *buf,u8 *len)
  93. {
  94.         u8 rxlen=RS485_RX_CNT;
  95.         u8 i=0;
  96.         *len=0;                                //默認(rèn)為0
  97.         delay_ms(10);                //等待10ms,連續(xù)超過10ms沒有接收到一個數(shù)據(jù),則認(rèn)為接收結(jié)束
  98.         if(rxlen==RS485_RX_CNT&&rxlen)//接收到了數(shù)據(jù),且接收完成了
  99.         {
  100.                 for(i=0;i<rxlen;i++)
  101.                 {
  102.                         buf[i]=RS485_RX_BUF[i];
  103.                 }               
  104.                 *len=RS485_RX_CNT;        //記錄本次數(shù)據(jù)長度
  105.                 RS485_RX_CNT=0;                //清零
  106.         }
  107. }


  108. u8 RS485_correspondence(u8 addr)
  109. {
  110.         u8 rs485buf[8];
  111.         u8 crc485[5];
  112.         u8 data1,data2;
  113.         u8 len1,len2;
  114.         u8 k,i;
  115.         u8 cnt;
  116.         u16 crc;
  117.         u8 crc1,crc2;
  118.         u8 crc3,crc4;
  119.         rs485buf[0] = addr;
  120.         RS485_Send_Data(rs485buf,1);   //地址發(fā)送       
  121.         RS485_Receive_Data(rs485buf,&len1); //接收從機(jī)回饋
  122.         if(len1)
  123.         {
  124.                 for(i=0;i<7;i++)
  125.                 {
  126.                         printf("%d\r\t",rs485buf[i]);
  127.                 }
  128.                 data1 = rs485buf[0];
  129.                 if(addr == data1)//判斷從機(jī)是否準(zhǔn)備就緒
  130.                 {
  131.                         printf("接收到從機(jī)信號\r\n");
  132.                         data2 = rs485buf[1];
  133.                         len2 = rs485buf[2];//測量數(shù)據(jù)長度
  134.                         if(data2 == 0xAA)
  135.                         {
  136.                                 for(k = 0;k < len2;k++)
  137.                                 {
  138.                                         cnt=cnt+rs485buf[3+k];
  139.                                         crc485[k] = rs485buf[3+k];
  140.                                 }
  141.                         }                       
  142.                         if(data2 == 0xBB)
  143.                         {
  144.                                 for(k = 0;k < len2;k++)
  145.                                 {
  146.                                         cnt=cnt+rs485buf[3+k];
  147.                                         crc485[k] = rs485buf[3+k];
  148.                                         cnt = -cnt;
  149.                                 }                                       
  150.                         }
  151.                                         crc=GetCRC16(crc485,len2);
  152.                                         crc2 = crc>>8;
  153.                                         crc1 = crc&0xff;
  154.                                         crc3 = rs485buf[3+k];
  155.                                         crc4 = rs485buf[4+k];
  156.                                         if(crc1==crc3&&crc2==crc4)
  157.                                         {
  158.                                                 printf("CRC16校驗正確\r\n");
  159.                                         }
  160.                                         else
  161.                                         {
  162.                                                 static int flag3;
  163.                                                 printf("CRC16校驗錯誤,重新發(fā)送數(shù)據(jù)\r\n");
  164.                                                 flag3++;
  165.                                                 if(flag3 == 3)
  166.                                                 {
  167.                                                         printf("數(shù)據(jù)發(fā)送有誤,請重新檢查\r\n");       
  168.                                                         flag3 = 0;
  169.                                                 }
  170.                                                 return 0;                                       
  171.                                         }
  172.                 }
  173.                 else  //從機(jī)錯誤
  174.                 {
  175.                         static int flag1;
  176.                         printf("從機(jī)未準(zhǔn)備就緒\r\n");
  177.                         flag1++;
  178.                         if(flag1 == 3)
  179.                         {
  180.                                 printf("通信錯誤,請重新檢查設(shè)備\r\n");
  181.                                 flag1 = 0;
  182.                         }
  183.                         return 0;
  184.                 }
  185.                 len1 = 0;
  186.         }
  187.         return cnt;
  188. }

復(fù)制代碼
ID:1037582 發(fā)表于 2022-12-28 11:11
Y_G_G 發(fā)表于 2022-12-27 23:32
這也不是什么商業(yè)機(jī)密,直接上傳工程文件不好嗎?
我想驗證一下,難道還要我對著圖片一個字母一個字母的輸入 ...

不上傳工程文件,是因為這只是工程一小部分,我來是想請問大家遇到一些問題從哪方面開始思考解決,能給我開啟新的思路,并不指望誰能馬上給我解決問題;還有就是問題出在哪里,我能說出來就是我自己驗證過了的,而且我是想請問是哪里引起的這個問題。并不是問題本身;也謝謝你對我提問方式的指教,我很少玩論壇,有不足的地方,感謝指正
ID:401564 發(fā)表于 2022-12-27 23:32
這也不是什么商業(yè)機(jī)密,直接上傳工程文件不好嗎?
我想驗證一下,難道還要我對著圖片一個字母一個字母的輸入嗎?
還有就是,不要老是自己認(rèn)為問題會出現(xiàn)在那一段,然后想當(dāng)然的把你認(rèn)為不會出問題的地方排除了.......
ID:513507 發(fā)表于 2022-12-27 16:24
主從通訊方式,主機(jī)給從機(jī)發(fā)送命令后,從機(jī)發(fā)送應(yīng)答,主機(jī)接收從機(jī)應(yīng)答信號后,接收從機(jī)信息
ID:384109 發(fā)表于 2022-12-27 14:24
代碼不全,無法判斷,另外感覺樓主對485概念由偏差,485根本來說也還只是串口通訊而已
ID:1037582 發(fā)表于 2022-12-27 11:17
wangweijie 發(fā)表于 2022-12-27 09:56
你嘗試主機(jī)接收中斷提高一個搶占優(yōu)先級,或者從機(jī)延時發(fā)送數(shù)據(jù)。

感謝意見,嘗試過了,還是不行
ID:1037582 發(fā)表于 2022-12-27 11:03
TTQ001 發(fā)表于 2022-12-27 03:42
消息接收過程是否包含在定時器中斷程序中?

消息接收在中斷中進(jìn)行啊
ID:1037582 發(fā)表于 2022-12-27 11:02
Hephaestus 發(fā)表于 2022-12-26 22:10
你沒有控制收發(fā)器的DE/RE引腳。

您好,收發(fā)控制在發(fā)送和接收程序中有寫了
ID:77589 發(fā)表于 2022-12-27 10:50
RS485是主從通信,要想主機(jī)獲取從機(jī)數(shù)據(jù),必須讓主機(jī)給從機(jī)發(fā)送獲取數(shù)據(jù)命令,再讓自己處于接收狀態(tài)等待從機(jī)數(shù)據(jù)到來。
首先排查邏輯是否正確,再排查硬件配置。
ID:417460 發(fā)表于 2022-12-27 09:56
你嘗試主機(jī)接收中斷提高一個搶占優(yōu)先級,或者從機(jī)延時發(fā)送數(shù)據(jù)。
ID:420836 發(fā)表于 2022-12-27 03:42
消息接收過程是否包含在定時器中斷程序中?
ID:883242 發(fā)表于 2022-12-26 22:10
你沒有控制收發(fā)器的DE/RE引腳。

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表