STM32 跟触摸屏modbus-rtu通信问题(485)

2019-07-20 12:27发布

[mw_shl_code=c,true]void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)//判断是否发生TIM2更新中断 { TIM_Cmd(TIM2,DISABLE); //关掉定时器2 TIM_SetCounter(TIM2, 0);//重新设初值0 if(recenum >= 8) { Uart1_rev_flag = 1;//接收完毕一帧,置位标志位,通知主函数调用接收处理函数 USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//失能串口1接收中断 } recenum = 0; GPIO_SetBits(GPIOF,GPIO_Pin_13);//485发送使能 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除TIM2的中断待处理位 TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM2待处理标志位 } } void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收中断 { USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除USART1中断待处理位RXNE(RXNE=0) if(Uart1_rev_flag != 1) { if(recenum < 12)//接收分8字节数据 和11字节数据 { ReceBuf[recenum] = USART1->DR; recenum++; TIM_Cmd(TIM2, ENABLE); TIM_SetCounter(TIM2, 0); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); } } } /*if(USART_GetITStatus(USART1,USART_IT_TXE)!=RESET) { USART_ClearITPendingBit(USART1,USART_IT_TXE);//清除USART1中断待处理位RXNE(RXNE=0) USART_SendData(USART1,ReceBuf[sendnum]); sendnum++; if(sendnum == 8) { LED4(ON); sendnum = 0; USART_ITConfig(USART1,USART_IT_TXE,DISABLE); //USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//打开接收中断使能 //GPIO_ResetBits(GPIOF,GPIO_Pin_13);//485使能接收 } }*/ //溢出-如果发生溢出需要先清空SR的溢出位,再读DR寄存器 则可清除不断入中断的问题 if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)!=RESET) { USART_ClearFlag(USART1,USART_FLAG_ORE); //清溢出位 USART_ReceiveData(USART1); //读DR } }[/mw_shl_code] 这是我中断函数,为什么我接收到的第一个数据不是设备地址0x01,但是我用串口监控,看到的是01 03 00 00 00 01 84 0A,但是接收之后就不行了
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
258233569@qq.co
1楼-- · 2019-07-24 20:20
我想 问下  我现在用stm32作主机然后连接触摸屏与从机(pc)通信,想问下思路
wan-der
2楼-- · 2019-07-24 23:29
 精彩回答 2  元偷偷看……
翱翔云端的鸟
3楼-- · 2019-07-25 04:55
wan-der 发表于 2016-2-23 16:40
这个问题我最近也遇到了   收到的第一个字节从站设备地址一直不对   把波特率设高了也没用啊   
然后想问 ...

aRxBuff[4] 和 aRxBuff[5]  是寄存器数量的高位和低位   这样是将十六进制转为十进制
这里要乘以2是因为传输是是无符号的16位数据  每个数据占两个字节
(aRxBuff[4] * 256 + aRxBuff[5])*2 =  要返回的数据字节数
前面的5  分开来   从机地址+功能码+数据字节数+CRC低+CRC高
所以:Sendnum = 回发的总字节数


usDataLen = sendnum - 2; 是除去CRC校验的字节数
因为CRC校验是在前面这些数据的基础上计算的   在计算CRC校验时只需要前面的数据
也就是crcData = crc16(ReceBuf,usDataLen);
wan-der
4楼-- · 2019-07-25 10:03
翱翔云端的鸟 发表于 2016-2-24 09:28
aRxBuff[4] 和 aRxBuff[5]  是寄存器数量的高位和低位   这样是将十六进制转为十进制
这里要乘以2是因为 ...

感谢百忙之中回复!昨天我用仿真看结果,出现一个问题,在判断功能码操作之前的CRC校验不对(我的程序跟你的有所不同,我需要的功能码是写多个寄存器)程序不能继续往下走,所以用调试助手给从机发的数据一直得不到回复,是因为有误码的原因吗?我把波特率设置成9600以上误码率很高啊,相反波特率降低成4800或者2400误码却较少(接收到的数据帧时对时错),我也整的没招了,这是仿真出现错误部分的程序
if (aRxBuff[0] == SlaveID)
        {
            
      crc16tem=((unsigned int)(aRxBuff[CommIndexEnd-1]) << 8) |
      aRxBuff[CommIndexEnd];   //CommIndexEnd是接收长度   
                                                          //CommIndex是数据位置索引
     uIndex=crc16(aRxBuff,CommIndex-1);//(((unsigned int)(temp[0]) *256) | temp[1]) ;
      if(crc16tem==uIndex)  //此处CRC校验一直不对,是有误码存在的原因吗?
                                                       //CRC16这个计算函数与你的程序中是一样的
    {
  此处判断功能码然后数据解析回发;
    }
    }
ktye
5楼-- · 2019-07-25 10:33
 精彩回答 2  元偷偷看……
wan-der
6楼-- · 2019-07-25 11:56
翱翔云端的鸟 发表于 2016-2-24 09:28
aRxBuff[4] 和 aRxBuff[5]  是寄存器数量的高位和低位   这样是将十六进制转为十进制
这里要乘以2是因为 ...

补充一哈,利用ModBus Poll 调试助手给板子发数据时出现Framing error 和checksum error,然后就连接超时了,是误码造成的吗?

一周热门 更多>