通信原理课设(gec6818) 008:LED+蜂鸣器+串口+MQ01+GY39+RFID

目录

1、LED和蜂鸣器

a. 安装驱动

b. 代码

2、串口

3、MQ01烟雾传感器

4、GY39


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、处理数据

光照强度计算方法(当 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)

   

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;
	}
}

posted @ 2023-12-30 19:45  Flying3080  Views(373)  Comments(0Edit  收藏  举报  来源