一、基本环境
????????触摸屏:威纶通TK6071iP
????????开发板:STM32F103ZET6
? ? ? ? 物理层:RS-485
? ? ? ? 应用层:Modbus RTU
二、stm32核心代码
1)所有核心通信功能在接收中断中实现,不使用其他中断,整体逻辑是:首先接收数据,然后进行整理,最后发送返回值报文;
2)上位机将地址整段间隔设置为0,取消合并命令功能,指令发送和接收采用6x报文功能码(读操作为03H,写操作为06H),统一采取单个寄存器读/写的形式,这样可以大大简化从机(stm32)的通信协议。
u8 RS485_RX_CNT = 0;
u8 RS485_RX_BUFF[8] = {0};
u8 RS485_TX_BUFF[8] = {0};
u8 DataH = 0;
u8 DataL = 0;
void USART2_IRQHandler(void)//从机的接收中断
{
u8 res;
u8 err;
u8 i;
u16 RegAddr;
u16 RegNumb;
u16 calCRC;
if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
{
if(USART_GetFlagStatus(USART2,USART_FLAG_NE|USART_FLAG_FE|USART_FLAG_PE))
err = 1;
else
err = 0;
res = USART_ReceiveData(USART2); //接收数据
//上位机报文包含8字节
if((RS485_RX_CNT < 8)&&(err == 0))
{
RS485_RX_BUFF[RS485_RX_CNT]=res;
RS485_RX_CNT++;
}
//报文接收完毕,进行数据整理和返回
if(RS485_RX_CNT == 8)
{
RS485_RX_CNT = 0;
if(RS485_RX_BUFF[0] == 0x01)//判断从机地址
{
//若为读寄存器或写寄存器指令
if((RS485_RX_BUFF[1] == 0x03) || (RS485_RX_BUFF[1] == 0x06))
{
RegAddr = (((u16)RS485_RX_BUFF[2])<<8) | RS485_RX_BUFF[3];//读地址字节
RegNumb = (((u16)RS485_RX_BUFF[4])<<8) | RS485_RX_BUFF[5];
if((CRC_16(RS485_RX_BUFF,8))==0)//CRC校验通过
{
switch(RS485_RX_BUFF[1])//根据不同功能码,执行相应操作
{
case 0x03://读寄存器指令
//准备返回值
RS485_TX_BUFF[0] = RS485_RX_BUFF[0];
RS485_TX_BUFF[1] = RS485_RX_BUFF[1];
RS485_TX_BUFF[2] = RegNumb * 2;
for(i=0;i<RegNumb;i++)
{
RS485_TX_BUFF[3+i*2] = DataH;
RS485_TX_BUFF[4+i*2] = DataL;
}
calCRC = CRC_16(RS485_TX_BUFF,RegNumb*2+3);//生成校验位
RS485_TX_BUFF[RegNumb*2+3] = calCRC/256; //高8位
RS485_TX_BUFF[RegNumb*2+4] = calCRC%256; //低8位
//数据发送
RS485_RN = 1;
RS485_Send(RS485_TX_BUFF,RegNumb*2+5);
RS485_RN = 0;
break;
case 0x06:
//若为设置转速,则更新指令值
if(RegAddr == 0x2001)
{
DataH = RS485_RX_BUFF[4];
DataL = RS485_RX_BUFF[5];
}
//准备返回值
RS485_TX_BUFF[0]=RS485_RX_BUFF[0];
RS485_TX_BUFF[1]=RS485_RX_BUFF[1];
RS485_TX_BUFF[2]=RS485_RX_BUFF[2];
RS485_TX_BUFF[3]=RS485_RX_BUFF[3];
RS485_TX_BUFF[4]=RS485_RX_BUFF[4];
RS485_TX_BUFF[5]=RS485_RX_BUFF[5];
calCRC=CRC_16(RS485_TX_BUFF,6);
RS485_TX_BUFF[6] = (calCRC>>8)&0xFF;
RS485_TX_BUFF[7] = (calCRC)&0xFF;
//数据发送
RS485_RN = 1;
RS485_Send(RS485_TX_BUFF,8);
RS485_RN = 0;
break;
case 0x16:
break;
}
}
else
{
RS485_TX_BUFF[0]=RS485_RX_BUFF[0];
RS485_TX_BUFF[1]=RS485_RX_BUFF[1]|0x80;
RS485_TX_BUFF[2]=0x04;
RS485_RN = 1;
RS485_Send(RS485_TX_BUFF,3);
RS485_RN = 0;
}
}
else
{
RS485_TX_BUFF[0]=RS485_RX_BUFF[0];
RS485_TX_BUFF[1]=RS485_RX_BUFF[1]|0x80;
RS485_TX_BUFF[2]=0x02;
RS485_RN = 1;
RS485_Send(RS485_TX_BUFF,3);
RS485_RN = 0;
}
}
}
}
}
三、测试结果
??? ? ? 以电机控制为例,上位机控制界面如下图。测试结果表明,stm32可以与上位机之间顺利传送指令和数据,stm32接收和发送过程均正常。
?
?
?
?
|