【电机控制】RS485通讯MODBUS协议实验
【电机控制】RS485通讯MODBUS协议实验 @TOC 前言 1.STLINK仿真器 2.USB-TTL 3.USB转RS485 4.RS485转TTL 5.STM32控制器 6.上位机SSCOM(带MODBUS协议) 提示:以下是本篇文章正文内容,下面案例可供参考 一、串口数据格式 串口通信帧数据如此,每帧由空闲位、起始位、数据位、校验位、停止位组成 传输的数据是低位在前高位在后 从低到高,1000 1101,每位104us 9600bps就是每秒传输9600bit(位)的意思,也就相当于:1/9600=1.041666666666667e-4秒为每个bit的传输时间,也即104us 二、示波器解析串口数据 1.上位机发送数据 发送字符1,对应ASCII理论值十进制为49 上位机发送数据波形 2、3、4、5、6、7、8、9组成8位数据 反馈为 0011 0001 2.MCU接收数据波形 1.加上光耦隔离 2.不加光耦隔离 可以看出,加了光耦,数据接收异常; 不加光耦,数据接收正常 三、MODBUS协议格式 四、代码 1.实验一:发送010600010055 2.实验二:发送010600010056 void TestOpr(void) { /* 这里只是演示,不具实际意义 */ if (regGroup[1] == 0x55) { printf("驱动电机A !\r\n"); regGroup[1] = 0; //这里是为了防止重复输出 } else if (regGroup[1] == 0x56) { printf("驱动电机B !\r\n"); regGroup[1] = 0; //这里是为了防止重复输出 } } 3.实验三:发送010600010017 void UartDriver(void) { static unsigned char len; static unsigned char buf[64]; unsigned char i; unsigned char cnt; unsigned int crc; unsigned char crch,crcl; if (From_Flag) //帧接收完成标志,即接收到一帧新数据 { From_Flag = 0; //帧接收完成标志清零 len = UartRead(buf,sizeof(buf)); //将接收到的命令读到缓冲区中 crc = GetCRC16(buf,len-2); //计算CRC校验值,除去CRC校验值 crch=crc >> 8; //crc高位 crcl=crc & 0xFF; //crc低位 printf("485接收数据\r\n"); for(i = 0;i

【电机控制】RS485通讯MODBUS协议实验
@TOC
前言
1.STLINK仿真器
2.USB-TTL
3.USB转RS485
4.RS485转TTL
5.STM32控制器
6.上位机SSCOM(带MODBUS协议)
提示:以下是本篇文章正文内容,下面案例可供参考
一、串口数据格式
串口通信帧数据如此,每帧由空闲位、起始位、数据位、校验位、停止位组成
传输的数据是低位在前高位在后
从低到高,1000 1101,每位104us
9600bps就是每秒传输9600bit(位)的意思,也就相当于:1/9600=1.041666666666667e-4秒为每个bit的传输时间,也即104us
二、示波器解析串口数据
1.上位机发送数据
2、3、4、5、6、7、8、9组成8位数据
反馈为 0011 0001
2.MCU接收数据波形
1.加上光耦隔离
2.不加光耦隔离
三、MODBUS协议格式
四、代码
1.实验一:发送010600010055
2.实验二:发送010600010056
void TestOpr(void)
{
/* 这里只是演示,不具实际意义 */
if (regGroup[1] == 0x55)
{
printf("驱动电机A !\r\n");
regGroup[1] = 0; //这里是为了防止重复输出
}
else if (regGroup[1] == 0x56)
{
printf("驱动电机B !\r\n");
regGroup[1] = 0; //这里是为了防止重复输出
}
}
3.实验三:发送010600010017
void UartDriver(void)
{
static unsigned char len;
static unsigned char buf[64];
unsigned char i;
unsigned char cnt;
unsigned int crc;
unsigned char crch,crcl;
if (From_Flag) //帧接收完成标志,即接收到一帧新数据
{
From_Flag = 0; //帧接收完成标志清零
len = UartRead(buf,sizeof(buf)); //将接收到的命令读到缓冲区中
crc = GetCRC16(buf,len-2); //计算CRC校验值,除去CRC校验值
crch=crc >> 8; //crc高位
crcl=crc & 0xFF; //crc低位
printf("485接收数据\r\n");
for(i = 0;i < len;i ++)
printf("485接收的值 = buf[%d] = %x \r\n",i,buf[i]);
if((buf[len-2] == crch) && (buf[len-1] == crcl)) //判断CRC校验是否正确
{
/* 在点对多点的应用中,这里还需要加上一条,判断报文的地址是否和本机地址一致,否则不作处理 */
/* 可设置不同从机为不同地址,用以区分报文是发给谁的,相同则处理,不同则不作处理 */
switch (buf[1]) //按功能码执行操作
{
case 0x03: //读数据
if((buf[2] == 0x00) && (buf[3] <= 0x05)) //寄存器地址支持0x0000~0x0005
{
if(buf[3] <= 0x04)
{
i = buf[3]; //提取寄存器地址
cnt = buf[5]; //提取待读取的寄存器数量
buf[2] = cnt*2; //读取数据的字节数,为寄存器*2,因modbus定义的寄存器为16位
len = 3; //响应帧第4个字节开始为数据
while(cnt --)
{
buf[len ++] = 0x00; //寄存器高字节补0
buf[len ++] = regGroup[i ++]; //低字节
}
}
break;
}
else //寄存器地址不被支持时,返回错误码
{
buf[1] = 0x83; //功能码最高位置1
buf[2] = 0x02; //设置异常码为02-无效地址
len = 3;
break;
}
case 0x06: //写入单个寄存器
if((buf[2] == 0x00) && (buf[3] <= 0x05)) //寄存器地址支持0x0000-0x0005
{
if(buf[3] <= 0x04)
{
i = buf[3]; //提取寄存器地址
regGroup[i] = buf[5]; //保存寄存器数据
}
len -= 2; //长度-2以重新计算CRC并返回原报文
break;
}
else
{ //寄存器地址不被支持,返回错误码
buf[1] = 0x86; //功能码最高位置1
buf[2] = 0x02; //设置异常码为02-无效地址
len = 3;
break;
}
default: //其他不支持的功能码
buf[1] = 0x80; //功能码最高位置1
buf[2] = 0x01; //设置异常码为01—无效功能
len = 3;
break;
}
crc = GetCRC16(buf,len); //计算CRC校验值
buf[len ++] = crc >> 8; //CRC高字节
buf[len ++] = crc & 0xff; //CRC低字节
Send_Data(buf,len); //发送响应帧
}
else /* 如果校验值错误,执行错误处理函数 这里用串口1打印一条提示信息 也可自定义共它处理函数 */
printf("接收错误\r\n");
}
}
五、实验
0.实物接线
USB-TTL TXD- MCU-RXD PA10
USB-TTL RXD- MCU-RXD PA9
USB转485 A- RS485转TTL A
USB转485 B- RS485转TTL B
USB转485 RXD- MCU-RXD PA3
USB转485 GND- MCU-GND
1.实验一
2.实验二
3.实验三
六、参考资料
MODBUS通讯协议中文版.pdf
隔离串口通信电路设计注意事
Ascii(256个) 编码表 完整码表 ASCII编码 ASCII表 ASCII码 二进制 十进制 八进制 十六进制
隔离串口通信电路设计注意事
STM32开发(六)STM32F103 通信 —— RS485 Modbus通信编程详解
STM32F1之485通信
STM32F103C8T6的MODBUS-RTU通讯(485通讯)
基于STM32以及modbus——RTU的从机程序(STM32作为从机)
并行,串行,同步,异步与UART,串口,TTL,RS232,RS485相关概念认识与解读
总结
本文仅仅简单介绍了【电机控制】RS485通讯MODBUS协议实验,评论区欢迎讨论。