1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > ARM实验板移植Linux操作系统 LCD显示汉字(名字)

ARM实验板移植Linux操作系统 LCD显示汉字(名字)

时间:2023-01-30 20:20:22

相关推荐

ARM实验板移植Linux操作系统 LCD显示汉字(名字)

一、实验目的

1.熟悉点阵字库的使用

2.熟悉Linux操作系统的使用

3.熟悉ARM嵌入式系统开发的过程

二、实验内容

1.pc端编写用×和空格显示自己名字的c程序

2.安装交叉编译工具,修改程序,交叉编译

3.制作新的文件系统镜像,烧写。

三、实验设备及工具

硬件:MX1ADS嵌入式实验平台、PC机

软件:Linux操作系统、交叉编译工具

四、实验原理

1.16×16点阵字库HZK16的使用

GB2312规定对收录的每个字符采用两个字节表示,第一个字节为“高字节”,对应94个区;第二个字节为“低字节”,对应94个位。

每个区记录94个汉字,位号为该字在该区中的位置。

区码:汉字的第一个字节 - 0xA0 (因为汉字编码是从0xA1区开始的,要算出相对区码)位码:汉字的第二个字节 - 0xA0

汉字在HZK16中的绝对偏移位置:offset =[94×(区号-1)+(位号-1)]×一个字模占用的字节数。

2.MX1 ADS液晶显示的硬件结构

MX1 ADS附带的是一块Sharp的TFT显示屏,分辨率320*240, 16位真彩色。每个像素点对应于一个16位色彩描述存储器,颜色描述方式为R5G6B5。

3.BSP-Linux的显示结构

在MX1 ADS上运行的操作系统是BSP-Linux0.3.6(Kernel 2.4.18)。该系统使用的显示驱动是FrameBuffer。

在FrameBuffer驱动模式下,系统将显示设备映射成文件描述符(/dev/fb0)。应用程序只需打开这个文件,调用mmap()将显示存储器映射为用户空间的内存后,即可在用户空间对现存直接进行读/写

五、实验步骤

1.Linux系统上编写输出自己名字的c程序

代码如下

#include <stdio.h>#include <stdlib.h>void LCD_ShowChar(unsigned char *word){FILE* fphzk = NULL;int i, j, k, p, offset;int flag;unsigned char buffer[32];fphzk = fopen("HZK16", "rb");if(fphzk == NULL){fprintf(stderr, "error hzk16\n");}offset = (94*(unsigned int)(*word-0xa0-1)+(*(word+1)-0xa0-1))*32;fseek(fphzk, offset, SEEK_SET);//SEEK_SET(对应 0):文件开头fread(buffer, 1, 32, fphzk);//const void *buffer 为指向二进制数据来源的指针;size_t size 为每个数据单元所占的字节数;//size_t num 为需要读取的数据单元的个数;FILE *stream 为目的文件指针for(j=0; j<16; j++){printf("\n");for(i=0; i<2; i++){for(k=0; k<8; k++){flag = buffer[j*2+i]&(0x80>>k);printf("%s", flag?"* ":" ");}}}fclose(fphzk);fphzk = NULL;}void LCD_ShowString(unsigned char *p){while(*p>0){LCD_ShowChar(p);p=p+2;}}int main(void){LCD_ShowString((unsigned char*)"张三李四");//此处写自己的名字或者任意汉字组合system("pause");return 0;}

2.在Linux系统中建立交叉编译环境并修改程序

(1)解压交叉编译工具

①将armLinuxXToolChain.tar.gz(arm-linux 交叉编译工具)复制到 /usr/local 目录(注意一定要用老师的低版本交叉编译器,不要自己在网上下载)

②终端"cd" 到 /usr/local (意思是所有的命令都要在对应的路径输入,否则会提示找不到文件)

③执行 “tar -xzf armLinuxXToolChain.tar.gz” 命令解压缩

(2)配置环境变量

①打开环境变量文件:sudo gedit /etc/profile

②增加路径设置,在末尾添加如下:

export PATH=$PATH:/usr/local/binexport PATH=$PATH:/usr/local/arm/bin

③注册环境变量:source /etc/profile

④测试是否安装成功:在终端里输入arm-linux-gcc -v

(3)修改代码(先编译执行之前的c代码之后再进行这一步,编译执行的命令请看下一步)

要在LCD上显示需要将printf语句改成在对应地址写寄存器值。首先打开FrameBuffer驱动:fd_fb = open("/dev/fb0", O_RDWR),然后使用mmap()函数映射显示寄存器,返回首地址。

具体代码如下:

#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<sys/mman.h>#include<string.h>#include<stdlib.h>//画笔颜色#define BLACK 0xFFFF#define WHITE0x0000 unsigned short *fb=0;void LCD_ShowChar(int x,int y,unsigned char *word){FILE* fphzk = NULL;int i, j, k, p, offset;int flag;unsigned char buffer[32];fphzk = fopen("HZK16", "rb");if(fphzk == NULL){fprintf(stderr, "error hzk16\n");}offset = (94*(unsigned int)(*word-0xa0-1)+(*(word+1)-0xa0-1))*32;fseek(fphzk, offset, SEEK_SET);//SEEK_SET(对应 0):文件开头fread(buffer, 1, 32, fphzk); for(j=0; j<16; j++){printf("\n");for(i=0; i<2; i++){for(k=0; k<8; k++){flag = buffer[j*2+i]&(0x80>>k);printf("%s",flag?"* ":" ");if(flag==1){*(fb+(j+y)*240+x+i*8+k) = WHITE;}}}}fclose(fphzk);fphzk = NULL;}void LCD_ShowString(int x,int y,unsigned char *p){while(*p>0){LCD_ShowChar(x,y,p);p=p+2;x=x+20;}}int main(void){int fd_fb=0;int x,y;fd_fb=open("/dev/fb0",O_RDWR);fb=(unsigned short*)mmap(0,240*320*2,PROT_READ|PROT_WRITE,MAP_SHARED,fd_fb,0);for(y=0;y<320;y++){for(x=0;x<240;x++){*(fb+y*240+x) = BLACK;}}LCD_ShowString(30,30,(unsigned char*)"张三李四");}

(4)交叉编译

(所有命令行均在该文件夹路径下执行)

对于修改前的代码:

①使用gcc编译:gcc -o display display.c 报错则修改,不报错则继续执行下一步

②执行编译文件:./display

对于修改后的代码:

①使用gcc编译:gcc -o display1 display1.c 报错则修改,不报错则继续执行下一步

②使用arm-linux-gcc编译:arm-linux-gcc -o display1 display1.c

3.制作新的文件系统镜像并烧写

(1)生成root文件系统

①将root文件系统镜像Mount(挂载)到一个空目录(disk),使用如下命令:mount –t cramfs –o loop root.cramfs disk

②将disk目录内的整个root文件系统复制到一个新文件夹newdisk:将挂载后的文件夹在终端打开,输入sudo nautilus获得最高管理员权限,在弹出的文件窗口中操作即可(否则将没有复制权限)

③确定完整无误地复制了root文件系统后,Unmount(卸载)disk 内的文件系统,使用命令如下:

umount disk

④修改newdisk文件夹下所有文件的权限:

chmod -R 777 newdisk/

⑤将经过交叉编译的目标文件display及HZK16字库文件复制到newdisk的bin文件夹中(确保复制后两文件权限为可读写)

⑥使用如下命令生成一个新的 root 文件系统镜像:

mkcramfs newdisk newroot.cramfs

⑦修改newroot的权限:

chmod 777 newroot.cramfs

(2)烧写

将newroot.cramfs文件拷贝至老师电脑某文件夹下,按照第一个实验的第三步(文件系统镜像烧写)进行烧写

①新建超级终端,恢复默认值,码率选择115200,上电

②输入2(文件系统镜像烧写)

③插拔usb激活

④将文件系统镜像文件拷贝到u盘里

⑤弹出u盘(文件拷贝结束的标志)

⑥按任意键开始烧写

⑦烧写结束后按复位键进入文件系统

最终结果

并没有显示成功,显示的位置和大小都对,但是没有显示全,不知道问题出在哪里

还有一个我写的比较高大上的代码,但是也出错了(段错误 访问的内存超出了系统所给这个程序的内存空间)

#include <stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<sys/mman.h>#include<string.h>#include <stdlib.h>//画笔颜色#define WHITE0xFFFF#define BLACK0x0000 #define BLUE0x001F #define BRED 0XF81F#define GRED0XFFE0#define GBLUE0X07FF#define RED 0xF800#define MAGENTA 0xF81F#define GREEN0x07E0#define CYAN 0x7FFF#define YELLOW 0xFFE0#define BROWN0XBC40 //棕色#define BRRED0XFC07 //棕红色#define GRAY 0X8430 //灰色//画笔颜色unsigned short POINT_COLOR = 0x0000;//首地址unsigned short *start_addr;void LCD_DrawPoint(unsigned short x,unsigned short y,unsigned short color){*(start_addr+x+y*240) = color;}//清屏函数//color:要清屏的填充色void LCD_Clear(unsigned short color){unsigned short x,y;for(y=0;y<320;y++){for(x=0;x<240;x++){LCD_DrawPoint(x,y,color);}}} void LCD_ShowChar(unsigned short x,unsigned short y,unsigned char *word,unsigned char mode){FILE* fphzk = NULL;int i, j, k, p, offset;int flag;unsigned char buffer[32];fphzk = fopen("HZK16", "rb");if(fphzk == NULL){fprintf(stderr, "error hzk16\n");}offset = (94*(unsigned int)(*word-0xa0-1)+(*(word+1)-0xa0-1))*32;fseek(fphzk, offset, SEEK_SET);//SEEK_SET(对应 0):文件开头fread(buffer, 1, 32, fphzk);//const void *buffer 为指向二进制数据来源的指针;size_t size 为每个数据单元所占的字节数;size_t num 为需要读取的数据单元的个数;FILE *stream 为目的文件指针if(mode == 0){for(j=0; j<16; j++){y++;for(i=0; i<2; i++){for(k=0; k<8; k++){x++;flag = buffer[j*2+i]&(0x80>>k);if(flag == 1){ LCD_DrawPoint(x,y,POINT_COLOR);} } }}}else if(mode == 1){for(j=0; j<16; j++){x--;for(i=0; i<2; i++){for(k=0; k<8; k++){y++;flag = buffer[j*2+i]&(0x80>>k);if(flag == 1){ LCD_DrawPoint(x,y,POINT_COLOR);} } }}}fclose(fphzk);fphzk = NULL;}void LCD_ShowString(unsigned short x,unsigned short y,unsigned char *p,unsigned char mode){if(mode == 0){while(*p>0){LCD_ShowChar(x,y,p,mode);p=p+2;x=x+20;}}if(mode == 1){while(*p>0){LCD_ShowChar(x,y,p,mode);p=p+2;y=y+20;}}}int main(void){//init();unsigned char x = 0;int fd;int i,a;int delay = 100000000;//100M //使用mmap函数返回首地址fd = open("dev/fb0",O_RDWR);start_addr = (unsigned short*)mmap(0,240*320*2,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);while(1){switch(x){case 0:LCD_Clear(WHITE);break;case 1:LCD_Clear(BLACK);break;case 2:LCD_Clear(BLUE);break;case 3:LCD_Clear(RED);break;case 4:LCD_Clear(GREEN);break;case 5:LCD_Clear(YELLOW);break;case 6:LCD_Clear(GRAY);break;case 7:LCD_Clear(BROWN);break;}x++;if(x==8)x=0;LCD_ShowString(30,30,(unsigned char*)"张三李四",0);//横屏LCD_ShowString(50,50,(unsigned char*)"张三李四",1);//竖屏//延时函数for(i=0;i<delay;i++){a = a;}}}

几点注意的地方

一定要修改所有文件的权限 比如disk、newdisk下所有文件、newroot.cramfs、编译文件等

chmod 777 文件名 为单独修改某文件读写权限命令

chmod -R 777 文件名/ 为修改该文件夹下所有文件权限的命令交叉编译器一定要用老师的第一行第二列位置为fb+1而非fb+2(代码中+1,实际的内存地址+2)不信可以自己在vc上写个测试代码看下地址的变化gcc -o可在pc端执行 arm-linux-gcc -o只能在arm端执行输入sudo nautilus获得最高管理员权限,在弹出的文件窗口中操作,可以解决root解决不了的问题

有问题可以随时给我留言

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。