找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1528|回复: 15
收起左侧

关于rs485主从机通信,主机为什么接收不到从机数据?

[复制链接]
ID:1037582 发表于 2022-12-26 17:38 | 显示全部楼层 |阅读模式
目的:以STM32f103为主机,51单片机为从机建立通信
问题描述:目前硬件电路没有问题,主机使用正点原子的RS485测试程序(通信程序在主程序while循环中),通过按下按键,STM32发送数据,可以成功接收到51单片机的返回数据;但是在我自己编写的程序中,主机发送地址不通过按键触发,而是放在定时器中断中,主机发送数据,从机可以接收到且返回发送给主机的数据,但是主机接收不到任何数据(这应该是目前的问题所在);想问问论坛大神们,大家有什么思路去解决这个问题,万分感谢

回复

使用道具 举报

ID:1037582 发表于 2022-12-26 17:42 | 显示全部楼层
这是通信程序代码,len1为数据长度,在程序过程中一直为0,进不去if语句
1672047586945.jpg
回复

使用道具 举报

ID:883242 发表于 2022-12-26 22:10 | 显示全部楼层
你没有控制收发器的DE/RE引脚。
回复

使用道具 举报

ID:420836 发表于 2022-12-27 03:42 | 显示全部楼层
消息接收过程是否包含在定时器中断程序中?
回复

使用道具 举报

ID:417460 发表于 2022-12-27 09:56 | 显示全部楼层
你尝试主机接收中断提高一个抢占优先级,或者从机延时发送数据。
回复

使用道具 举报

ID:77589 发表于 2022-12-27 10:50 | 显示全部楼层
RS485是主从通信,要想主机获取从机数据,必须让主机给从机发送获取数据命令,再让自己处于接收状态等待从机数据到来。
首先排查逻辑是否正确,再排查硬件配置。
回复

使用道具 举报

ID:1037582 发表于 2022-12-27 11:02 | 显示全部楼层
Hephaestus 发表于 2022-12-26 22:10
你没有控制收发器的DE/RE引脚。

您好,收发控制在发送和接收程序中有写了
回复

使用道具 举报

ID:1037582 发表于 2022-12-27 11:03 | 显示全部楼层
TTQ001 发表于 2022-12-27 03:42
消息接收过程是否包含在定时器中断程序中?

消息接收在中断中进行啊
回复

使用道具 举报

ID:1037582 发表于 2022-12-27 11:17 | 显示全部楼层
wangweijie 发表于 2022-12-27 09:56
你尝试主机接收中断提高一个抢占优先级,或者从机延时发送数据。

感谢意见,尝试过了,还是不行
回复

使用道具 举报

ID:384109 发表于 2022-12-27 14:24 | 显示全部楼层
代码不全,无法判断,另外感觉楼主对485概念由偏差,485根本来说也还只是串口通讯而已
回复

使用道具 举报

ID:513507 发表于 2022-12-27 16:24 | 显示全部楼层
主从通讯方式,主机给从机发送命令后,从机发送应答,主机接收从机应答信号后,接收从机信息
回复

使用道具 举报

ID:401564 发表于 2022-12-27 23:32 | 显示全部楼层
这也不是什么商业机密,直接上传工程文件不好吗?
我想验证一下,难道还要我对着图片一个字母一个字母的输入吗?
还有就是,不要老是自己认为问题会出现在那一段,然后想当然的把你认为不会出问题的地方排除了.......
回复

使用道具 举报

ID:1037582 发表于 2022-12-28 11:11 | 显示全部楼层
Y_G_G 发表于 2022-12-27 23:32
这也不是什么商业机密,直接上传工程文件不好吗?
我想验证一下,难道还要我对着图片一个字母一个字母的输入 ...

不上传工程文件,是因为这只是工程一小部分,我来是想请问大家遇到一些问题从哪方面开始思考解决,能给我开启新的思路,并不指望谁能马上给我解决问题;还有就是问题出在哪里,我能说出来就是我自己验证过了的,而且我是想请问是哪里引起的这个问题。并不是问题本身;也谢谢你对我提问方式的指教,我很少玩论坛,有不足的地方,感谢指正
回复

使用道具 举报

ID:1037582 发表于 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. //接收缓存区        
  10. u8 RS485_RX_BUF[64];          //接收缓冲,最大64个字节.
  11. //接收到的数据长度
  12. u8 RS485_RX_CNT=0;   
  13. void USART2_IRQHandler(void)
  14. {
  15.         u8 res;            

  16.         if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到数据
  17.         {         
  18.                                   
  19.                 res =USART_ReceiveData(USART2);         //读取接收到的数据
  20.                 if(RS485_RX_CNT<64)
  21.                 {
  22.                         RS485_RX_BUF[RS485_RX_CNT]=res;                //记录接收到的值
  23.                         RS485_RX_CNT++;                                                //接收数据增加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;        //复用推挽
  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);//复位串口2
  51.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位

  52.        
  53. #ifdef EN_USART2_RX                          //如果使能了接收
  54.         USART_InitStructure.USART_BaudRate = bound;//波特率设置
  55.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据长度
  56.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  57.         USART_InitStructure.USART_Parity = USART_Parity_No;///奇偶校验位
  58.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  59.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式

  60.   USART_Init(USART2, &USART_InitStructure); ; //初始化串口
  61.   
  62.         NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断
  63.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级2级
  64.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级2级
  65.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
  66.         NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  67.   USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
  68.    
  69.   USART_Cmd(USART2, ENABLE);                    //使能串口

  70. #endif

  71.   RS485_TX_EN=0;                        //默认为接收模式

  72. }

  73. //RS485发送len个字节.
  74. //buf:发送区首地址
  75. //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
  76. void RS485_Send_Data(u8 *buf,u8 len)
  77. {
  78.         u8 t;
  79.         RS485_TX_EN=1;                        //设置为发送模式
  80.           for(t=0;t<len;t++)                //循环发送数据
  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;                                //设置为接收模式       
  88. }
  89. //RS485查询接收到的数据
  90. //buf:接收缓存首地址
  91. //len:读到的数据长度
  92. void RS485_Receive_Data(u8 *buf,u8 *len)
  93. {
  94.         u8 rxlen=RS485_RX_CNT;
  95.         u8 i=0;
  96.         *len=0;                                //默认为0
  97.         delay_ms(10);                //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
  98.         if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了
  99.         {
  100.                 for(i=0;i<rxlen;i++)
  101.                 {
  102.                         buf[i]=RS485_RX_BUF[i];
  103.                 }               
  104.                 *len=RS485_RX_CNT;        //记录本次数据长度
  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);   //地址发送       
  121.         RS485_Receive_Data(rs485buf,&len1); //接收从机回馈
  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)//判断从机是否准备就绪
  130.                 {
  131.                         printf("接收到从机信号\r\n");
  132.                         data2 = rs485buf[1];
  133.                         len2 = rs485buf[2];//测量数据长度
  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校验错误,重新发送数据\r\n");
  164.                                                 flag3++;
  165.                                                 if(flag3 == 3)
  166.                                                 {
  167.                                                         printf("数据发送有误,请重新检查\r\n");       
  168.                                                         flag3 = 0;
  169.                                                 }
  170.                                                 return 0;                                       
  171.                                         }
  172.                 }
  173.                 else  //从机错误
  174.                 {
  175.                         static int flag1;
  176.                         printf("从机未准备就绪\r\n");
  177.                         flag1++;
  178.                         if(flag1 == 3)
  179.                         {
  180.                                 printf("通信错误,请重新检查设备\r\n");
  181.                                 flag1 = 0;
  182.                         }
  183.                         return 0;
  184.                 }
  185.                 len1 = 0;
  186.         }
  187.         return cnt;
  188. }

复制代码
回复

使用道具 举报

ID:1037582 发表于 2022-12-28 11:16 | 显示全部楼层
完整RS485通信代码已经上传,请各位大神指点
回复

使用道具 举报

ID:384109 发表于 2022-12-28 15:05 | 显示全部楼层
楼主还没完全理解串口通讯,就上手485通讯,出现这种情况是会比较难理解的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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