GEC6818传感器模块(烟雾+GY39+RFID)——使用文字取模的方式实现数据显示
完整的工程大家可以在我的gitee上进行下载
下载地址:GEC6818智能语音家居系统
文章目录
- GEC6818传感器模块(烟雾+GY39+RFID)——使用文字取模的方式实现数据显示
- 一、 文字取模实现数据显示
- 1. `display_bg()`
- 2. `display_word()`
- 3. `display_digit()`
- 二、 烟雾传感器
- 2.1 烟雾传感器实现线程
- 2.2 解析
- 三、GY39
- 3.1 GY39的线程代码
- 3.2 解析
- 四、 RFID
- 4.1 RFID线程代码
- 4.2 解析
- 五、 完整代码
一、 文字取模实现数据显示
在许多嵌入式系统或特定的显示屏幕上,为了节省存储空间和减少数据传输量,字符通常不是直接以像素形式存储的,而是以“点阵”或“点阵字库”的形式存储。每个字符都由一组预定义的点阵数据来表示。当需要显示一个字符时,可以通过访问这些点阵数据来在显示屏上绘制该字符。
实现步骤:
-
定义点阵数据:
digits
数组定义了数字0到9的点阵数据。每个数字都是一个5x7的点阵,其中5代表宽度,7代表高度。- 其他变量(如
guan
,qian
,wen
等)定义了对应汉字的点阵数据。
-
字符取模:
字符取模通常是指根据预定义的点阵数据来“绘制”或“显示”字符。为了从点阵数据中绘制字符,通常会使用两层嵌套循环遍历点阵数据的每一行和每一列,然后根据点阵数据的值来决定是否在显示屏上显示一个点(或像素)。 -
字符显示:
使用点阵数据来绘制字符时,通常会有一个显示函数或方法来实际在屏幕上显示字符。该函数可能会使用点阵数据来决定应该在屏幕上的哪些位置显示像素。
总之,这种字符取模的方式提供了一种有效的方法来在显示屏上显示字符,特别是在资源有限的嵌入式系统中。通过预定义的点阵数据,可以节省存储空间,并减少绘制字符所需的计算量。
void display_bg(int x0, int y0,int x1, int y1 , int color)
{
int i, j;
for(i = x0; i < x1; i++)
{
for(j = y0; j < y1; j++)
{
point(j, i, color);
}
}
}
void display_word(int color,int x0, int y0, char word[], int w, int h)
{
int i, j, x, y;
for(i = 0; i < w*h/8; i++)
{
for(j = 0; j < 8; j++)
{
if(word[i]>>(7-j) & 1 ==1)
{
x = i/(w/8) + x0;
y = (i%(w/8))*8 + j + y0;
point(y, x, color);
}
}
}
}
void display_digit(int color, int x0, int y0, int number, int w, int h)
{
int i, j, m = 0, a[100] = {0};
if(number == 0)
{
display_word(blue, x0, y0, digits[0], w, h);
}
else
{
for(i = 0; number != 0; i++)
{
a[i] = number%10;
number /= 10;
}
for(j = i - 1; j >= 0; j--)
{
// printf("%d\n", a[j]);
display_word(blue, x0, y0+m*8, digits[a[j]], w, h);
m++;
}
}
}
1. display_bg()
该函数旨在在显示器上的指定边界内绘制具有给定颜色的背景矩形。
-
参数:
x0, y0
:矩形的起始坐标(左上角)。x1, y1
:矩形的结束坐标(右下角)。color
:矩形的背景颜色。
-
逻辑:
- 嵌套循环遍历指定边界内的x和y坐标。
- 在每个坐标
(i, j)
处,调用point(j, i, color)
函数(可能是)来设置该像素的颜色。
2. display_word()
该函数旨在在显示器上显示一个字符(以比特矩阵的形式)。
-
参数:
color
:字符的颜色。x0, y0
:字符将被显示的起始坐标(左上角)。word[]
:以特定格式表示字符的数组。w, h
:字符的宽度和高度。
-
逻辑:
- 函数遍历字符矩阵的每个比特。
- 对于每个比特,如果它被设置为1,那么相应的像素将设置为指定的颜色。
- 从给定的字符宽度和高度中推导出要设置的像素的确切位置
(x, y)
的公式。
3. display_digit()
这是display_word()
的一个专门版本,特别用于显示数字。
-
参数:
color
:数字的颜色。x0, y0
:数字将被显示的起始坐标(左上角)。number
:要显示的数字。w, h
:数字的宽度和高度。
-
逻辑:
- 如果给定的数字是
0
,它会直接使用display_word()
显示数字0
。 - 否则,它会将数字分解为各个数字,并逐个显示每个数字。这是通过反复将数字除以10并将余数存储在数组中来完成的。
- 对于每个数字,都会调用
display_word()
来显示它。
- 如果给定的数字是
二、 烟雾传感器
2.1 烟雾传感器实现线程
//烟雾传感器的线程
#define COM2 "/dev/ttySAC1"
void * yanwu(void *arg)
{
pthread_detach(pthread_self());
int fd = serial_init(COM2, 9600);
int fd1 = open("/dev/pwm", O_RDWR);
int ret;
char beep_ctrl[1];
if(fd == -1)
{
perror("serial_init error!\n");
return (void *)-1;
}
if(fd1 == -1)
{
perror("open /dev/pwm error!\n");
return (void *)-1;
}
while(1)
{
char w_buf[9] = {0xFF, 0X01, 0x86, 0, 0, 0, 0, 0, 0x79};
write(fd, w_buf, 9);
usleep(1000);
char r_buf[9];
int r = read(fd, r_buf, 9);
if(r == 9 && r_buf[0] == 0xff && r_buf[1] == 0x86)
{
int n = r_buf[2]<<8 | r_buf[3];
printf("n = %d\n", n);
if(n > 138)
{
printf("蜂鸣器\n");
beep_ctrl[0] = 1; //不响
ret = write(fd1,beep_ctrl,sizeof(beep_ctrl));
if( ret == -1)
{
perror("write");
}
sleep(1);
beep_ctrl[0] = 0; //响
ret = write(fd1,beep_ctrl,sizeof(beep_ctrl));
if( ret == -1)
{
perror("write");
}
sleep(1);
}
else
{
beep_ctrl[0] = 0; //响
ret = write(fd1,beep_ctrl,sizeof(beep_ctrl));
if( ret == -1)
{
perror("write");
}
}
}
sleep(1);
}
//close(fd1);
close(fd);
return 0;
}
2.2 解析
这段代码定义了一个名为yanwu
的线程函数,该函数用于处理烟雾传感器的数据和操作蜂鸣器。以下是对该函数的详细解析:
-
宏定义:
- 使用
#define
定义了串行通信端口COM2为"/dev/ttySAC1"
。
- 使用
-
线程初始化:
- 调用
pthread_detach
函数使得线程在结束时能够自动释放其资源。 - 使用
serial_init
函数初始化一个串行端口连接烟雾传感器。 - 打开一个设备文件
/dev/pwm
来控制蜂鸣器。
- 调用
-
错误检查:
- 检查串行端口和设备文件的打开情况,如果有错误则打印错误信息并返回。
-
主循环:
- 在一个无限循环中,不断地向烟雾传感器发送请求数据的命令,并读取其响应。
- 如果接收到的数据满足预期格式(前两个字节是特定的值),则进行进一步处理。
-
数据解析:
- 从接收到的数据中提取出一个16位的数值
n
。 - 如果
n
大于138,表示检测到烟雾浓度超过了设定的阈值,这时蜂鸣器会响应,并进行一系列的响与不响的交替操作。
- 从接收到的数据中提取出一个16位的数值
-
蜂鸣器控制:
- 根据烟雾浓度的不同,设置蜂鸣器的状态:当浓度高于阈值时,蜂鸣器会交替响和不响;否则,蜂鸣器会维持不响的状态。
-
资源释放:
- 代码中有一个注释掉的
close(fd1);
,这表示该代码段原先可能是用于关闭蜂鸣器设备文件的,但在当前版本中被注释掉了。
- 代码中有一个注释掉的
-
返回值:
- 函数最后返回0,这通常表示函数执行成功。
总的来说,该线程函数yanwu
负责与烟雾传感器通信,根据检测到的烟雾浓度来控制蜂鸣器的响与不响,并在控制台打印相关的信息。
三、GY39
3.1 GY39的线程代码
//GY39 的线程
void * gy_39(void *arg)
{
/*
发送的信息:
开发板发送给传感器的指令格式:帧头+指令+校验和(8bit)
帧头和校验和是用来“验证身份”的
指令才是用来表达此次通信的目的
各占一个字节,共三个字节
帧头:0xa5
指令:
只请求光照: 10000001 -> 0x81
只请求温湿度气压海拔:10000010 -> 0x82
两种都请求:10000011 -> 0x83
检验和:
等于帧头加上指令,只保存低8位
0xa5 + 0x81 -> 0x26
*/
pthread_detach(pthread_self());
char led_ctrl[2];
int fd1 = open("/dev/led_drv",O_RDWR);
if(fd1 < 0)
{
printf("open led_drv failed\n");
return (void*)-1;
}
int fd = serial_init(COM3, 9600);
int m = 2;
char w_buf[][3] ={{0xa5, 0x81, 0x26}, {0xa5, 0x82, 0x27}, {0xa5, 0x83, 0x28}};
int Lux = 0, T = 0, P = 0, Hum = 0, H = 0;
int t,r,ret;
char r_buf[24];
while (1)
{
t = write(fd, w_buf[m], 3);
// printf("%d\n", t);
usleep(1000);
r = read(fd, r_buf, 24);
if (r == 9 && r_buf[2] == 0x15)
{
Lux = (r_buf[4] << 24 | r_buf[5] << 16 | r_buf[6] << 8 | r_buf[7]) / 100;
}
else if (r == 15 && r_buf[2] == 0x45)
{
T = (r_buf[4] << 8 | r_buf[5]) / 100;
P = (r_buf[6] << 24 | r_buf[7] << 16 | r_buf[8] << 8 | r_buf[9]) / 100;
Hum = (r_buf[10] << 8 | r_buf[11]) / 100;
H = (r_buf[12] << 8 | r_buf[13]) / 100;
}
else if (r == 24)
{
Lux = (r_buf[4] << 24 | r_buf[5] << 16 | r_buf[6] << 8 | r_buf[7]) / 100;
T = (r_buf[13] << 8 | r_buf[14]) / 100;
P = (r_buf[15] << 24 | r_buf[16] << 16 | r_buf[8] << 8 | r_buf[9]) / 100;
Hum = (r_buf[10] << 8 | r_buf[11]) / 100;
H = (r_buf[12] << 8 | r_buf[13]) / 100;
}
printf("Lux = %d, T = %d, P = %d, Hum = %d, H = %d\n", Lux, T, P, Hum, H);
sleep(1);
if (Lux < 6)
{
led_ctrl[1] = 9; //D9
led_ctrl[0] = 1; //on
ret = write(fd1,led_ctrl,sizeof(led_ctrl));
if( ret != 2)
{
perror("write");
}
sleep(1);
}
else
{
led_ctrl[1] = 9; //D9
led_ctrl[0] = 0; //off
ret = write(fd1,led_ctrl,sizeof(led_ctrl));
if( ret != 2)
{
perror("write");
}
sleep(1);
}
display_word(black, 170, 100, guan, 16, 16);
display_word(black, 170, 116, qian, 16, 16);
display_word(black, 170, 132, maohao, 16, 16);
display_bg(170, 148, 186, 164, white);
display_digit(blue, 170, 148, Lux, 8, 16);
display_word(blue, 170, 169, L, 8, 16);
display_word(blue, 170, 177, U, 8, 16);
display_word(blue, 170, 185, X, 8, 16);
display_word(black, 196, 100, wen, 16, 16);
display_word(black, 196, 116, du, 16, 16);
display_word(black, 196, 132, maohao, 16, 16);
display_bg(196, 148, 218, 172, white);
display_digit(blue, 196, 148, T, 8, 16);
display_word(blue, 196, 169, C, 16, 16);
display_word(black, 222, 100, shi, 16, 16);
display_word(black, 222, 116, du, 16, 16);
display_word(black, 222, 132, maohao, 16, 16);
display_bg(222, 148, 238, 182 + 100, white);
display_digit(blue, 222, 148, Hum, 8, 16);
display_word(blue, 222, 174, baifenhao, 8, 16);
display_word(black, 248, 100, qi, 16, 16);
display_word(black, 248, 116, ya, 16, 16);
display_word(black, 248, 132, maohao, 16, 16);
display_bg(248, 148, 264, 209 + 50, white);
display_digit(blue, 248, 148, P, 8, 16);
display_word(blue, 248, 193, _P, 8, 16);
display_word(blue, 248, 201, A, 8, 16);
display_word(black, 272, 100, hai, 16, 16);
display_word(black, 272, 116, ba, 16, 16);
display_word(black, 272, 132, maohao, 16, 16);
display_bg(272, 148, 288, 177 + 100, white);
display_digit(blue, 272, 148, H, 8, 16);
display_word(blue, 272, 169, M, 8, 16);
}
close(fd);
//return 0;
}
3.2 解析
这段代码是一个线程函数gy_39
,该函数与一个光照、温湿度、气压和海拔高度传感器GY-39进行通信。以下是对该函数的详细解析:
-
函数开头的注释:提供了与传感器通信的指令格式。
-
初始化:
- 打开了一个名为
/dev/led_drv
的设备文件来控制LED。 - 使用
serial_init
函数初始化了一个串行端口连接传感器。
- 打开了一个名为
-
通信部分:
- 代码定义了三种不同的指令,每个指令对应于从传感器请求不同的数据(光照、温湿度、气压和海拔高度)。
- 使用
write
函数将这些指令写入串行端口,并尝试从传感器读取数据。
-
数据解析:
- 从传感器读取的数据被解析并存储在不同的变量(如
Lux
,T
,P
,Hum
,H
)中。 - 这些数据被打印到控制台。
- 从传感器读取的数据被解析并存储在不同的变量(如
-
LED控制:
- 根据读取的光照值(
Lux
),代码控制LED的状态。如果光照值小于6,LED会被打开;否则,LED会关闭。
- 根据读取的光照值(
-
显示函数:
- 使用了多个
display_word
和display_bg
函数来在屏幕上显示不同的文本和背景。
- 使用了多个
-
循环:
- 整个代码位于一个无限循环中,使得传感器持续地发送数据并更新LED状态和屏幕显示。
-
函数结束:
- 关闭了串行端口并返回。
总体来说,这个线程函数gy_39
负责与GY-39传感器通信,读取其数据,根据读取的数据控制LED的状态,并在屏幕上显示这些数据。
四、 RFID
4.1 RFID线程代码
void * rfid(void *arg)
{
pthread_detach(pthread_self());
//初始化串口
int fd = serial_init(COM4,9600);
printf("fd = %d\n",fd);
//给我们的rfid发送使能命令 打开你的rfid这个设备
//自己写一个函数 来实现命令的发送
int r = SendEnableCmd(fd);
if(r != 0)//失败了
{
printf("SendEnableCmd error\n");
}
while(1)
{
//发送请求
r = RequestRfidCmd(fd);
if(r == 0)//请求成功
{
//防碰撞
CascAnticollRfidCmd(fd);
printf("你好我是小草神\n");
show_bmp("green.bmp", 450, 10,0);
sleep(1);
InitSensor();
}
}
}
4.2 解析
这段代码定义了一个名为rfid
的线程函数,该函数用于与RFID设备进行通信并执行一系列操作。以下是对该函数的详细解析:
-
线程初始化:
- 使用
pthread_detach
函数使得线程在结束时能够自动释放其资源。
- 使用
-
串口初始化:
- 使用
serial_init
函数初始化一个串行端口连接RFID设备,并返回一个文件描述符fd
。 - 打印文件描述符
fd
的值。
- 使用
-
RFID设备使能:
- 调用
SendEnableCmd(fd)
函数发送使能命令给RFID设备。 - 检查命令发送的结果,如果返回值不为0,表示命令发送失败,并打印错误信息。
- 调用
-
主循环:
- 在一个无限循环中,不断地向RFID设备发送请求命令。
- 如果请求成功(即返回值为0),则执行以下操作:
- 调用
CascAnticollRfidCmd(fd)
函数进行防碰撞处理。 - 在控制台打印消息"你好我是小草神"。
- 使用
show_bmp
函数显示一个名为"green.bmp"的位图文件在指定位置。 - 调用
sleep(1)
函数使线程休眠1秒。 - 调用
InitSensor
函数进行传感器的初始化。
- 调用
-
函数结束:
- 由于这是一个无限循环的线程函数,因此在正常情况下,函数不会自然结束。需要外部干预(例如通过其他线程或信号)才能结束该函数。
总的来说,该线程函数rfid
负责与RFID设备通信,执行一系列初始化和操作,并在控制台上显示相关的消息和位图。
五、 完整代码
#include "sensor.h"
extern int touch_fd;
// 存储点阵数据
char digits[10][16] = {
/*-- 文字: 0 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},
/*-- 文字: 1 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},
/*-- 文字: 2 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x02,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00},
/*-- 文字: 3 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x04,0x02,0x42,0x42,0x3C,0x00,0x00},
/*-- 文字: 4 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x04,0x0C,0x0C,0x14,0x24,0x24,0x44,0x7F,0x04,0x04,0x1F,0x00,0x00},
/*-- 文字: 5 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x78,0x44,0x02,0x02,0x42,0x44,0x38,0x00,0x00},
/*-- 文字: 6 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x18,0x24,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x22,0x1C,0x00,0x00},
/*-- 文字: 7 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x7E,0x42,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x00,0x00},
/*-- 文字: 8 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},
/*-- 文字: 9 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
{0x00,0x00,0x00,0x38,0x44,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x24,0x18,0x00,0x00}
};
char guan[] = {
/*-- 文字: 光 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x01,0x00,0x21,0x08,0x11,0x08,0x09,0x10,0x09,0x20,0x01,0x00,0xFF,0xFE,0x04,0x40,
0x04,0x40,0x04,0x40,0x04,0x40,0x08,0x42,0x08,0x42,0x10,0x42,0x20,0x3E,0xC0,0x00
};
char qian[] = {
/*-- 文字: 强 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0xF9,0xFC,0x09,0x04,0x09,0x04,0x09,0xFC,0x78,0x20,0x40,0x20,0x43,0xFE,
0x42,0x22,0x7A,0x22,0x0B,0xFE,0x08,0x20,0x08,0x24,0x08,0x22,0x57,0xFE,0x20,0x02
};
char wen[] = {
/*-- 文字: 温 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8,
0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00
};
char du[] = {
/*-- 文字: 度 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20,
0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E
};
char shi[] = {
/*-- 文字: 湿 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x27,0xF8,0x14,0x08,0x14,0x08,0x87,0xF8,0x44,0x08,0x44,0x08,0x17,0xF8,
0x11,0x20,0x21,0x20,0xE9,0x24,0x25,0x28,0x23,0x30,0x21,0x20,0x2F,0xFE,0x00,0x00
};
char qi[] = {
/*-- 文字: 气 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x10,0x00,0x10,0x00,0x3F,0xFC,0x20,0x00,0x4F,0xF0,0x80,0x00,0x3F,0xF0,0x00,0x10,
0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x0A,0x00,0x0A,0x00,0x06,0x00,0x02
};
char ya[] = {
/*-- 文字: 压 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x3F,0xFE,0x20,0x00,0x20,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x2F,0xFC,
0x20,0x80,0x20,0x80,0x20,0x90,0x20,0x88,0x20,0x88,0x40,0x80,0x5F,0xFE,0x80,0x00
};
char hai[] = {
/*-- 文字: 海 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x01,0x00,0x21,0x00,0x11,0xFC,0x12,0x00,0x85,0xF8,0x41,0x08,0x49,0x48,0x09,0x28,
0x17,0xFE,0x11,0x08,0xE2,0x48,0x22,0x28,0x23,0xFC,0x20,0x08,0x20,0x50,0x00,0x20
};
char ba[] = {
/*-- 文字: 拔 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x10,0x50,0x10,0x48,0x10,0x48,0x10,0x40,0xFB,0xFE,0x10,0x80,0x14,0x80,0x18,0xFC,
0x31,0x44,0xD1,0x44,0x11,0x28,0x11,0x28,0x12,0x10,0x12,0x28,0x54,0x44,0x21,0x82
};
char maohao[] = {
/*-- 文字: : --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00
};
char C[] = {
/*-- 文字: ℃ --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x60,0x00,0x91,0xF4,0x96,0x0C,0x6C,0x04,0x08,0x04,0x18,0x00,0x18,0x00,0x18,0x00,
0x18,0x00,0x18,0x00,0x18,0x00,0x08,0x00,0x0C,0x04,0x06,0x08,0x01,0xF0,0x00,0x00
};
char L[] = {
/*-- 文字: l --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00
};
char U[] = {
/*-- 文字: u --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x42,0x42,0x42,0x42,0x46,0x3B,0x00,0x00
};
char X[] = {
/*-- 文字: x --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x24,0x18,0x18,0x18,0x24,0x6E,0x00,0x00
};
char baifenhao[] = {
/*-- 文字: % --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x44,0xA4,0xA8,0xA8,0xB0,0x54,0x1A,0x2A,0x2A,0x4A,0x44,0x00,0x00
};
char _P[] = {
/*-- 文字: P --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0xFC,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x40,0xE0,0x00,0x00
};
char A[] = {
/*-- 文字: a --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x0C,0x34,0x44,0x4C,0x36,0x00,0x00
};
char M[] = {
/*-- 文字: m --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x49,0x49,0x49,0x49,0x49,0xED,0x00,0x00
};
//6818串口所对应的文件名
#define COM2 "/dev/ttySAC1"
#define COM3 "/dev/ttySAC2"
#define COM4 "/dev/ttySAC3"
int * p, blue = 0xff0000, black = 0xff0000, white = 0x00FFFFFF;
void display_bg(int x0, int y0,int x1, int y1 , int color)
{
int i, j;
for(i = x0; i < x1; i++)
{
for(j = y0; j < y1; j++)
{
point(j, i, color);
}
}
}
void display_word(int color,int x0, int y0, char word[], int w, int h)
{
int i, j, x, y;
for(i = 0; i < w*h/8; i++)
{
for(j = 0; j < 8; j++)
{
if(word[i]>>(7-j) & 1 ==1)
{
x = i/(w/8) + x0;
y = (i%(w/8))*8 + j + y0;
point(y, x, color);
}
}
}
}
void display_digit(int color, int x0, int y0, int number, int w, int h)
{
int i, j, m = 0, a[100] = {0};
if(number == 0)
{
display_word(blue, x0, y0, digits[0], w, h);
}
else
{
for(i = 0; number != 0; i++)
{
a[i] = number%10;
number /= 10;
}
for(j = i - 1; j >= 0; j--)
{
// printf("%d\n", a[j]);
display_word(blue, x0, y0+m*8, digits[a[j]], w, h);
m++;
}
}
}
void display_picture(int x0, int y0, char file[])
{
printf("%s\n", file);
short int m;
int bmp_fd, w, h;
bmp_fd = open(file, O_RDONLY);
if(bmp_fd == -1)
{
perror("open picture file error!");
return;
}
lseek(bmp_fd, 0x12, SEEK_SET);
read(bmp_fd, &w, 4);
lseek(bmp_fd, 0x16, SEEK_SET);
read(bmp_fd, &h, 4);
lseek(bmp_fd, 0x1C, SEEK_SET);
read(bmp_fd, &m, 2);
// printf("w = %d\n", w);
// printf("h = %d\n", h);
// printf("m = %d\n", m);
char color_buf[w*h*m/8];
lseek(bmp_fd, 54, SEEK_SET);
read(bmp_fd, color_buf, w*h*m/8);
int i, j, n = 0;
for(i = h-1+x0; i >= x0; i--)
{
for(j = y0; j < w + y0; j++)
{
int color = color_buf[2+3*n] << 16 | color_buf[1+3*n] << 8 | color_buf[0+3*n];
point(j, i, color);
n++;
}
}
close(bmp_fd);
}
int serial_init(char *file,int speed)
{
/*
打开串口文件
*/
int fd = open(file,O_RDWR);
if(fd == -1)
{
perror("open serial error");
return -1;
}
/*定义串口属性结构体*/
struct termios myserial;
memset(&myserial,0,sizeof(myserial));//清零
/*设置控制模式 本地连接 使能接收*/
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; //不要校验
/*设置波特率*/
switch(speed)
{
case 9600:
cfsetospeed(&myserial,B9600);
cfsetispeed(&myserial,B9600);
break;
case 57600:
cfsetospeed(&myserial,B57600);
cfsetispeed(&myserial,B57600);
break;
case 115200:
cfsetospeed(&myserial,B115200);
cfsetispeed(&myserial,B115200);
break;
}
/*刷新输出队列,清除正接收的数据*/
tcflush(fd,TCIFLUSH);
/*更改配置*/
tcsetattr(fd,TCSANOW,&myserial);
return fd;
}
//获取校验和
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;
}
}
void InitSensor()
{
show_bmp("beauty.bmp", 0, 0,0);
show_bmp("draw4.bmp", 750, 400,0);
Displaysql(200, 150, 90, 160, 0xffffff);
}
/* 进程部分 */
void * yanwu(void *arg)
{
pthread_detach(pthread_self());
int fd = serial_init(COM2, 9600);
int fd1 = open("/dev/pwm", O_RDWR);
int ret;
char beep_ctrl[1];
if(fd == -1)
{
perror("serial_init error!\n");
return (void *)-1;
}
if(fd1 == -1)
{
perror("open /dev/pwm error!\n");
return (void *)-1;
}
while(1)
{
char w_buf[9] = {0xFF, 0X01, 0x86, 0, 0, 0, 0, 0, 0x79};
write(fd, w_buf, 9);
usleep(1000);
char r_buf[9];
int r = read(fd, r_buf, 9);
if(r == 9 && r_buf[0] == 0xff && r_buf[1] == 0x86)
{
int n = r_buf[2]<<8 | r_buf[3];
printf("n = %d\n", n);
if(n > 138)
{
printf("蜂鸣器\n");
beep_ctrl[0] = 1; //不响
ret = write(fd1,beep_ctrl,sizeof(beep_ctrl));
if( ret == -1)
{
perror("write");
}
sleep(1);
beep_ctrl[0] = 0; //响
ret = write(fd1,beep_ctrl,sizeof(beep_ctrl));
if( ret == -1)
{
perror("write");
}
sleep(1);
}
else
{
beep_ctrl[0] = 0; //响
ret = write(fd1,beep_ctrl,sizeof(beep_ctrl));
if( ret == -1)
{
perror("write");
}
}
}
sleep(1);
}
//close(fd1);
close(fd);
return 0;
}
void * rfid(void *arg)
{
pthread_detach(pthread_self());
//初始化串口
int fd = serial_init(COM4,9600);
printf("fd = %d\n",fd);
//给我们的rfid发送使能命令 打开你的rfid这个设备
//自己写一个函数 来实现命令的发送
int r = SendEnableCmd(fd);
if(r != 0)//失败了
{
printf("SendEnableCmd error\n");
}
while(1)
{
//发送请求
r = RequestRfidCmd(fd);
if(r == 0)//请求成功
{
//防碰撞
CascAnticollRfidCmd(fd);
printf("你好我是小草神\n");
show_bmp("green.bmp", 450, 10,0);
sleep(1);
InitSensor();
}
}
}
void * gy_39(void *arg)
{
/*
发送的信息:
开发板发送给传感器的指令格式:帧头+指令+校验和(8bit)
帧头和校验和是用来“验证身份”的
指令才是用来表达此次通信的目的
各占一个字节,共三个字节
帧头:0xa5
指令:
只请求光照: 10000001 -> 0x81
只请求温湿度气压海拔:10000010 -> 0x82
两种都请求:10000011 -> 0x83
检验和:
等于帧头加上指令,只保存低8位
0xa5 + 0x81 -> 0x26
*/
pthread_detach(pthread_self());
char led_ctrl[2];
int fd1 = open("/dev/led_drv",O_RDWR);
if(fd1 < 0)
{
printf("open led_drv failed\n");
return (void*)-1;
}
int fd = serial_init(COM3, 9600);
int m = 2;
char w_buf[][3] ={{0xa5, 0x81, 0x26}, {0xa5, 0x82, 0x27}, {0xa5, 0x83, 0x28}};
int Lux = 0, T = 0, P = 0, Hum = 0, H = 0;
int t,r,ret;
char r_buf[24];
while (1)
{
t = write(fd, w_buf[m], 3);
// printf("%d\n", t);
usleep(1000);
r = read(fd, r_buf, 24);
if (r == 9 && r_buf[2] == 0x15)
{
Lux = (r_buf[4] << 24 | r_buf[5] << 16 | r_buf[6] << 8 | r_buf[7]) / 100;
}
else if (r == 15 && r_buf[2] == 0x45)
{
T = (r_buf[4] << 8 | r_buf[5]) / 100;
P = (r_buf[6] << 24 | r_buf[7] << 16 | r_buf[8] << 8 | r_buf[9]) / 100;
Hum = (r_buf[10] << 8 | r_buf[11]) / 100;
H = (r_buf[12] << 8 | r_buf[13]) / 100;
}
else if (r == 24)
{
Lux = (r_buf[4] << 24 | r_buf[5] << 16 | r_buf[6] << 8 | r_buf[7]) / 100;
T = (r_buf[13] << 8 | r_buf[14]) / 100;
P = (r_buf[15] << 24 | r_buf[16] << 16 | r_buf[8] << 8 | r_buf[9]) / 100;
Hum = (r_buf[10] << 8 | r_buf[11]) / 100;
H = (r_buf[12] << 8 | r_buf[13]) / 100;
}
printf("Lux = %d, T = %d, P = %d, Hum = %d, H = %d\n", Lux, T, P, Hum, H);
sleep(1);
if (Lux < 6)
{
led_ctrl[1] = 9; //D9
led_ctrl[0] = 1; //on
ret = write(fd1,led_ctrl,sizeof(led_ctrl));
if( ret != 2)
{
perror("write");
}
sleep(1);
}
else
{
led_ctrl[1] = 9; //D9
led_ctrl[0] = 0; //off
ret = write(fd1,led_ctrl,sizeof(led_ctrl));
if( ret != 2)
{
perror("write");
}
sleep(1);
}
display_word(black, 170, 100, guan, 16, 16);
display_word(black, 170, 116, qian, 16, 16);
display_word(black, 170, 132, maohao, 16, 16);
display_bg(170, 148, 186, 164, white);
display_digit(blue, 170, 148, Lux, 8, 16);
display_word(blue, 170, 169, L, 8, 16);
display_word(blue, 170, 177, U, 8, 16);
display_word(blue, 170, 185, X, 8, 16);
display_word(black, 196, 100, wen, 16, 16);
display_word(black, 196, 116, du, 16, 16);
display_word(black, 196, 132, maohao, 16, 16);
display_bg(196, 148, 218, 172, white);
display_digit(blue, 196, 148, T, 8, 16);
display_word(blue, 196, 169, C, 16, 16);
display_word(black, 222, 100, shi, 16, 16);
display_word(black, 222, 116, du, 16, 16);
display_word(black, 222, 132, maohao, 16, 16);
display_bg(222, 148, 238, 182 + 100, white);
display_digit(blue, 222, 148, Hum, 8, 16);
display_word(blue, 222, 174, baifenhao, 8, 16);
display_word(black, 248, 100, qi, 16, 16);
display_word(black, 248, 116, ya, 16, 16);
display_word(black, 248, 132, maohao, 16, 16);
display_bg(248, 148, 264, 209 + 50, white);
display_digit(blue, 248, 148, P, 8, 16);
display_word(blue, 248, 193, _P, 8, 16);
display_word(blue, 248, 201, A, 8, 16);
display_word(black, 272, 100, hai, 16, 16);
display_word(black, 272, 116, ba, 16, 16);
display_word(black, 272, 132, maohao, 16, 16);
display_bg(272, 148, 288, 177 + 100, white);
display_digit(blue, 272, 148, H, 8, 16);
display_word(blue, 272, 169, M, 8, 16);
}
close(fd);
//return 0;
}
int main()
{
struct input_event ev;//
int flag = 0;//超时的flag
int ev_x0,ev_y0,ev_x,ev_y,move_x,move_y;
pthread_t task_yanwu,task_rfid,task_gy39;
if(pthread_create(&task_yanwu, NULL, (void *)yanwu, NULL) == -1)
{
perror("fail to create pthread task_yanwu\n");
return -1;
}
if(pthread_create(&task_rfid, NULL, (void *)rfid, NULL) == -1)
{
perror("fail to create pthread task_rfid\n");
return -1;
}
if(pthread_create(&task_gy39, NULL, (void *)gy_39, NULL) == -1)
{
perror("fail to create pthread task_rfid\n");
return -1;
}
while (1)
{
//我们想获取坐标值 那么就是从这个文件里面读取内容
int r = read(touch_fd,&ev,sizeof(ev));
if(sizeof(ev) != r)//读出问题出来了
{
usleep(10);
flag++;
if(10 <= flag)
{
//超时太多了 不行了
perror("read ev error");
return 0;//返回一个错误的方向
}
continue;
}
flag = 0;
//将数据打印出来看看
//printf("type:%d code:%d value:%d\n",ev.type,ev.code,ev.value);
//获取坐标
if(EV_ABS == ev.type)//接下来的数据就是坐标
{
if(REL_X == ev.code)//x轴
{
ev_x = ev.value;
}
else if(REL_Y == ev.code)//y轴
{
ev_y = ev.value;
}
}
if(0x01 == ev.type && BTN_TOUCH == ev.code && 0x01 == ev.value)//手按下去的时候
{
ev_x0 = ev_x * 800 / 1200;
ev_y0 = ev_y * 480 / 600;
}
else if(0x01 == ev.type && BTN_TOUCH == ev.code && 0x00 == ev.value)//手抬起来
{
//printf("ev_x0:%d ev_y0:%d\n",ev_x0,ev_y0);
//实现点击和方向判断
if(ev_x0 == (ev_x * 800 / 1200) && ev_y0 == (ev_y * 480 / 600))//你的手没有动
{
printf("点击\n");
//return;
}
if ((ev_x0 > 600 && ev_x0 < 680) && (ev_y0 > 400 && ev_y0 < 470))
{
printf("退出\n");
pthread_cancel(task_yanwu);
pthread_cancel(task_rfid);
pthread_cancel(task_gy39);
break;
//exit(1);
}
}
}
return 0;
}
完整的工程大家可以在我的gitee上进行下载
下载地址:GEC6818智能语音家居系统