RK3568平台(UART篇)uart应用编程读取模块数据

一.串口介绍

串口设备是嵌入式开发中最常用的外设之一,通过串口打印信息可以调试程序的运行,通 过串口也可以链接很多种外设,比如串口打印机,蓝牙,wifi,GPS,GPRS 等等。

数据传输方式:

串口通信使用的是串行传输方式,即将数据按照顺序一个一个地发送或接收。每个数据位 都在一定的时间间隔内发送或接收。串口使用两条数据线(TXD,RXD)和一条地线(GND) 进行传输。

数据格式:

串口通信使用的是异步传输方式,数据被分成固定大小的数据帧,每个数据帧由起始位、 数据位、校验位和停止位组成,通常称为“帧”。其中起始位和停止位用于标识数据帧的开始和 结束,校验位用于检验数据传输的准确性。数据位的数量一般为 7 位或 8 位。

波特率:

波特率是指数据传输的速度,也称为比特率,表示每秒钟可以传输多少个二进制数据位。 波特率越高,数据传输的速度就越快。常见的波特率有 9600bps、19200bps、38400bps、115200bps 等。

二.串口节点介绍

在嵌入式设备中,串口设备通常以字符设备节点的形式出现在 Linux 系统中。在 Linux 系 统中,每个设备都由一个设备节点(device node)来表示,设备节点是与设备相关联的一个文 件,以/dev 目录下的文件形式存在。 串口设备节点通常以 tty 开头,具体命名方式根据串口的类型和数量不同而不同。开发板 系统启动之后,使用以下命令打印终端设备节点。

查看串口ttyS2是否有数据输出:

cat /dev/ttyS2

 三.使用uart读取模块串口数据

下图为uart读取一帧数据,数据位所代表的解析:

串口编程:解析串口数据

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>

#define MCU_TTY_PORT    "/dev/ttyS2"

int input_fd = -1;

static unsigned int Temp_data;
static unsigned int Humi_data;
static unsigned int PM25_data;
static unsigned int PM10_data;
static unsigned int VOC_data;
static unsigned int CO2_data;

static void unpackMcuData(unsigned char *buf, int size)
{
    if (size < 5) {
        return;
    } 

    if (buf[0] != 0x55 && buf[1] != 0xaa) {
        return;
    }

    int dataSize = (int)buf[2];
    if ((buf[dataSize+ 2] != 0x0d) && (buf[dataSize + 2] != 0x0a)) {
        return;
    }

    unsigned char crc = 0;
    for (int i = 2; i < dataSize + 1; i++) {
        crc ^= buf[i];
    }

    if (crc != buf[dataSize + 1]) {
        return;
    }

    switch (buf[3]) {
        case 0x02 : {
            PM25_data = 0;
            PM25_data |= (((int)buf[9] & 0xff) << 8); //PM2.5 H
            PM25_data |= ((int)buf[10] & 0xff);        //PM2.5 L
			
			PM10_data = 0;
            PM10_data |= (((int)buf[11] & 0xff) << 8); //PM10 H
            PM10_data |= ((int)buf[12] & 0xff); //PM10 L
            break;
        }
        case 0x03 : {
            VOC_data = 0;
			VOC_data = ((int)buf[4] & 0xff) * 256 + ((int)buf[5] & 0xff);
            break;
        }
        case 0x04 : {
            if((int)buf[5] == 0x17)
            {
                CO2_data = ((int)buf[8] & 0xff) * 256 + ((int)buf[9] & 0xff);
            }
            break;
        }
        case 0x05 : {
            Temp_data = 0;
			Humi_data = 0;
			Humi_data = ((int)buf[4] & 0xff) * 100 + ((int)buf[5] & 0xff);
			Temp_data = ((int)buf[6] & 0xff) * 100 + ((int)buf[7] & 0xff);
            break;
        }
        default : break;
    }
}

void *getMcuData(void *ptr)
{
    #if 1
    struct termios new_options, old_options;
    fd_set r_fds;
    struct timeval timeout;
    #define SET_IO_SPEED B115200
    static unsigned char _cmdLine[64];
    static unsigned int _u8ReceivedBytes = 0;
    int ret = 0;
    input_fd = open(MCU_TTY_PORT, O_RDWR| O_NOCTTY | O_NDELAY );
    if(input_fd == -1)
    {
        ALOGW(" error open %s\n", MCU_TTY_PORT);
        return 0;
    }
    //fcntl(input_fd, F_SETFL, FNDELAY);
    tcgetattr(input_fd, &old_options);
    // config ttyS0 not do local ECHO, turn off flow control
    tcgetattr(input_fd, &new_options);
    new_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ISIG);
    new_options.c_iflag  &= ~(INPCK | INLCR | ICRNL | IUCLC | IXON | IXOFF);
    new_options.c_oflag  &= ~OPOST;   // raw output
    speed_t setiospeed=SET_IO_SPEED;
    cfsetispeed(&new_options, setiospeed);
    cfsetospeed(&new_options, setiospeed);
    tcsetattr(input_fd, TCSANOW, &new_options);
    ALOGW("pangming, start to get mcu data");
    while(1){
        usleep(500*1000);
        timeout.tv_sec = 0;
        timeout.tv_usec = 10*1000; // 10 ms
        FD_ZERO(&r_fds);
        FD_SET(input_fd, &r_fds);
        ret = ::select(input_fd + 1, &r_fds, NULL, NULL, &timeout);

        if(ret == 0)
        {
            continue;
        }
        else if(ret > 0 && FD_ISSET(input_fd, &r_fds))//else if(ret > 0)
        {
            ret = read(input_fd, _cmdLine, sizeof(_cmdLine));

            if(ret <= 0)
            {
                continue;
            }
            char str[128] = {0};
            sprintf(str, "recv: %02x %02x %02x %02x ", _cmdLine[0], _cmdLine[1], _cmdLine[2], _cmdLine[3]);
            ALOGW(" 6 data %s\n", str);
            unpackMcuData(_cmdLine, ret);
        }
    }
    #endif
}

int main(void)
{
    pthread_t tid;
    pthread_attr_t thr_attr;
    pthread_attr_init(&thr_attr);
    if ((pthread_create(&tid, &thr_attr, getMcuData, (void *)NULL)) == -1){
        printf("getMcuData create error!\n");
        return -1;
    }

    return 0;
}

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式_笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值