通知:所有Qt源码和文档会在后面公布。敬请期待…

图片

常见的硬件通信接口协议

   1.硬件通信接口协议

      很多硬件传感器需要用到如下的通信协议

           串口(上层应用的串口代码编写,不是底层的串口代码编写)

  •            SPI

  •            IIC

  •            CAN

  •            USB

   2.使用串口的传感器

          串口蓝牙,串口wifi

          开发板跟电脑


串口通信的代码实现

   常见的硬件校验算法有哪些?算法原理是怎么样?

  •           CRC校验 –》循环冗余校验

  •           哈希校验 

   1.两个版本

            QT中的串口编程(既可以在window上运行,也能在ARM平台,linux平台都能运行)

            linux中的串口编程(只能在ARM平台,linux平台运行)

      波特率: 串口传输数据的速度  115200表示每一秒钟传输115200个比特位

      数据位:串口传输一帧数据的位数

      奇偶校验:校验–》检查数据收发是否发生了错误

                        奇校验

                        偶校验

      停止位:标记数据的结尾

      流控: 当数据的接收端无法收到数据的时候,会通知发送端停止发送

图片

   2.QT中的串口编程

            类和方法

                   添加的库.pro:  serialport

QSerialPortInfo //获取当前系统中所有的串口信息QSerialPort //表示串口

           (1)代码思路

                   第一步:获取当前系统所有的串口信息

[static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts()返回值:  QList存放的就是所有的串口信息QString QSerialPortInfo::description() const返回:串口的描述信息QString QSerialPortInfo::portName() const返回:串口的名字

                   第二步:创建QSerialPort 串口对象,配置串口的参数      

QSerialPort::QSerialPort(const QString &name) 参数:name --》串口的名字bool setBaudRate(qint32 baudRate) 参数:baudRate --》你要设置的波特率 QSerialPort::Baud115200bool setDataBits(QSerialPort::DataBits dataBits) 参数:dataBits --QSerialPort::Data8 8位数据位bool setParity(QSerialPort::Parity parity) 参数:parity --QSerialPort::NoParity 无奇偶校验 QSerialPort::EvenParity 偶校验 QSerialPort::OddParity 奇校验bool setStopBits(QSerialPort::StopBits stopBits) 参数:stopBits --QSerialPort::OneStop 1位停止位 QSerialPort::OneAndHalfStop 1.5位停止位bool setFlowControl(QSerialPort::FlowControl flowControl) 参数:flowControl --QSerialPort::NoFlowControl 无流控 QSerialPort::HardwareControl 硬件流控 QSerialPort::SoftwareControl 软件流控

                   第三步:打开串口

bool QSerialPort::open(QIODevice::OpenMode mode)

                   第四步:读写串口数据

                                    读串口–》接收对方从串口发送过来的数据

[signal] void QIODevice::readyRead() //关联这个信号,在槽函数中读取数据 read/readAll

                                    写串口–》你把数据从串口发送给对方               

 write

                   第五步:关闭串口    

void QSerialPort::close()

图片

   3.实际开发使用串口的时候,参数究竟配置成什么样??

                答案:认真阅读传感器厂家提供的使用说明书–》清楚地告诉你串口该如何配置


linux中串口编程

    1.重要的结构体      

 struct termios{  里面都是标志位,用来设置串口参数  c_cflag   //控制模式标志位}

    2.思路和方法

                 第一步:打开串口的驱动

                                        连接电脑        –》/dev/ttySAC0

                                        右上角第一排 –》/dev/ttySAC1

                                        右上角第二排 –》/dev/ttySAC2

                                        右上角第三排 –》/dev/ttySAC3

                                        open()

                 第二步:配置串口        

#include <termios.h>#include <unistd.h>int tcgetattr(int fd, struct termios *termios_p); //获取当前串口的配置信息 参数: fd --》串口的文件描述符            termios_p --》结构体指针,用来保存串口配置信息

 (1)设置串口工作在原始模式(串口只用于数据的收发,不用做其它功能)                        

struct termios  myios;bzero(&myios,sizeof(myios));myios.c_cflag |=  CLOCAL | CREAD; void cfmakeraw(struct termios *termios_p);

(2)设置波特率,数据位,停止位,奇偶校验…….                                       

波特率:int cfsetispeed(struct termios *termios_p, speed_t speed);int cfsetospeed(struct termios *termios_p, speed_t speed);参数:speed --》你要设置的波特率B115200 B数字(就是波特率)
数据位:myios.c_cflag &= ~CSIZE; /* 用数据位掩码清空数据位设置 */myios.c_cflag |= CS8;  //CS5    CS6    CS7    CS8
奇偶校验:奇校验myios.c_cflag |= (PARODD | PARENB);myios.c_iflag |= INPCK; 偶校验myios.c_cflag |= PARENB;myios.c_cflag &= ~PARODD;/* 清除奇校验标志,则配置为偶校验*/ myios.c_iflag |= INPCK;无校验myios.c_cflag &= ~PARENB; //使能 --》开启 失能 --》关闭
停止位myios.c_cflag &= ~CSTOPB;      1位停止位myios.c_cflag |= CSTOPB;       2位停止位

 设置最少读取的字符数量和最长等待时间                                        

myiosc_cc[VTIME] = 0;myios.c_cc[VMIN] = 4;

  让刚才的设置生效(激活配置)                                         

int tcflush(int fd, int queue_selector);参数:  fd --》串口的文件描述符          queue_selector --》TCIOFLUSH  刷新串口的输入输出缓冲区tcsetattr(int fd, int optional_actions, const struct termios*termios_p);参数:  fd --》串口的文件描述符          optional_actions --》TCSANOW  设置立即生效

                 第三步:收发数据 

                                        发送 write()

                                        接收 read()

                 第四步:关闭串口

                                        close()


串口的应用–》通过串口读写获取RFID的卡号

图片

   1.分析RFID的通信协议

               通信协议:硬件传感器依照什么样的数据格式去发送/接收数据

                                类似于tcp通信发送字符串/发送表情包

   2.分析ISO14443A命令

               A命令(请求):   激活RFID读卡模块,使之能够对外发射电磁场,当有卡靠近模块的时候,模块能够感应到卡的存在

char abuf[7];abuf[0]=0x07; //帧长abuf[1]=0x02; //ISO14443Aabuf[2]='A'// A命令abuf[3]=0x01; //信息长度abuf[4]=0x52; //ALL模式abuf[5]=校验和;abuf[6]=0x03; //帧结束标记//发送A命令给模块write(fd,abuf,7); //串口发送A命令给RFID读卡模块 主机--》从机 命令
//接收模块回复的应答信息char rbuf[8];read(fd,rbuf,8); 从机--》主机 状态//判断接收的应答信息是否正确 if(rbuf[2]==0x00) //应答成功 printf('A命令发送成功了!n');else printf('A命令没有发送成功了!n');B命令(防碰撞): 防止多张卡同时进入磁场范围,出现读写冲突的问题(只会挑选其中一张来读写)char bbuf[8];bbuf[0]=0x08; //帧长bbuf[1]=0x02; //ISO14443Abbuf[2]='B'// B命令bbuf[3]=0x02; //信息长度bbuf[4]=0x93; //一级防碰撞bbuf[5]=0x00; bbuf[6]=校验和;bbuf[7]=0x03; //帧结束标记//发送B命令给模块write(fd,bbuf,8); //串口发送B命令给RFID读卡模块 主机--》从机 命令//接收模块回复的应答信息charrbuf[10];read(fd,rbuf,10); 从机--》主机 状态//判断接收的应答信息是否正确 if(rbuf[2]==0x00) //应答成功 printf('B命令发送成功了,同时得到了序列号!n'); //卡的序列号 rbuf[4]rbuf[5]rbuf[6]rbuf[7]else printf('B命令没有发送成功了!n');

练习:(源码下节公布)

   1.循环给RFID模块发送AB命令,打印得到的卡序列号

int main(){         open('/dev/ttySAC1')// 串口驱动         //配置串口         while(1)         {                 发送A命令                 发送B命令         }}

           老师给的参考代码:

                  第一个:以非阻塞的方式打开串口(无论串口是否有数据可读,read去读取串口数据的时候都不会阻塞)

fd = open('/dev/ttySAC1', O_RDWR | O_NOCTTY | O_NONBLOCK);

                  第二个:使用了多路复用监测串口是否有数据可读(可读就调用read去读取模块的响应信息)

                  第三个:延时–》while(1)执行速度太快了,串口的读写速度跟不上,所以适当延时一下      

图片

图片