根据lcd.c
#include "lcd.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
//全局变量
int fd_lcd; //帧缓冲设备文件的文件描述符
int fb_size = 800*480*4; //帧缓冲设备文件的大小
unsigned int *pmap; //映射区首地址
/********************************************
* 功能:初始化LCD显示屏
* 返回值:
* -1:失败
* 0:成功
* 参数:无
********************************************/
int lcdInit()
{
//打开帧缓冲设备文件(/dev/fb0)
fd_lcd = open("/dev/fb0",O_RDWR);
if (-1 == fd_lcd)
{
perror("open lcd error");
return -1;
}
//映射
pmap = mmap(NULL, fb_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd_lcd, 0);
if (MAP_FAILED == pmap)
{
//映射失败
perror("mmap error");
close(fd_lcd);
return -1;
}
return 0;
}
/********************************************
* 功能:关闭LCD显示屏
* 返回值:无
* 参数:无
********************************************/
void lcdClose()
{
//解除映射,释放内存
munmap(pmap, fb_size);
//关闭帧缓冲设备文件
close(fd_lcd);
}
/********************************************
* 功能:显示背景颜色
* 返回值:无
* 参数:
* color:要显示的颜色值
********************************************/
void lcdBrushBG(unsigned int color)
{
for (int y = 0; y < 480; y++)
{
for (int x = 0; x < 800; x++)
{
*(pmap + y*800 + x) = color;
}
}
}
/********************************************
* 功能:在指定的位置像素点
* 返回值:无
* 参数:
* x,y:像素点的坐标
* color:像素点显示的颜色值
********************************************/
void lcdDrawPoint(int x,int y,unsigned int color)
{
if (x >= 0 && x < 800 && y >= 0 && y < 480)
{
//是屏幕范围内的点,画像素点
*(pmap + y*800 + x) = color;
}
}
/********************************************
* 功能:在指定的位置画矩形(实心)
* 返回值:无
* 参数:
* x0,y0:矩形显示的位置(左上顶点的坐标)
* w,h:矩形的宽度和高度
* color:矩形的颜色值
********************************************/
void lcdDrawRect(int x0,int y0,int w,int h,unsigned int color)
{
for (int y = y0; y < y0+h; y++)
{
for (int x = x0; x < x0+w; x++)
{
lcdDrawPoint(x,y,color);
}
}
}
/********************************************
* 功能:在指定的位置画圆形(实心)
* 返回值:无
* 参数:
* x0,y0:圆心的坐标
* r:半径
* color:圆的颜色值
********************************************/
void lcdDrawCircle(int x0,int y0,int r,unsigned int color)
{
for (int y = y0-r; y < y0+r; y++)
{
for (int x = x0-r; x < x0+r; x++)
{
if ((y-y0)*(y-y0)+(x-x0)*(x-x0) <= r*r)
{
//这个坐标到圆心的距离小于等于半径(是圆内的点)
lcdDrawPoint(x,y,color);
}
}
}
}
/********************************************
* 功能:在指定的位置显示文字
* 返回值:无
* 参数:
* x0,y0:文字显示的位置(左上顶点的坐标)
* word:文字取模结果的首地址
* w,h:文字的宽度和高度(像素点个数)
* color:文字的颜色值
********************************************/
void lcdDrawWord(int x0,int y0,unsigned char *word,int w,int h,unsigned int color)
{
//遍历取模结果
int bytes_line = w/8; //每一行数据需要用多少个字节来保存
for (int i = 0; i < w/8*h; i++)
{
//每一个字节的数据对应8个像素点的状态
for (int j = 0; j <= 7; j++)
{
if(word[i]>>7-j & 0x01)
{
//是文字上的点,画像素点
int x = j + (i%bytes_line)*8 + x0;
int y = i/bytes_line + y0;
lcdDrawPoint(x,y,color);
}
}
}
}
/********************************************
* 功能:在指定的位置显示字符串(每个汉字占3个字节)
* 返回值:无
* 参数:
* x0,y0:字符串显示的位置(第一字符左上顶点的坐标)
* count:要显示的字符个数
* word:字符串取模结果的首地址
* w,h:字符的宽度和高度(像素点个数)
* color:字符的颜色值
********************************************/
void lcdDrawStr(int x0,int y0,int count,unsigned char *word,int w,int h,unsigned int color)
{
//逐个显示字符
for (int i = 0; i < count; i++)
{
lcdDrawWord(x0+i*w,y0,word+i*w*h/8,w,h,color);
}
}
/********************************************
* 功能:在指定的位置显示数字(正整数)
* 返回值:无
* 参数:
* x0,y0:数字显示的位置(左边第一个数字左上顶点的坐标)
* number:要显示的数字值
* word:数字0~9取模结果的首地址
* w,h:数字的宽度和高度(像素点个数)
* color:数字的颜色值
********************************************/
void lcdDrawNumber(int x0,int y0,int number,unsigned char *word,int w,int h,unsigned int color)
{
if (number < 0)
{
return;
}
//提取数字各位的值
char bits[20] = {0}; //保存数字各位的值
int wei = 0; //记录数字的位数
//如果数字是0,那么就是一个一位数
if (number == 0)
{
wei = 1;
}
//循环获取数字个位的数,直到number为0
while (number)
{
bits[wei++] = number%10; //提取个位数
number /= 10; //去除个位数
}
//显示数字
for (int i = wei-1; i >= 0; i--)
{
lcdDrawWord(x0+(wei-1-i)*w,y0,word+bits[i]*w*h/8,w,h,color);
}
}
/********************************************
* 功能:在指定的位置显示BMP图片
* 返回值:无
* 参数:
* x0,y0:图片显示的位置(左上顶点的坐标)
* pic_path:要显示的图片文件的路径名
********************************************/
void lcdDrawBMP(int x0,int y0,char *pic_path)
{
//打开图片文件
int fd_pic = open(pic_path,O_RDONLY);
if (-1 == fd_pic)
{
perror("open pic error");
return;
}
//读取图片的参数(魔数、像素数组文件偏移量、宽度、高度、色深)
short MS,depth; //魔数、色深
int offset,w,h; //像素数组的文件偏移量、图片宽度、图片高度
read(fd_pic,&MS,2);
//判断当前图片是不是BMP图片
if (0x4D42 != MS)
{
//不是BMP图片
printf("this pic is not BMP!\n");
close(fd_pic);
return;
}
lseek(fd_pic,0x0A,SEEK_SET);
read(fd_pic,&offset,4);
lseek(fd_pic,0x12,SEEK_SET);
read(fd_pic,&w,4);
read(fd_pic,&h,4);
lseek(fd_pic,0x1C,SEEK_SET);
read(fd_pic,&depth,2);
if (depth < 24)
{
//该BMP图片是24位以下的BMP图片,当前代码不支持显示
printf("The depth of this image is less than 24 bits and thus cannot be displayed.\n");
close(fd_pic);
return;
}
// printf("MS=0x%x,offset=0x%x,w=%d,h=%d,deepth=%d\n",MS,offset,w,h,depth);
//读取像素数组数据
int full_bytes_line = (4-(w*depth/8)%4)%4; //每一行填充的字节数 = (4 - 一行像素点颜色值的有效字节数%4)%4
int buf_size = (w*depth/8+full_bytes_line)*abs(h); //像素数组的大小 = 像素点颜色值的有效字节数+填充字节数
unsigned char buf[buf_size]; //用来保存像素数组数据
lseek(fd_pic,offset,SEEK_SET);
read(fd_pic,buf,buf_size);
//遍历图片上的每个像素点,将其颜色值提取出来按照argb的顺序重新排列组合,并显示到屏幕上去
unsigned char a,r,g,b; //4个颜色分量
unsigned char *p = buf; //为了方便访问数据,通过指针来访问
for (int y = 0; y < abs(h); y++)
{
for (int x = 0; x < w; x++)
{
//获取一个像素点的4个颜色分量值
b = *p++;
g = *p++;
r = *p++;
if (depth == 24)
{
//是一个24位的BMP图片,只有3个颜色分量,a需要手动赋值
a = 0;
}
else if (depth == 32)
{
//是一个32位的BMP图片,有4个颜色分量,a可以直接获取
a = *p++;
}
//将这4个颜色分量按照 a r g b 的顺序重新排列组合成一个32位的颜色值
// a: 1001 1101
// r: 0101 0000
// g: 1010 0010
// b: 0000 1111
// a << 24:
// 1010 1101 0000 0000 0000 0000 0000 0000
// r << 16:
// 0101 0000 0000 0000 0000 0000
// g << 8:
// 1010 0010 0000 0000
// b << 0:
// 0000 1111
// a << 24 | r << 16 | g << 8 | b:
// 1010 1101 0101 0000 1010 0010 0000 1111
unsigned int color = a << 24 | r << 16 | g << 8 | b;
//将该像素点颜色值显示到屏幕上去
if (h > 0)
{
//图像在保存的时候是从下往上保存的,显示也要从下往上显示
lcdDrawPoint(x+x0,h-1-y+y0,color);
}
else
{
lcdDrawPoint(x+x0,y+y0,color);
}
}
//每显示完一行像素点的颜色值,就需要跳过后面的填充数据
p += full_bytes_line;
}
//关闭图片文件
close(fd_pic);
}
main.c:
#include <string.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
//初始化串口
//file: 串口所对应的文件名
//baudrate:波特率
//返回值:成功返回串口设备文件描述符,失败返回-1
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;
}
int main()
{
//初始化串口(如:设备文件/dev/ttySAC1,波特率9600)
int fd_gy39 = init_serial(“/dev/ttySAC1”,9600);
if (-1 == fd_gy39)
{
printf(“GY39 init error!\n”);
return -1;
}
//发送命令(如:0xA5 0x83 0x28) unsigned char cmd[3] = {0xA5,0x83,0x28}; //同时获取光照强度数据和温湿度数据 //往设备文件中写入命令(发送命令) write(fd_gy39,cmd,3); //循环读取传感器数据 ssize_t ret; while (1) { sleep(1); unsigned char data[9+15] = {0}; //光照强度数据9个字节,温湿度数据15个字节 ret = read(fd_gy39,data,sizeof(data)); if (-1 == ret) { //读取GY39数据失败 perror(“read data from GY39 error”); close(fd_gy39); return -1; } else if (ret == 0) { //没有读到数据 printf(“No data was read.\n”); sleep(1); continue; } else if (sizeof(data) != ret) { //读取到的数据长度不正确,数据不完整,放弃这条数据,重新读 printf(“The data is incomplete.\n”); printf(“sizeof(data)=%d,ret=%ld\n”,sizeof(data),ret); continue; } //分析计算传感器数据 if (data[2] == 0x15) { //光照强度数据在前面 if (data[0] != 0x5A && data[1] != 0x5A && data[9] != 0x5A && data[10] != 0x5A) { //数据不是以0x5A开头,数据不完整,放弃这条数据,重新读 printf(“Error in data: data[0]=0x%x data[1]=0x%x,data[9]=0x%x,data[10]=0x%x”); continue; } //计算光照强度数据 float LUX = (data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7])/100; //计算温度 float T = (data[13] << 8 | data[14])/100; //打印或者显示数据 printf(“LUX=%.2f,T=%.2f\n”,LUX,T); } else { //温湿度等数据在前面 if (data[0] != 0x5A && data[1] != 0x5A && data[15] != 0x5A && data[16] != 0x5A) { //数据不是以0x5A开头,数据不完整,放弃这条数据,重新读 // printf(“data[0]=0x%x data[1]=0x%x,data[9]=0x%x,data[10]=0x%x”); continue; } } } //关闭串口文件 close(fd_gy39); return 0;
}
在此程序上修改获取传感器数据,并显示到GEC6818开发板屏幕上去,要显示名称和单位,
实现手控灯和自控灯
最新发布