通信原理课设(gec6818) 008:LED+蜂鸣器+串口+MQ01+GY39+RFID
目录
1、LED和蜂鸣器
a. 安装驱动
在开发板上要使用led和蜂鸣器需要安装对应的驱动
链接:https://pan.baidu.com/s/15I1kGKhT1kENqplu5Dmg5Q?pwd=lebe
提取码:lebe
将上面的两个文件放到开发板上面去
使用insmod命令加载驱动:
insmod led_drv.ko
insmod pwm.ko
去/dev文件夹,如果看到led_drv和pwm,就是驱动加载成功
如果在加载驱动的过程中,提示文件繁忙,那就先卸载驱动,再重新下载:
rmmod gec6818_beep.ko
再insmod pwm.ko
b. 代码
led大家都很熟悉了,概念和原理啥的就跳过
为了在后面的gy39和mq01使用中,当数值超过一定阈值时,能调用led,所以我定义了变量state,num,直接调led函数,并传相应的值就能实现led灯的亮灭,蜂鸣器也是如此。
led.c :
#include "led.h" //state:灯的状态,是开还是关 1:开 0:关 //num:灯的编号,亮哪个灯 int state = 0; //灯默认为关 int num; void led(int state,int num) { int fd,ret; char led_ctrl[2]; //0 --> 灯的状态 1 --->灯编号 //[1] fd = open("/dev/led_drv",O_RDWR); if(fd < 0) { printf("open led_drv failed\n"); } led_ctrl[1] = num; // led_ctrl[0] = state; //on ret = write(fd,led_ctrl,sizeof(led_ctrl)); if( ret != 2) { perror("write"); } close(fd); }
led.h :
#ifndef _LED_H_ #define _LED_H_ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void led(int state,int num); #endif
beep.c :
#include "beep.h" int sound = 0; //默认不响 void beep(int sound) { int fd,ret; char beep_ctrl[1]; //0 --> 不响 1 --->响 //[1] fd = open("/dev/pwm",O_RDWR); if(fd < 0) { printf("open /dev/pwm failed\n"); } beep_ctrl[0] = sound; //响 ret = write(fd,beep_ctrl,sizeof(beep_ctrl)); if( ret == -1) { perror("write"); } close(fd); }
beep.h :
#ifndef __BEEP_H__ #define __BEEP_H__ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> void beep(int sound); #endif
2、串口
在linux里面串口也是一个文件
"/dev/ttySAC1" -> 串口1
"/dev/ttySAC2" -> 串口2
"/dev/ttySAC3" -> 串口3
我们在使用串口之前要设置这个串口的波特率以及其他的属性,调用int init_serial(const char *file, int baudrate)这个函数。
serial_init.c :
#include "serial_init.h" //初始化串口,把 open 和 初始化 结合在一起了 int init_serial(const char *file, int baudrate) { int fd; //打开串口 fd = open(file, O_RDWR); if (fd == -1) { perror("open device error:"); return -1; } struct termios myserial; //清空结构体 memset(&myserial, 0, sizeof (myserial)); //O_RDWR myserial.c_cflag |= (CLOCAL | CREAD); //设置控制模式状态,本地连接,接受使能 //设置 数据位 myserial.c_cflag &= ~CSIZE; //清空数据位 myserial.c_cflag &= ~CRTSCTS; //无硬件流控制 myserial.c_cflag |= CS8; //数据位:8 myserial.c_cflag &= ~CSTOPB;// //1位停止位 myserial.c_cflag &= ~PARENB; //不要校验 //myserial.c_iflag |= IGNPAR; //不要校验 //myserial.c_oflag = 0; //输入模式 //myserial.c_lflag = 0; //不激活终端模式 switch (baudrate) { case 9600: cfsetospeed(&myserial, B9600); //设置波特率 cfsetispeed(&myserial, B9600); break; case 115200: cfsetospeed(&myserial, B115200); //设置波特率 cfsetispeed(&myserial, B115200); break; case 19200: cfsetospeed(&myserial, B19200); //设置波特率 cfsetispeed(&myserial, B19200); break; } /* 刷新输出队列,清除正接受的数据 */ tcflush(fd, TCIFLUSH); /* 改变配置 */ tcsetattr(fd, TCSANOW, &myserial); return fd; }
serial_init.h :
#ifndef __SERIAL_INIT__ #define __SERIAL_INIT__ #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdio.h> //初始化串口,把 open 和 初始化 结合在一起了 int init_serial(const char *file, int baudrate); #endif
3、MQ01烟雾传感器
基本流程:
1、初始化串口
2、发送命令:FF 01 86 00 00 00 00 00 79
3、MQ采集数据
4、处理数据,将返回值第2个字节左移8位并于第3个字节相或
注意,烟雾传感器MQ是发送一次命令,返回一次信息。
MQ01.c :
#include "MQ01.h" extern int state; //灯默认为关 extern int num; void Z_MQ(void) { int Z_MQ_fd = 0; unsigned char yanwucmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; unsigned char yanwu_buf[100]={0}; int yanwu; Z_MQ_fd = init_serial("/dev/ttySAC2",9600); while(1) { write(Z_MQ_fd,yanwucmd,9); read(Z_MQ_fd,yanwu_buf,9); yanwu = yanwu_buf[2]<<8 | yanwu_buf[3]; printf("烟雾值:%d\n",yanwu); if(yanwu>=300) { led(1,9); //led9 亮 beep(1); //蜂鸣器响 sleep(5);//持续5s beep(0); //蜂鸣器关 } else{ led(0,9); //led9 灭 beep(0); //蜂鸣器关 } sleep(1); } close(Z_MQ_fd); }
MQ01.h :
#ifndef __MQ01_H__ #define __MQ01_H__ //#include <stdio.h> #include "serial_init.h" #include <unistd.h> #include "led.h" #include "beep.h" void Z_MQ(void); #endif
4、GY39
基本流程:
1、初始化串口
2、发送命令
当发送命令为:0xA5+0x81+0x26时,只输出光照
当发送命令为:0xA5+0x82+0x27时,只输出温度、气压、湿度、海拔
当发送命令为:0xA5+0x83+0x28时,输出全部:光照、温度、气压、湿度、海拔
3、采集数据
4、处理数据
H=(高 8 位<<8)|低 8 位 单位 m
GY39.c :
#include "GY39.h" extern int state; //灯默认为关 extern int num; void printGy39Data(unsigned char *recvdata,int n) { int i; for(i = 0;i < n;i++) { printf("%x ",recvdata[i]); } printf("\n"); int LUX,T,P,HUM,H;//光照,气温,气压,湿度,海拔 LUX = (recvdata[4]<<24 | recvdata[5]<<16 | recvdata[6]<<8 | recvdata[7]) / 100; T = (recvdata[13]<<8 | recvdata[14]) / 100; P = (recvdata[15]<<24 | recvdata[16]<<16 | recvdata[17]<<8 | recvdata[18]) / 100; HUM = (recvdata[19]<<8 | recvdata[20]) / 100; H = recvdata[21]<<8 | recvdata[22]; printf("LUX:%d T:%d P:%d HUM:%d H:%d\n",LUX,T,P,HUM,H); if(T>28) { led(1,8); //led9 亮 beep(1); //蜂鸣器响 sleep(5);//持续5s beep(0); //蜂鸣器关 } else{ led(0,8); //led8灭 led(0,9); } } void Gy39GetData() { int fd = init_serial("/dev/ttySAC1",9600); unsigned char cmd[3] = {0xA5,0x83,0x28}; int r = write(fd,cmd,3); printf("write r = %d\n",r); usleep(500000); int gy39_i = 0; unsigned char recvdata[24] = {0}; int timeout = 0; while(1) { r = read(fd,recvdata + gy39_i,1); if(0 == r) { timeout++; usleep(1000); if(timeout > 1000)//连续两秒没有回应 { printf("超时\n"); timeout = 0; break; } continue; } timeout = 0; gy39_i++; switch(gy39_i) { case 1:if(recvdata[0] != 0x5a){gy39_i = 0;}break; case 2:if(recvdata[1] != 0x5a){gy39_i = 0;}break; case 3:if(recvdata[2] != 0x15){gy39_i = 0;}break; case 4:if(recvdata[3] != 0x04){gy39_i = 0;}break; case 24:printGy39Data(recvdata,24);gy39_i = 0;break;//接收完毕 default: if(gy39_i > 24 || gy39_i < 0) { gy39_i = 0; sleep(1); } break; } } }
GY39.h :
#ifndef __GY39_H__ #define __GY39_H__ //#include <stdio.h> #include <unistd.h> #include "serial_init.h" #include "beep.h" #include "led.h" void printGy39Data(unsigned char *recvdata,int n); void Gy39GetData(); //int gy39_getlux(void); #endif
---------------------------------------------------补充-----------------------------------------------------------------------
5、RFID识别
#include "rifd.h" //获取校验和 char get_BCC(char *cmd) { char BCC = 0; int i; for(i = 0;i < cmd[0] - 2;i++) { //BCC = BCC ^ cmd[i]; BCC ^= cmd[i]; } return ~BCC; } /* 防碰撞 */ void CascAnticollRfidCmd(int fd) { char cmd[8] = {0}; cmd[0] = 0x08; cmd[1] = 0x02; cmd[2] = 0x42; cmd[3] = 0x02; cmd[4] = 0x93;//使用ALL模式 cmd[5] = 0x00; cmd[6] = get_BCC(cmd); cmd[7] = 0x03; //将这个命令发送给rfid write(fd,cmd,cmd[0]); //稍微延时一会 0.1s usleep(100000); //收rfid的回应 unsigned char buf[10] = {0}; int r = read(fd,buf,10); if(r == 10) { if(buf[2] == 0) { int getUID = buf[4] | buf[5] << 8 | buf[6] << 16 | buf[7] << 24; printf("getUID = %x\n",getUID);//卡序列号 } } else { perror("read CascAnticollRfidCmd error"); } } /* 这个函数是对rfid进行请求的 成功返回0 失败返回-1 */ int RequestRfidCmd(int fd) { unsigned char cmd[7] = {0}; cmd[0] = 0x07; cmd[1] = 0x02; cmd[2] = 0x41; cmd[3] = 0x01; cmd[4] = 0x52;//使用ALL模式 cmd[5] = get_BCC(cmd); cmd[6] = 0x03; //将这个命令发送给rfid write(fd,cmd,cmd[0]); //稍微延时一会 0.1s usleep(1000000); //等待rfid的回应 char buf[8] = {0}; int r = read(fd,buf,8); if(r == 8) { if(buf[2] == 0)//请求成功 { switch(buf[4]) { case 0x04: printf("S50\n"); //卡片类型 break; case 0x02: printf("S70\n"); break; } return 0; } return -1; } else { perror("请求失败\n"); //将蜂鸣器弄的不响 return -1; } } /* 这个函数的功能是为了给rfid发送使能命令 并且专注这个rfid的返回信息 fd:是你的初始化好了的串口 成功返回0 失败返回-1 */ int SendEnableCmd(int fd) { unsigned char cmd[6] = {0}; cmd[0] = 0x06; cmd[1] = 0x01; cmd[2] = 0x41; cmd[3] = 0x00; cmd[4] = get_BCC(cmd); cmd[5] = 0x03; //将这个命令发送给rfid write(fd,cmd,cmd[0]); //稍微延时一会 0.1s usleep(100000); //等你的rfid回你的信息 char buf[18] = {0}; int r = read(fd,buf,18); //printf("%d %d\n",r,buf[2]); if(18 == r)//这样你才叫得到了完整信息 { if(buf[2] == 0)//这样才叫准备好了 { printf("yes\n"); return 0; } return -1; } else { printf("SendEnableCmd read r = %d\n",r); perror("read error"); return -1; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)