stm32与PLC(或者显控触摸屏通讯问题)

2019-07-20 11:32发布

    最近在弄stm32与PLC的ModBus通讯问题,现在问题是单片机和ModBus Poll调试助手通讯成功了,比如说调试助手给单片机发的数是01 03 00 00 00 01 84 0A单片机回发的数据帧是01 03 02 00 00 B8 44,但是用显控的触摸屏就不行了,我现在在触摸屏上设置了一个数值输入框,用的是功能码03的测试程序,每当点输入框写数进去时触摸屏上提示的是0x43错误代码,进仿真查看单片机收到和发出的数据帧,发现单片机收到的数据帧为01 03 00 00 00 00 84 0A,第6个字节(寄存器数量的低字节)和调试助手时不同,然后我转而用调试助手看单片机收到的数据,发现单片机收到的数据帧也是01 03 00 00 00 00 84 0A,如果是这样单片机怎么能和调试助手通讯上的?不知道怎么回事了,求原子哥解答,附上部分程序如下:(  码字好困难  求大神们好心解决  程序段后面的注释都是自己敲的啊啊!!!==!)
         void Usart2_Init(void)  //用的是USART2复用
{                                                                       
        GPIOD->CRL&=~0xeb400000;         
        GPIOD->CRL|=0x14b00000;
        USART2->BRR=0x1D4C;  //波特率4800  之所以用4800  因为我发现用其他的波特率单片机收到的数据帧都是乱码  目前还不知道是什么原因?
              USART2->CR1=0x202c;  //一个起始位 8个数据位 1个停止位
        NVIC_SetPriority(USART2_IRQn,10);        
        NVIC->ISER[1]|=(u32)1<<(38-32);                                  //开中断                                                                                                                                                                                                  
        Set_485_In();                                  //设置为485接收
}

void USART2_IRQHandler(void)  //中断服务函数
{
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //判断接收缓存区为非空
        {
         if (CommIndex < CommIndexEnd)                  //  CommIndex字节数量索引号初值0  CommIndexEnd为字节数初始值为8  
        {
                   aRxBuff[CommIndex]=USART2->DR;  //aRxBuff[]是接收缓存数组
                 if(aRxBuff[0]!= SlaveID)                           //判断主机设置的从站ID号是否正确
                                {
                                        CommIndex = 0;
                                        return ;
                                }
                        CommIndex++;
        }
        else                                                                   // 如果接收完毕
        {                    
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
                {                                                        
                    aRxBuff[CommIndexEnd]=USART2->DR;
                }
                    RecFinishF=1;                                     //  接收完成标志置1                                                                               }
                if(aRxBuff[0]== SlaveID)
        {
                 ParseRecieve();                                    //数据帧解析处理函数         
        }
                CommIndex=0;
                RecFinishF=0;         
        }
        }
}
void ParseRecieve()   //从主站读取的数据帧处理函数
{
        unsigned int  uIndex ;
        unsigned int crc16tem;
        unsigned char i = 0;
        if (aRxBuff[0] == SlaveID)  //判断从站地址是否正确
        {
    crc16tem=((unsigned int)(aRxBuff[CommIndexEnd-1]) << 8) | aRxBuff[CommIndexEnd]; // calculate CRC check, erase two CRC byte

    uIndex=crc16(aRxBuff,CommIndexEnd-1);//(((unsigned int)(temp[0]) *256) | temp[1]) ;  //计算CRC校验码

                if(crc16tem==uIndex)//如果计算的校验码和收到的校验码一致
                {
                        switch (aRxBuff[1])                                // 判断功能码
                          {

                        case PresetMulReg:        {Delay_my(5);Receive_10();}break;  //10功能码是写多字  这个函数是我所需要的  目前是拿03功能码做测试  还没有通讯上
                        case ReadHoldReg:   {Delay_my(5);Receive_03();}break;  //03功能码处理函数               
                        default:
                        for (i=0;i<=80;i++)
                                        Delay_my(15);
                        break;
                          }
                }
                else
                    {
                          for (i=0;i<=80;i++);  // delay
                                Delay_my(1);
                    }
          }
        }

void Receive_03() //03功能码是处理函数  感谢该贴吧一哥们提供
{
  u8 sendnum;
        u16  usDataLen;
        u16 crcDataHi;
        u16 crcDataLo;
        u8 count;
        u8 i;
if(aRxBuff[0] == SlaveID)   
        {       
                    sendnum = 5+(2*((aRxBuff[4] * 256)+ aRxBuff[5]));//回发的字节数
                                                        usDataLen = sendnum - 2;
                                                        aTxBuff[0] = aRxBuff[0];//从站地址
                                                        aTxBuff[1] = aRxBuff[1];//功能码
                                                        aTxBuff[2] = sendnum - 5;//回发的字节数
                                                        for(count = 3;aRxBuff[5]>0;aRxBuff[5]--)
                                                        {
                                                                aTxBuff[count] =  XBuf[count - 3]/256;//回发数据高字节
                                                                aTxBuff[count+1] = XBuf[count - 3]%256;//回发数据低字节
                                                                count = count + 2;
                                                        }
                                                        crcData = crc16(aTxBuff,usDataLen);
                                                        crcDataLo = crcData/256; //校验码低字节
                                                        crcDataHi = crcData%256; //校验码高字节
                                                        aTxBuff[sendnum -1] = crcDataHi;//CRC高
                                                        aTxBuff[sendnum -2] = crcDataLo;//CRC低
                                                        for(i = 0;i < sendnum;i++)
                                                        {       
                                                                Set_485_Out();
                                                               USART2_SendByte(aTxBuff[i]);
                                                                while(!(USART2->SR & USART_FLAG_TXE));
                                                        }
                                                        Set_485_In();         //复位 485接收状态
                                                        sendnum = 0;
  }
}




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
21条回答
wan-der
1楼-- · 2019-07-23 04:28
 精彩回答 2  元偷偷看……
lkjhbbb
2楼-- · 2019-07-23 05:01
wan-der 发表于 2016-3-19 22:17
原子哥  现在终于通讯上了  但是PLC的40001这种地址对应的是写双字   怎么让单片机的变量和接收到的这个 ...

你程序里面有考虑3.5T这些时间吗
biwfnso
3楼-- · 2019-07-23 08:56
wan-der 发表于 2016-3-5 14:28
显控的触摸屏,昨天调试一整天已经通讯上了,但是把显控触摸屏换成PLC还是通讯不上,这俩都是标准的ModBu ...

能把与显控触摸屏的程序借我看下吗?参考下、、biwfnso@163.com
谢谢!!

一周热门 更多>