程序设计流程图
使用GEC6818开发板,内核链表模拟公交车运行,以及libfont.a 字库显示
test.bmp
test2.bmp
广告显示模块
使用多张图片,做成一个视频
#include "head.h"
void show_video_animation(char pic_names[][25], int num_pics, int x, int y, int delay_ms)
{
for (int i = 0; i < num_pics; i++)
{
if(flag==0)
{
// 显示图片
show_any_bmp(pic_names[i], x, y);
// 等待一段时间
if (delay_ms > 0)
{
// 使用sleep函数实现延时,具体实现可能需要根据操作系统调整
// Windows系统可以使用Sleep函数,Linux系统可以使用usleep函数
#ifdef _WIN32
Sleep(delay_ms);
#else
usleep(delay_ms * 1000);
#endif
}
}
}
}
void* pth_show_ad()
{
char pic_names[][25] = {
"./image/frame_10.bmp",
"./image/frame_11.bmp",
"./image/frame_12.bmp",
"./image/frame_13.bmp",
"./image/frame_14.bmp",
"./image/frame_15.bmp",
"./image/frame_16.bmp",
"./image/frame_17.bmp",
"./image/frame_18.bmp",
"./image/frame_19.bmp",
"./image/frame_20.bmp",
"./image/frame_21.bmp",
"./image/frame_22.bmp",
"./image/frame_23.bmp",
"./image/frame_24.bmp",
"./image/frame_25.bmp",
"./image/frame_31.bmp",
"./image/frame_32.bmp",
"./image/frame_33.bmp",
"./image/frame_34.bmp",
"./image/frame_35.bmp",
"./image/frame_36.bmp",
"./image/frame_37.bmp",
"./image/frame_38.bmp",
"./image/frame_39.bmp",
"./image/frame_76.bmp",
"./image/frame_77.bmp",
"./image/frame_78.bmp",
"./image/frame_79.bmp",
"./image/frame_100.bmp",
"./image/frame_101.bmp",
"./image/frame_102.bmp",
"./image/frame_103.bmp",
"./image/frame_104.bmp",
"./image/frame_105.bmp",
"./image/frame_106.bmp",
"./image/frame_107.bmp",
"./image/frame_108.bmp",
"./image/frame_109.bmp",
"./image/frame_110.bmp",
"./image/frame_111.bmp",
"./image/frame_112.bmp",
"./image/frame_113.bmp",
"./image/frame_114.bmp",
"./image/frame_115.bmp",
"./image/frame_116.bmp",
"./image/frame_117.bmp",
"./image/frame_118.bmp",
"./image/frame_119.bmp",
"./image/frame_120.bmp",
"./image/frame_131.bmp",
"./image/frame_132.bmp",
"./image/frame_133.bmp",
"./image/frame_134.bmp",
"./image/frame_135.bmp",
"./image/frame_136.bmp",
"./image/frame_137.bmp",
"./image/frame_138.bmp",
"./image/frame_139.bmp",
"./image/frame_140.bmp",
"./image/frame_141.bmp",
"./image/frame_142.bmp",
"./image/frame_143.bmp",
"./image/frame_144.bmp",
"./image/frame_145.bmp",
"./image/frame_146.bmp",
"./image/frame_147.bmp",
"./image/frame_148.bmp",
"./image/frame_149.bmp",
"./image/frame_150.bmp",
"./image/frame_151.bmp",
"./image/frame_152.bmp",
"./image/frame_153.bmp",
"./image/frame_154.bmp",
"./image/frame_155.bmp",
"./image/frame_156.bmp",
"./image/frame_157.bmp",
"./image/frame_158.bmp",
"./image/frame_159.bmp",
"./image/frame_160.bmp",
"./image/frame_161.bmp",
"./image/frame_162.bmp",
"./image/frame_163.bmp",
"./image/frame_164.bmp",
"./image/frame_165.bmp",
"./image/frame_166.bmp",
"./image/frame_167.bmp",
"./image/frame_168.bmp",
"./image/frame_169.bmp",
"./image/frame_170.bmp",
"./image/frame_171.bmp",
"./image/frame_172.bmp",
"./image/frame_173.bmp",
"./image/frame_174.bmp",
"./image/frame_175.bmp",
"./image/frame_176.bmp",
"./image/frame_177.bmp",
"./image/frame_178.bmp",
"./image/frame_179.bmp",
"./image/frame_180.bmp",
"./image/frame_181.bmp",
"./image/frame_182.bmp",
"./image/frame_183.bmp",
"./image/frame_184.bmp",
"./image/frame_185.bmp",
"./image/frame_186.bmp",
"./image/frame_187.bmp",
"./image/frame_188.bmp",
"./image/frame_189.bmp",
"./image/frame_190.bmp",
"./image/frame_191.bmp",
"./image/frame_192.bmp",
"./image/frame_193.bmp",
"./image/frame_194.bmp",
"./image/frame_195.bmp",
"./image/frame_196.bmp",
"./image/frame_197.bmp",
"./image/frame_198.bmp",
"./image/frame_199.bmp",
"./image/frame_200.bmp",
"./image/frame_201.bmp",
"./image/frame_202.bmp",
"./image/frame_203.bmp",
"./image/frame_204.bmp",
"./image/frame_205.bmp",
"./image/frame_206.bmp",
"./image/frame_207.bmp",
"./image/frame_208.bmp",
"./image/frame_209.bmp",
"./image/frame_210.bmp",
"./image/frame_211.bmp",
"./image/frame_212.bmp",
"./image/frame_213.bmp",
"./image/frame_214.bmp",
"./image/frame_215.bmp",
"./image/frame_216.bmp",
"./image/frame_217.bmp",
"./image/frame_218.bmp",
"./image/frame_219.bmp",
"./image/frame_220.bmp",
"./image/frame_221.bmp",
"./image/frame_222.bmp",
"./image/frame_223.bmp",
"./image/frame_224.bmp",
"./image/frame_225.bmp",
"./image/frame_226.bmp",
"./image/frame_227.bmp",
"./image/frame_228.bmp",
"./image/frame_229.bmp",
"./image/frame_230.bmp",
"./image/frame_231.bmp",
"./image/frame_232.bmp",
"./image/frame_233.bmp",
"./image/frame_234.bmp",
"./image/frame_235.bmp",
"./image/frame_236.bmp",
"./image/frame_237.bmp",
"./image/frame_238.bmp",
"./image/frame_239.bmp",
"./image/frame_240.bmp",
"./image/frame_241.bmp",
"./image/frame_242.bmp",
"./image/frame_243.bmp",
"./image/frame_244.bmp",
"./image/frame_245.bmp",
"./image/frame_246.bmp",
"./image/frame_247.bmp",
"./image/frame_248.bmp",
"./image/frame_249.bmp",
"./image/frame_250.bmp",
"./image/frame_251.bmp",
"./image/frame_252.bmp",
"./image/frame_253.bmp",
"./image/frame_254.bmp",
"./image/frame_255.bmp",
"./image/frame_256.bmp",
"./image/frame_257.bmp",
"./image/frame_258.bmp",
"./image/frame_259.bmp",
"./image/frame_260.bmp",
"./image/frame_261.bmp",
"./image/frame_262.bmp",
"./image/frame_263.bmp",
"./image/frame_264.bmp",
"./image/frame_265.bmp",
"./image/frame_266.bmp",
"./image/frame_267.bmp",
"./image/frame_268.bmp",
"./image/frame_269.bmp",
"./image/frame_270.bmp",
"./image/frame_271.bmp",
"./image/frame_272.bmp",
"./image/frame_273.bmp",
"./image/frame_274.bmp",
"./image/frame_275.bmp",
"./image/frame_276.bmp",
"./image/frame_277.bmp",
"./image/frame_278.bmp",
"./image/frame_279.bmp",
"./image/frame_280.bmp",
"./image/frame_281.bmp",
"./image/frame_282.bmp",
"./image/frame_283.bmp",
"./image/frame_284.bmp",
"./image/frame_285.bmp",
"./image/frame_286.bmp",
"./image/frame_287.bmp",
"./image/frame_288.bmp",
"./image/frame_289.bmp",
"./image/frame_290.bmp",
"./image/frame_291.bmp",
"./image/frame_292.bmp",
"./image/frame_293.bmp",
"./image/frame_294.bmp",
"./image/frame_295.bmp",
"./image/frame_296.bmp",
"./image/frame_297.bmp",
"./image/frame_298.bmp",
"./image/frame_299.bmp",
"./image/frame_300.bmp",
"./image/frame_301.bmp",
"./image/frame_302.bmp",
"./image/frame_303.bmp",
"./image/frame_304.bmp",
"./image/frame_305.bmp",
"./image/frame_306.bmp",
"./image/frame_307.bmp",
"./image/frame_308.bmp",
"./image/frame_309.bmp",
"./image/frame_310.bmp",
"./image/frame_311.bmp",
"./image/frame_312.bmp",
"./image/frame_313.bmp",
"./image/frame_314.bmp",
"./image/frame_315.bmp",
"./image/frame_316.bmp",
"./image/frame_317.bmp",
"./image/frame_318.bmp",
"./image/frame_319.bmp",
"./image/frame_320.bmp",
"./image/frame_321.bmp",
"./image/frame_322.bmp",
"./image/frame_323.bmp",
"./image/frame_324.bmp",
"./image/frame_325.bmp",
"./image/frame_326.bmp",
"./image/frame_327.bmp",
"./image/frame_328.bmp",
"./image/frame_329.bmp",
"./image/frame_330.bmp",
"./image/frame_331.bmp",
"./image/frame_332.bmp",
"./image/frame_333.bmp",
"./image/frame_334.bmp",
"./image/frame_335.bmp",
"./image/frame_336.bmp",
"./image/frame_337.bmp",
"./image/frame_338.bmp",
"./image/frame_339.bmp",
"./image/frame_340.bmp",
"./image/frame_341.bmp",
"./image/frame_342.bmp",
"./image/frame_343.bmp",
"./image/frame_344.bmp",
"./image/frame_345.bmp",
"./image/frame_346.bmp",
"./image/frame_347.bmp",
"./image/frame_348.bmp",
"./image/frame_349.bmp",
"./image/frame_350.bmp",
"./image/frame_351.bmp",
"./image/frame_352.bmp",
"./image/frame_353.bmp",
"./image/frame_354.bmp",
"./image/frame_355.bmp",
"./image/frame_356.bmp",
"./image/frame_357.bmp",
"./image/frame_358.bmp",
"./image/frame_359.bmp",
"./image/frame_360.bmp",
"./image/frame_361.bmp",
"./image/frame_362.bmp",
"./image/frame_363.bmp",
"./image/frame_364.bmp",
"./image/frame_365.bmp",
"./image/frame_366.bmp",
"./image/frame_367.bmp"
};
while (1)
{
if(flag==0&&page==0)
{
show_video_animation(pic_names, sizeof(pic_names) / sizeof(pic_names[0])-1, 208, 0, 200);
// 数量 ,x=100, y=100, 延时100ms
}
}
return NULL;
}
天气,时间,公告显示模块
天气显示是固定的,可以使用高德api自己获取
#include"head.h"
void* show_now_time(void* arg)
{
char time_str[30]; // 用于存储格式化后的时间字符串
//int fd_active = open("active.txt", O_RDWR);
//char buf[1024];
char ad_name[2][10] = {"AD1.bmp", "AD2.bmp"};
//read(fd_active, buf, sizeof(buf));
while(1)
{
// 获取当前时间
time_t now;
time(&now);
// 格式化时间
struct tm *local = localtime(&now);
if (local == NULL) {
perror("localtime");
exit(EXIT_FAILURE);
}
// 使用strftime来格式化时间字符串
if (strftime(time_str, sizeof(time_str), "%m月%d日 %H:%M:%S", local) == 0)
{
fprintf(stderr, "strftime returned 0");
exit(EXIT_FAILURE);
}
if (flag == 0&&page==0)
{
// 打印当前时间
show_font_time(time_str, 10, 43);
show_font_time("广州市:晴", 10, 130);
show_font_active(buf, 5, 230);
sleep(1);
}
}
close(fd_active); // 关闭文件描述符
return NULL; // 线程函数应该返回一个void指针
}
交互式查询模块
#include"head.h"
void* bus1_now_pth()
{
struct list_head *pos1;
pos1 = head1->list.next;
while (1)
{
node1 = list_entry(pos1, typeof(*node1), list);
printf("bus1 到达站点:%s\n", node1->station);
sleep(5); // bus1 停留 5 秒
pos1 = pos1->next; // 移动到下一个站点
bus1_now++;
if(bus1_now==5)
{
bus1_now=0;
}
show_lacation1(bus1_now);
if (pos1 == &head1->list)
{
pos1 = head1->list.next; // 如果是最后一个节点,则回到起点
}
}
return NULL;
}
void* bus2_now_pth()
{
struct list_head *pos2;
pos2 = head2->list.next;
while (1)
{
node2 = list_entry(pos2, typeof(*node2), list);
printf("bus2 到达站点:%s\n", node2->station);
sleep(4); // bus1 停留 5 秒
pos2 = pos2->next; // 移动到下一个站点
bus2_now++;
if(bus2_now==5)
bus2_now=0;
show_lacation2(bus2_now);
if (pos2 == &head2->list)
pos2 = head2->list.next; // 如果是最后一个节点,则回到起点
}
return NULL;
}
void* bus3_now_pth()
{
struct list_head *pos3;
pos3 = head3->list.next;
while (1)
{
node3 = list_entry(pos3, typeof(*node3), list);
printf("bus3 到达站点:%s\n", node3->station);
sleep(6); // bus1 停留 5 秒
pos3 = pos3->next; // 移动到下一个站点
bus3_now++;
if(bus3_now==5)
bus3_now=0;
show_lacation3(bus3_now);
if (pos3 == &head3->list)
pos3 = head3->list.next; // 如果是最后一个节点,则回到起点
}
return NULL;
}
void show_lacation1(int bus)
{
memset(where1,0,sizeof(where1));
if (bus==0)
{
strcpy(where1," ^ ");
}
if (bus==1)
{
strcpy(where1," ^");
}
if (bus==2)
{
strcpy(where1," ^");
}
if (bus==3)
{
strcpy(where1," ^");
}
if (bus==4)
{
strcpy(where1," ^");
}
}
void show_lacation2(int bus)
{
memset(where2,0,sizeof(where2));
if (bus==0)
{
strcpy(where2,"^ ");
}
if (bus==1)
{
strcpy(where2," ^");
}
if (bus==2)
{
strcpy(where2," ^");
}
if (bus==3)
{
strcpy(where2," ^");
}
if (bus==4)
{
strcpy(where2," ^");
}
}
void show_lacation3(int bus)
{
memset(where3,0,sizeof(where3));
if (bus==0)
{
strcpy(where3,"^ ");
}
if (bus==1)
{
strcpy(where3," ^");
}
if (bus==2)
{
strcpy(where3," ^");
}
if (bus==3)
{
strcpy(where3," ^");
}
if (bus==4)
{
strcpy(where3," ^");
}
}
#include "head.h"
void* show_station()
{
char buf[256];
//int station = *(int*)arg;
// 根据station的不同,更新buf内容
while(1)
{
if(page==1&&flag==1)
{
switch (station)
{
case 1:
{
snprintf(buf, sizeof(buf), "您现在位于 广州站,\n1号线公交现在位于 %s,\n长沙站->上海站->南京站->广州站->桂林站->长沙站\n", node1->station);
show_font_station_info(buf, 285, 88);
show_font_bus_now(where1,285,171);
break;
}
case 2:
{
snprintf(buf, sizeof(buf), "您现在位于 广州站,\n2号线公交现在位于 %s,\n北京站->武汉站->南宁站->深圳站->广州站->北京站\n", node2->station);
show_font_station_info(buf, 285, 88);
show_font_bus_now(where2,285,171);
break;
}
case 3:
{
snprintf(buf, sizeof(buf), "您现在位于 广州站,\n3号线公交现在位于 %s,\n柳州站->吉林站->北海站->重庆站->广州站->柳州站\n", node3->station);
show_font_station_info(buf, 285, 88);
show_font_bus_now(where3,285,171);
break;
}
default:
break;
}
}
}
return NULL;
}
触摸屏事件模块
#include"head.h"
void *event()
{
int fd = open("/dev/input/event0",O_RDWR);
int x,y;
if (fd==-1)
{
perror("触摸屏打开");
return NULL;
}
struct input_event info;
while (1)//等待进入查询页面
{
read(fd,&info,sizeof(struct input_event));
if (info.type==EV_ABS&&info.code==ABS_X)
{
x=info.value;
}
if (info.type==EV_ABS&&info.code==ABS_Y)
{
y=info.value;
}
if (info.type == EV_KEY && info.value == 0)
{
// 检测到触摸屏按下事件
if ((x > 680 && x < 800) && (y > 0 && y < 480))
{
usleep(500000);
flag=1;
page=1;
show_image("test2.bmp",0,0);
printf("page=0\n");
}
if (page==1)//查询页面点击才有效
{
if ((x > 0 && x < 150) && (y > 0 && y < 60))
{
usleep(50000);
flag=0;
page=0;
show_image("test.bmp",0,0);
show_font_time("广州市:晴", 10, 130);
show_font_active(buf, 5, 230);
printf("page=1\n");
}
if ((x > 0 && x < 150) && (y > 60 && y < 200))
{
//show_station(&a);
station=1;
flag=1;
}
if ((x > 0 && x < 150) && (y > 200 && y < 340))
{
//show_station(&b);
station=2;
flag=1;
}
if ((x > 0 && x < 150) && (y > 340 && y < 480))
{
//show_station(&c);
station=3;
flag=1;
}
}
}
}
close(fd);
return NULL;
}
字库
#include "head.h"
// 编译命令:arm-linux-gcc show_font.c -o main -L ./ -lfont -lm
//1、初始化Lcd
struct LcdDevice *init_lcd(const char *device)
{
//申请空间
struct LcdDevice* lcd = malloc(sizeof(struct LcdDevice));
if(lcd == NULL)
{
return NULL;
}
//1打开设备
lcd->fd = open(device, O_RDWR);
if(lcd->fd < 0)
{
perror("open lcd fail");
free(lcd);
return NULL;
}
//映射
lcd->mp = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd->fd,0);
return lcd;
}
//时间,天气
int show_font_time(char *font_buf, int x, int y)
{
//1、打开Lcd屏幕(以读写的形式打开)
struct LcdDevice* lcd = init_lcd("/dev/fb0");
//2、要有字(找到字库并打开)
font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
//字体大小的设置 48是字体的大小
fontSetSize(f,30);
//3、创建一个画板
// 画板长度,宽度,字节像素,画板颜色
bitmap *bm = createBitmapWithInit(183,30,4,getColor(255,255,255,255));
//A B G R
//4、将字写到画板上,形成了一幅画(bm)
//字在画板的起始位置(X:100,Y:0)
fontPrint(f,bm,0,0,font_buf,getColor(0,0,0,0),0);
//A B G R
//5、将这幅画显示到lcd显示屏上
//画板在显示屏上的起始位置(X:0,Y:100)
show_font_to_lcd(lcd->mp,x,y,bm);
//6、关闭字体,关闭画板
fontUnload(f);
destroyBitmap(bm);
munmap(lcd->mp,800*400*4);
close(lcd->fd);
free(lcd);
}
//公告活动
int show_font_active(char *font_buf, int x, int y)
{
//1、打开Lcd屏幕(以读写的形式打开)
struct LcdDevice* lcd = init_lcd("/dev/fb0");
//2、要有字(找到字库并打开)
font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
//字体大小的设置 48是字体的大小
fontSetSize(f,30);
//3、创建一个画板
// 画板长度,宽度,字节像素,画板颜色
bitmap *bm = createBitmapWithInit(190,113,4,getColor(255,255,255,255));
//A B G R
//4、将字写到画板上,形成了一幅画(bm)
//字在画板的起始位置(X:100,Y:0)
fontPrint(f,bm,0,0,font_buf,getColor(0,0,0,0),0);
//A B G R
//5、将这幅画显示到lcd显示屏上
//画板在显示屏上的起始位置(X:0,Y:100)
show_font_to_lcd(lcd->mp,x,y,bm);
//6、关闭字体,关闭画板
fontUnload(f);
destroyBitmap(bm);
munmap(lcd->mp,800*400*4);
close(lcd->fd);
free(lcd);
}
int show_font_station_info(char *font_buf, int x, int y)
{
//1、打开Lcd屏幕(以读写的形式打开)
struct LcdDevice* lcd = init_lcd("/dev/fb0");
//2、要有字(找到字库并打开)
font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
//字体大小的设置 48是字体的大小
fontSetSize(f,30);
//3、创建一个画板
// 画板长度,宽度,字节像素,画板颜色
bitmap *bm = createBitmapWithInit(490,83,4,getColor(255,234,217,153));
//A B G R
//4、将字写到画板上,形成了一幅画(bm)
//字在画板的起始位置(X:100,Y:0)
fontPrint(f,bm,0,0,font_buf,getColor(0,0,0,0),0);
//A B G R
//5、将这幅画显示到lcd显示屏上
//画板在显示屏上的起始位置(X:0,Y:100)
show_font_to_lcd(lcd->mp,x,y,bm);
//6、关闭字体,关闭画板
fontUnload(f);
destroyBitmap(bm);
munmap(lcd->mp,800*400*4);
close(lcd->fd);
free(lcd);
}
int show_font_bus_info(char *font_buf, int x, int y)
{
//1、打开Lcd屏幕(以读写的形式打开)
struct LcdDevice* lcd = init_lcd("/dev/fb0");
//2、要有字(找到字库并打开)
font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
//字体大小的设置 48是字体的大小
fontSetSize(f,30);
//3、创建一个画板
// 画板长度,宽度,字节像素,画板颜色
bitmap *bm = createBitmapWithInit(400,30,4,getColor(255,234,217,153));
//A B G R
//4、将字写到画板上,形成了一幅画(bm)
//字在画板的起始位置(X:100,Y:0)
fontPrint(f,bm,0,0,font_buf,getColor(0,0,0,0),0);
//A B G R
//5、将这幅画显示到lcd显示屏上
//画板在显示屏上的起始位置(X:0,Y:100)
show_font_to_lcd(lcd->mp,x,y,bm);
//6、关闭字体,关闭画板
fontUnload(f);
destroyBitmap(bm);
munmap(lcd->mp,800*400*4);
close(lcd->fd);
free(lcd);
}
int show_font_bus_now(char *font_buf, int x, int y)
{
//1、打开Lcd屏幕(以读写的形式打开)
struct LcdDevice* lcd = init_lcd("/dev/fb0");
//2、要有字(找到字库并打开)
font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
//字体大小的设置 48是字体的大小
fontSetSize(f,30);
//3、创建一个画板
// 画板长度,宽度,字节像素,画板颜色
bitmap *bm = createBitmapWithInit(400,30,4,getColor(255,234,217,153));
//A B G R
//4、将字写到画板上,形成了一幅画(bm)
//字在画板的起始位置(X:100,Y:0)
fontPrint(f,bm,0,0,font_buf,getColor(0,0,0,255),0);
//A B G R
//5、将这幅画显示到lcd显示屏上
//画板在显示屏上的起始位置(X:0,Y:100)
show_font_to_lcd(lcd->mp,x,y,bm);
//6、关闭字体,关闭画板
fontUnload(f);
destroyBitmap(bm);
munmap(lcd->mp,800*400*4);
close(lcd->fd);
free(lcd);
}
显示图片函数
#include "head.h"
int show_any_bmp(char pic_name[], int x, int y)
{
// bmp图片部分的处理
int bmp_fd = open(pic_name, O_RDONLY);
if (bmp_fd == -1)
{
printf("%s\n",pic_name);
return -1;
}
//printf("%s\n",pic_name);
lseek(bmp_fd,14,SEEK_SET);
struct tagBITMAPINFOHEADER buf2;
read(bmp_fd, &buf2, sizeof(buf2)); // 读取bmp文件的内容信息
//printf("图片的长:%d,宽:%d\n", buf2.biWidth, buf2.biHeight);
// 显示任意大小的图片: 需要注意我们的长必须是4的倍数
if (buf2.biWidth%4!=0)
{
perror("not 4");
return -4;
}
char buf[buf2.biWidth*buf2.biHeight*3];
bzero(buf, sizeof(buf));
read(bmp_fd, buf, sizeof(buf)); // 读取颜色数据
// 3字节转4字节处理
int show_buf[buf2.biWidth*buf2.biHeight];
int i=0,j=0;
for( i=0,j=0;i<buf2.biWidth*buf2.biHeight;i++,j+=3)
show_buf[i] = buf[j+0]<<0|buf[j+1]<<8|buf[j+2]<<16;
// 拓展部分
int lcd_buf[buf2.biWidth*buf2.biHeight];
int y1=0;int x1=0;
for( y1=0;y1<buf2.biHeight;y1++)
{
for( x1=0;x1<buf2.biWidth; x1++)
{
lcd_buf[buf2.biWidth*(buf2.biHeight-1-y1)+x1] = show_buf[buf2.biWidth*y1+x1];
}
}
close(bmp_fd);
// 处理屏幕文件
int lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
{
perror("open lcd");
return -2;
}
// 申请映射空间
int *mmap_start = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
if (mmap_start == MAP_FAILED)
{
perror("mmap error");
return -3;
}
int *new_start = mmap_start+y*800+x; // 起点是(100,100)
int n=0;int y2=0;int x2=0;
for( y2=0;y2<buf2.biHeight;y2++)
{
for( x2=0;x2<buf2.biWidth;x2++,n++)
{
new_start[800*y2+x2] = lcd_buf[n];
}
//usleep(1000);
}
// 撤销映射空间
munmap(mmap_start, 800*480*4);
// 关闭lcd文件
close(lcd_fd);
return 0;
}
头文件
#ifndef _HEAD_H_
#define _HEAD_H_
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>//内存
#include <linux/input.h>//触摸
#include <pthread.h>
#include <time.h>
#include "list.h"
//========图片信息====================================================
#define UINT unsigned short
#define DWORD unsigned int
#define LONG unsigned int
#define WORD unsigned short
struct tagBITMAPINFOHEADER{
DWORD biSize; // 本结构所占用字节数(15-18字节)
LONG biWidth; // 位图的宽度,以像素为单位(19-22字节) ------图片的宽度
LONG biHeight; // 位图的高度,以像素为单位(23-26字节) ------图片的高度
WORD biPlanes; // 目标设备的级别,必须为1(27-28字节)
WORD biBitCount;// 每个像素所需的位数,必须是1(双色),(29-30字节) ---位深
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),(31-34字节)
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD biSizeImage; // 位图的大小,以字节为单位(35-38字节) ---图片颜色数据的大小
LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(39-42字节)
LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(43-46字节)
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数(47-50字节)
DWORD biClrImportant;// 位图显示过程中重要的颜色数(51-54字节)
}__attribute__((packed));
//===========================五、字库的变量和函数===========================//
#define color u32
#define getColor(a, b, c, d) (a|b<<8|c<<16|d<<24)
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
typedef struct stbtt_fontinfo
{
void * userdata;
unsigned char * data; // pointer to .ttf file
int fontstart; // offset of start of font
int numGlyphs; // number of glyphs, needed for range checking
int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph
} stbtt_fontinfo;
typedef struct{
u32 height;
u32 width;
u32 byteperpixel;
u8 *map;
}bitmap;
typedef struct{
stbtt_fontinfo *info;
u8 *buffer;
float scale;
}font;
//lcd设备结构体
struct LcdDevice
{
int fd;
unsigned int *mp; //保存映射首地址
};
//1.初始化字库
font *fontLoad(char *fontPath);
//2.设置字体的大小
void fontSetSize(font *f, s32 pixels);
//3.设置字体输出框的大小
bitmap *createBitmap(u32 width, u32 height, u32 byteperpixel);
//可以指定输出框的颜色
bitmap *createBitmapWithInit(u32 width, u32 height, u32 byteperpixel, color c);
//4.把字体输出到输出框中
void fontPrint(font *f, bitmap *screen, s32 x, s32 y, char *text, color c, s32 maxWidth);
//5.把输出框的所有信息显示到LCD屏幕中
void show_font_to_lcd(unsigned int *p,int px,int py,bitmap *bm);
//6、关闭字体库
void fontUnload(font *f);
//7、关闭bitmap
void destroyBitmap(bitmap *bm);
//8、初始化Lcd
struct LcdDevice *init_lcd(const char *device);
//9、显示字, x,y是起点坐标
//时间显示
int show_font_time(char *font_buf, int x, int y);
//活动公告
int show_font_active(char *font_buf, int x, int y);
//站点信息//公交实时信息
int show_font_station_info(char *font_buf, int x, int y);
int show_font_bus_info(char *font_buf, int x, int y);
int show_font_bus_now(char *font_buf, int x, int y);
//===============================字库==============================
//内核链表
typedef struct list_link
{
char station[15];
struct list_head list;
}list,*p_list;
//链表函数
p_list init();
void show_head(p_list head);
void add_node_tail(p_list head,char *data);
//全局变量
//=========================
pthread_t time_id1;
pthread_t ad_id1;
p_list head1;
p_list head2;
p_list head3;
p_list node1, node2, node3;
p_list bus1;
p_list bus2;
p_list bus3;
char where1[100];
char where2[100];
char where3[100];
int bus1_now;
int bus2_now;
int bus3_now;
volatile int flag;
volatile int page;//当前页面标志位
volatile int station;
int fd_active;
char buf[1024];
//====================================================
//函数声明
//显示图片
void show_image(char *image,int x,int y);
int show_any_bmp(char pic_name[], int x, int y);
//显示主界面
void show_main();
//显示时间
void* show_now_time(void* arg) ;
//循环广告
void* show_ad(void* arg);
//视频播放
void show_video_animation(char pic_names[][25], int num_pics, int x, int y, int delay_ms);
//触摸事件
void *event();
//站点查询
void* show_station();
//公交实时位置
void* bus_now();
//公交行走线程,3个
void* bus1_now_pth();
void* bus2_now_pth();
void* bus3_now_pth();
//循环显示公交位置
void show_lacation1(int bus);
void show_lacation2(int bus);
void show_lacation3(int bus);
//广告线程
void* pth_show_ad();
#endif
主函数
#include"head.h"
int main(int argc, char const *argv[])
{
//申请3个头节点,3个公交使用内核链表,循环
head1 =init();
head2 =init();
head3 =init();
//1号线
add_node_tail(head1,"长沙站");
add_node_tail(head1,"上海站");
add_node_tail(head1,"南京站");
add_node_tail(head1,"广州站");
add_node_tail(head1,"桂林站");
//二号线
add_node_tail(head2,"北京站");
add_node_tail(head2,"武汉站");
add_node_tail(head2,"南宁站");
add_node_tail(head2,"深圳站");
add_node_tail(head2,"广州站");
//三号线
add_node_tail(head3,"柳州站");
add_node_tail(head3,"吉林站");
add_node_tail(head3,"北海站");
add_node_tail(head3,"重庆站");
add_node_tail(head3,"广州站");
//初始化全局变量
flag=0;
page=0;
bus1_now=0;
bus2_now=0;
bus3_now=0;
fd_active = open("active.txt", O_RDWR);
read(fd_active, buf, sizeof(buf));
close(fd_active);
show_font_time("广州市:晴", 10, 130);
show_font_active(buf, 5, 230);
//1.====显示广告,时间,天气,公告线程======
pthread_create(&time_id1, NULL, show_now_time, NULL);
//2.====触摸事件线程====================
pthread_t event_id1;
pthread_create(&event_id1,NULL,event,NULL);
//3.=====广告线程=======================
pthread_t show_ad_id1;
pthread_create(&show_ad_id1,NULL,pth_show_ad,NULL);
//4.=====3个公交循环行走线程=============
pthread_t bus1_id;
pthread_create(&bus1_id,NULL,bus1_now_pth,NULL);
pthread_t bus2_id;
pthread_create(&bus2_id,NULL,bus2_now_pth,NULL);
pthread_t bus3_id;
pthread_create(&bus3_id,NULL,bus3_now_pth,NULL);
//5.====更新公交位置线程================
station=0;
pthread_t bus_run;
pthread_create(&bus_run,NULL, show_station, NULL);
//显示主界面
show_image("test.bmp",0,0);
while(1);
return 0;
}