目录
在开发板上要使用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
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
在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
基本流程:
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
基本流程:
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
---------------------------------------------------补充-----------------------------------------------------------------------
#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;
}
}