开发板上串口的使用—获取传感器的数据

01开发板上LED灯和蜂鸣器的控制

蜂鸣器:
        在Linux中,蜂鸣器同样是一个文件(Linux系统把它抽象成一个文件)

        我们系统中的蜂鸣器驱动是使用ioctl控制的,我们需要替换驱动(安装新的蜂鸣器驱动)
        原先的驱动是嵌入到系统中,每一次重启都会默认安装原先的驱动
        步骤:
                1. 先上传蜂鸣器驱动
                        rx pwm.ko

                2. 安装驱动(每一次重启都需要重新安装,可以写入配置文件)
                        insmod pwm.ko 
                        insmod: can't insert 'pwm.ko': Device or resource busy
                        ===============>
                        系统中固定的驱动一直占用这个设备,需要把原始的驱动卸载
                        rmmod  gec6818_beep.ko 

                        卸载之后,重新安装
                        成功之后,会在/dev/目录下面生成一个对应的设备结点,代表蜂鸣器这个设备,名称"/dev/pwm"

                3. 操作蜂鸣器
                        1) 打开蜂鸣器文件
                        2) 写入控制数据(由驱动决定)
                        3) 关闭设备

LED灯:
        在Linux中,LED同样是一个文件(Linux系统把它抽象成一个文件)
        1. 先上传LED驱动
                rx led_drv.ko

        2. 安装驱动(每一次重启都需要重新安装,可以写入配置文件)
                insmod led_drv.ko
                成功之后,会在/dev/目录下面生成一个对应的设备结点,代表蜂鸣器这个设备,名称"/dev/led_drv"

        3. 操作LED
                1) 打开LED文件
                2) 写入控制数据(由驱动决定)
                3) 关闭设备

02C语言中多线程接口

C语言中默认情况下,只有一个执行流程,但是在开发的过程中,可能需要程序能够同时执行多个任务(拥有多条执行分支)
        =======>
        并发(多进程/多线程)

        多线程的API函数接口(可以创建一条分支,让程序执行指定的任务)
   

NAME
    pthread_create - create a new thread
        创建一个新的线程
SYNOPSIS
    #include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                    void *(*start_routine) (void *), void *arg);
        
thread:指针,指向一块可用的内存空间,用来保存新创建的线程的线程号码
        
attr:指定新创建的线程的线程属性,一般为NULL,表示使用默认属性
        
start_routine:是一个函数指针,指定了线程需要完成的任务,新创建的线程就会去执行这个函数
        
arg:线程函数的参数

返回值:
    成功返回0,失败返回-1;

Compile and link with -pthread.

03串口编程和传感器的使用

串口是一种非常重要的通信协议(用到的地方非常多),特点是一个bit一个bit的传输数据
    波特率:1s能够传输的bit的数量(传输速度)

    开发板的右上角由4组外接串口(COM2/COM3/COM4/COM5),可以连接其他支持串口的任何设备,其中:COM2/COM3/COM4可以正常使用,COM5虽然有硬件,但是没有驱动,不能使用。

    串口有4根线
        VCC     电源
        GND     接地
        TX      transfer    发送端
        RX      recive      接收端

    串口通信是两个设备之间的通信,两个设备都有4个接口,接线的方式是交叉接线
        设备A           设备B 
        VCC   --------  VCC 
        GND   --------  GND 
        TX    --------  RX 
        RX    --------  TX

    注意:
        1.断电接线(传感器容易损坏)
        2.接线的时候以PCB底板的标识为准
        3.如果收不到数据
            a.线是否接对了(TX/RX,或者没有接到指定的串口)
            b.传感器是否本身就是坏的
            c.代码问题

    串口编程的步骤:
        串口在Linux中也是文件
        1.初始化串口(设置串口的通信属性)
            a.打开串口设备对应的文件名
                文件名:
                    COM1------>"/dev/ttySAC0"  通信串口,和电脑相连的那个接口
                    COM2------>"/dev/ttySAC1"
                    COM3------>"/dev/ttySAC2"
                    COM4------>"/dev/ttySAC3"
            b.设置串口的属性
                    波特率
                    数据位
                    停止位
                    ....
        2.读写数据(需要按照传感器设备的通信协议收发数据)
            发送:   write   发送指令给传感器
            接收:   read    从传感器读取数据


        3.关闭串口
            close(...)

按照传感器设备的通信协议收发数据:
超声波:
    波特率:9600
    输出的距离值共两个字节,第一个字节是距离的高 8 位(HDate),第二个字节距离的低 8 位(LData),单位为毫米。即距离值为 (HData*256 +LData)mm。
    HData << 8 | LData 

烟雾传感器的通信协议:
    波特率:9600
    发送的命令是9字节
    0xFF,0x01,0x86,0x0,0x0,0x0,0x0,0x0,0x79
    接收9个字节:
    其中第三个字节和第四个字节表示得到的可燃气体浓度


GY39的通信协议:
    默认波特率值 9600bps
    模块输出格式,每帧包含9或者15个字节 
    ①.Byte0: 0x5A 帧头标志 
    ②.Byte1: 0x5A 帧头标志 
    ③.Byte2: 0x15/0x45 本帧数据类型
    
    0x15         这一帧数据包含光照强度
    0x45        这一帧数据包含温度、气压、湿度、海拔

数据的计算方法:
    当Byte2=0x15时,数据表示的是光照强度,保存在,Byte4~Byte7) :
        Lux=(前高8位<<24) | (前低8位<<16) | (后高8位<<8) | 后低8位 单位lux 
        例:一帧数据
        <5A- 5A- 15 -04- 00 -00- FE- 40- 0B > 
        Lux=(0x00<<24)|(0x00<<16)|(0xFE<<8)|0x40 
        Lux=Lux/100 =650.88 (lux)
    
    当Byte2=0x45时,数据表示的是温度、气压、湿度、海拔
        温度保存在 Byte4~Byte5 
        T=(高 8 位<<8)|低 8 位 
        T=T/100 单位℃
        气压保存在 Byte6~Byte9 
        P=(前高 8 位<<24) | (前低 8 位<<16) | (后高 8 位<<8) | 后低 8 位 
        P=P/100 单位 pa 
        湿度保存在 Byte10~Byte11 
        Hum=(高 8 位<<8)|低 8 位 
        Hum=Hum/100 百分制
        海拔保存在Byte12~Byte13 
        H=(高 8 位<<8)|低 8 位 单位 m 
    
    
    例:一帧数据 
    < 5A -5A -45 -0A -0B -2D -00 -97 -C4 -3F -12- 77 -00- 9C- FA > 
    T=(0x0B<<8)|0x2D=2861 
    温度 T=2861/100=28.61 (℃) 
    
    P=(0x00<<24)|(0x97<<16)|(C4<<8)|3F=9946175 
    气压 P=9946175/100=99461.75 (pa) 
    
    Hum=(0x12<<8)| 77=4727 
    湿度 Hum=4727/100=47.27 (%) 
    
    海拔 H=(0x00<<8)|0x9c=156 (m) 
    ============================================================
    需要发送的命令:
    GY-39是一个配置型的传感器,只需要向它发送一次命令,就会不断的返回数据
    发送的命令(由外部控制器发送至GY39)
    
    所有串口指令格式:帧头(0xA5)+指令+校验和(8bit) 
    
    帧头:固定是0xA5
    指令:
        连续输出温度,气压,湿度,海波     0x82
        连续输出光照强度                0x81
        
    校验和:
    0xA5 + 0x82 =======> 0x27 
        0xA5   1010 0101
        0x82   1000 0010
        -------------------------
                0010 0111   -----》0x27       
    0xA5 + 0x81 =======> 0x26

    发送命令:
    0xA5+0x81+0x26,表示连续输出光照强度
    回复9个字节,光照强度保存到第4个位到第7个位
    5a  5a  15  4  0  0  15  cc  ae   

    0xA5+0x82+0x27,表示连续输出温度,气压,湿度,海波
    回复15个字节......
    5a  5a  45  a  d  68  0  98  23  94  17  c  0  87  71
    

    0xA5+0x83+0x28  表示连续输出光照强度以及温度,气压,湿度,海波
    回复9+15个字节为一帧数据
    5a  5a  15  4  0  0  15  cc  ae   5a  5a  45  a  9  d4  0  98  1f  e  17  f1  0  88  35


void monitor_temp()
{
    //初始化串口
    int fd = init_serial("/dev/ttySAC3",9600);
    if(fd == -1)
    {
        printf("初始化串口失败!");
        return;
    }
    //按照通信协议收发数据
    //char cmd[3] = {0xA5,0x81,0x26};//光照强度
    //char cmd[3] = {0xA5,0x82,0x27};//温湿度强度
    char cmd[3] = {0xA5,0x83,0x28};//光照强度 + 温湿度强度
    
    //是配置型传感器,只需要发送一次命令即可
    write(fd,cmd,3);
    sleep(1);
    //不断的读取数据
    while(1)
    {
        sleep(1);
        char ack[32] = {0};
        int r = read(fd,ack,32);
        if(r != 9 && r!=15  && r!= 24) //光照强度会返回9个字节,温湿度会返回15个字节
        {
            printf("GY39-read data error:%d\n",r);
            continue;
        }
        //验证数据的正确性
        int i;
        for(i=0;i<r;i++)
        { 
            printf("%x  ",ack[i]);  //原始数据
        }
        printf("\n");
        /*
        if(ack[0] == 0x5a && ack[1] == 0x5a) //验证数据的正确性
        {
            int lux = ack[4] << 24 | ack[5] << 16 | ack[6] << 8 | ack[7]; 
            lux = lux/100;
            printf("lux_value = %d\n",lux);
        }
        */
        
        /*
        if(ack[0] == 0x5a && ack[1] == 0x5a) //验证数据的正确性
        {
            int temp = ack[4] << 8 | ack[5]; 
            temp = temp/100;
            printf("temp_value = %d\n",temp);
        }
        */    
    }
    
    //关闭串口
    close(fd);
}


 

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值