MODBUS&UART&CAN
约 2103 字大约 7 分钟
2025-05-27
MODBUS&UART&CAN&GPIO
MODBUD RTU
这是一种二进制的单主多从的传输协议。
一些重要的概念 :
ADU:应用数据单元
PDU:协议数据单元
MSB:最高有效位
LSB:最低有效位
在RTU模式里里面,消息的发送和接受至少间隔3.5个字符时间,字符时间和波特率(1秒种能传输的字节数量),如果在这时间之外的所有情况,都将被丢弃。
0:表示广播,除此之外均只有指定的从站才能回应


功能码域:
03:读保持寄存器、04:读输入寄存器、06:预置单个保持寄存器
CRC:
即循环冗余校验:
用于在接受方接受之前进行正确性的校验,常见的有奇偶校验、因特网校验、循环冗余校验。
modbus-crc16 校验原理
注释
需要一个0xFFFF的寄存器
把一个8位的二进制数据,和CRC的低八位进行异或,把结果存储到寄存器.
CRC右移动过一位,高位补0,如果移除的是1,那么就和多项式A001进行异或
重复步骤3、4,直到8此,处理完整个通信信息帧的数据
重复2、5处理通信帧的下一个字节。
计算完成之后将CRC的高位和低位交换。
//举个例子
unsigned short CR =0xFFFF;
unsigned short RET =0;
for(auto& message:messages)
{
CR = message ^ CR;//[!code hitght] 第二步
for(int i=0;i<8;i++)
{
if(CR&0x01)//先检验最后一位是不是1
{
//进行第三步
CR =CR>>1;
CR = CR ^0xA001;
}
else
{
CR = CR>>1;
}
}//进行4
}//进行5
//进行6
RET = CR>>8;
RET = RET |(CR<<8);
return RET;GPIO
General Purpose input/output:
可以编程控制对应格式引脚的工作模式,也可以编程控制它的电压高低等等,从而使实现设备控制。


提醒
GPIO有八种模式
- 输入模式 -> 输入浮空、输入上拉、输入下拉、模拟输入
- 输出模式->开漏输出、开漏复用功能、推挽输出、推挽复用功能
[详细介绍-GPIO](GPIO详解 - 一步一磕头的菜鸡 - 博客园)
利用文件io的方式操作GPIO
通知
/sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号
/sys/class/gpio/unexport用于通知系统取消导出
/sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号base,寄存器名称,引脚总数
计算过程:
- 计算引脚编号=控制引脚的寄存器基数+控制引脚寄存器的位数
- 向/sys/class/gpio/export写入编号
- direction文件,定义输入方向,direction接受的参数:in,out,high,low。
- value文件是端口的数值,为1或者为0。
uart
:::tips struct termios
| 成员 | 作用 |
|---|---|
c_cflag | 控制模式标志(Control Flags),设置硬件参数:波特率、数据位、停止位、流控制等。 |
c_iflag | 输入模式标志(Input Flags),控制输入数据的预处理(如字符转换、软件流控制等)。 |
c_oflag | 输出模式标志(Output Flags),控制输出数据的处理(如换行符转换)。 |
c_lflag | 本地模式标志(Local Flags),控制终端的本地行为(如回显、信号处理)。 |
c_cc | 控制字符数组(Control Characters),定义特殊字符(如 Ctrl+C)和非规范模式下的超时参数。 |
c_ispeed | 输入波特率(Input Baud Rate)。 |
c_ospeed | 输出波特率(Output Baud Rate)。 |
:::
c_cc是一个unsigned char 类型的数组,用于定义终端控制字符和非规范模式下面的超时参数。
VINTRCtrl+C发送 SIGINT信号(中断进程)。VQUITCtrl+\发送 SIGQUIT信号(退出进程并生成核心转储)。VERASEBackspace删除前一个字符。 VKILLCtrl+U删除整行输入。 VEOFCtrl+D表示文件结束(End-of-File)。 VTIME- 非规范模式专用:读取超时时间(单位:100ms)。 VMIN- 非规范模式专用:最少读取字符数。
#include<fcntl.h>
#include<unisted.h>
int main()
{
const char * device = "/dev/tty";//这个地方的是表示串口设备的路径
if fd =open (device ,O_RDWR|O_NOCTTY);
//O_NOCTTY 不会让打开的文件成为该进程的控制终端
//O_NDELAY:不关心DCD信号线所处的状态、如果不指定这个标志,进程会一直处于睡眠状态,直到DCD信号线被激活。
if(fd<0)
{
perror("无法打开串口");
return -1;
}
}#include<termios.h>
//里面有一个termio结构体
//通过ictol系统调用可以操作DTR引脚的电平状态
#include<sys/ioctl.h>
int ioctl (int fd , usigned ling request,...);
//成功返回零,一些会返回一个有意义的值来表示成功,并以-1表示失败同时设置errno。
// The second argument is a device-dependent request code . the third argument is an nuntyped pointer to memory.
if(ioctl(fd,TIOCMBIS,&TICOM_DTR)<0)//拉低DTR
{
perror("ioctl(TIOCMBIS) 失败");
close(fd);
return -1;
}#include <termios.h>
struct termios options;
// 获取当前串口配置
if (tcgetattr(fd, &options) < 0) {
perror("tcgetattr 失败");
close(fd);
return -1;
}
// 设置输入输出波特率为 115200
cfsetispeed(&options, B115200); // 输入波特率
cfsetospeed(&options, B115200); // 输出波特率
//修改控制标志
options.c_cflag | = CLOCAL;//忽略调制器控制信号,强制本地链接。
options.c_cflag | = CREAD;//启用接受功能
options.c_cflag & = ~PARENB;//禁用校验位
options.c_cfalg & = ~CSTOPB;//设置停止位
options.c_cfalg & = ~CSIZE;//清楚数据位长度标志
options.c_cfalg | = CS8;//设置数据位8位
{
options.c_cflag | = PARENB;//启用校验位(奇偶)
options.c_cflag & = ~PARODD;//关闭奇校验
options.c_iflag |=INPCK ;//启用输入奇偶校验
}
//CSTOPB 设置停止位默认是1
//CRTSCTS启用RTS/CTS硬件流控制
//IXON IXOFF IXANY 软件流控制,允许发送发通过XOFF暂停,XON恢复发送
//IXOFF允许接受方发送XOFF通知发送方暂停
//ICSNY允许通过任意字符恢复
// 应用配置
if (tcsetattr(fd, TCSANOW, &options) < 0) {
perror("tcsetattr 失败");
close(fd);
return -1;
}- c_cflag (硬件参数:波特率,数据位,校验位,流控制)
| 标志位 | 作用 |
|---|---|
CLOCAL | 忽略调制解调器控制信号(如 DCD),强制本地连接。 |
CREAD | 启用接收功能(必须设置,否则无法读取数据)。 |
CSIZE | 数据位长度掩码(需与 CS5、CS6、CS7、CS8 结合使用)。 |
CS5-CS8 | 设置数据位长度(5-8 位)。 |
CSTOPB | 设置停止位:0=1位,1=2位。 |
PARENB | 启用奇偶校验位。 |
PARODD | 奇校验(需与 PARENB 一起设置);若未设置则为偶校验。 |
CRTSCTS | 启用 RTS/CTS 硬件流控制。 |
HUPCL | 关闭设备时自动挂断(拉低 DTR 信号)。 |
- c_iflag(输入数据的预处理)
| 标志位 | 作用 |
|---|---|
IGNBRK | 忽略 BREAK 条件(如连续低电平)。 |
BRKINT | BREAK 条件会触发 SIGINT 信号(需与 IGNBRK 互斥)。 |
IGNPAR | 忽略奇偶校验错误的数据帧。 |
PARMRK | 标记奇偶校验错误(在错误字节前添加 \377\0)。 |
INPCK | 启用输入奇偶校验检查(需同时启用 PARENB)。 |
ISTRIP | 将输入字符截断为 7 位(通常禁用)。 |
INLCR | 将接收到的换行符 \n 转换为回车符 \r。 |
IGNCR | 忽略接收到的回车符 \r。 |
ICRNL | 将接收到的回车符 \r 转换为换行符 \n(常用于终端兼容)。 |
IXON | 启用输出软件流控制(XON/XOFF)。 |
IXOFF | 启用输入软件流控制(XON/XOFF)。 |
IXANY | 允许任意字符恢复被暂停的输出(默认需 XON)。 |
- c_lflag (终端交互的行为)
| 标志位 | 作用 |
|---|---|
ICANON | 启用规范模式(行缓冲输入,逐行处理数据)。 |
ECHO | 回显输入字符(如用户在终端输入时显示字符)。 |
ECHOE | 在规范模式下,退格键(ERASE)会擦除屏幕上的字符。 |
ECHOK | 在规范模式下,KILL 字符会擦除整行。 |
ECHONL | 回显换行符(即使 ECHO 被禁用)。 |
ISIG | 启用终端信号(如 Ctrl+C 发送 SIGINT,Ctrl+Z 发送 SIGTSTP)。 |
IEXTEN | 启用扩展功能(如 Ctrl+V 字面输入)。 |
NOFLSH | 禁止在接收到 SIGINT 或 SIGQUIT 时清空输入输出队列。 |
TOSTOP | 后台进程尝试写终端时发送 SIGTTOU 信号。 |
- c_oflag
| 标志位 | 作用 |
|---|---|
OPOST | 启用输出处理(如换行符转换)。若禁用,输出为原始数据。 |
ONLCR | 将换行符 \n 转换为回车换行 \r\n。 |
OCRNL | 将回车符 \r 转换为换行符 \n。 |
ONLRET | 忽略回车符 \r。 |
