最近在弄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;
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
你程序里面有考虑3.5T这些时间吗
一周热门 更多>