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

一、 实验目的

    1. 熟悉点阵字库的使用2. 熟悉Linux操作系统的使用3. 熟悉ARM嵌入式系统开发的过程

二、 实验内容

    1. pc端编写用*和空格显示自己名字的c程序2. 安装交叉编译工具,修改程序,交叉编译3. 制作新的文件系统镜像,烧写

三、 实验设备及工具

    1. 硬件:MX1ADS嵌入式实验平台、PC机2. 软件: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。注意是横轴320个像素,竖轴240个像素。3. BSP-Linux的显示结构在MX1 ADS上运行的操作系统是BSP-Linux0.3.6(Kernel 2.4.18)。该系统使用的显示驱动是FrameBuffer。在FrameBuffer驱动模式下,系统将显示设备映射成文件描述符(/dev/fb0)。应用程序只需打开这个文件,调用mmap()将显示存储器映射为用户空间的内存后,即可在用户空间对显存直接进行读/写

五、 实验步骤

    1. Linux系统上编写输出自己名字的c程序test.c,使用gcc编译运行后发现输出乱码。原因是Linux系统默认汉字编码为utf8,于是引入头文件UTF-8toGB2312.c将utf8转码为GB2312,转码过程为utf8->unicode->gb2312,该文件中还包含有头文件cp936.h用于查表转码。此时gcc编译test.c输出了正常名字2. 在Linux系统中建立交叉编译环境并修改程序(1)解压交叉编译工具①将armLinuxXToolChain.tar.gz(arm-linux 交叉编译工具)复制到 /usr/local 目录(注意一定要用老师的低版本交叉编译器,不要自己在网上下载)②终端"cd" 到 /usr/local ③执行 “tar -xzf armLinuxXToolChain.tar.gz” 命令解压缩(2)配置环境变量打开用户环境变量配置文件:sudo vim ~/.profile在底部添加PATH=/usr/local/arm/arm-linux/bin/:/usr/local/arm/bin/:/usr/local/bin:$PATHexport PATH保存退出后使用:source ~/.profile使修改生效。测试是否生效,在终端输入arm按Tab键看是否补充为arm-linux-gcc(3)修改代码增加寄存器地址操作,使得汉字能够显示在开发板的液晶显示屏上,得到display.c(4)交叉编译代码修改后,使用gcc -o display display.c,若编译成功,则使用arm-linux-gcc -o  display display.c,若编译成功则得到二进制文件display3. 制作新的文件系统镜像并烧写(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盘(文件拷贝结束的标志)⑥按任意键开始烧写⑦烧写结束后按复位键进入文件系统

test.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "UTF-8toGB2312.c"void LCD_ShowChar(u16 *word)  //打印一个汉字:读入32字节1次
{FILE* fphzk = NULL;int i, j, k, p, offset;int flag;unsigned char left=*word>>8,right=*word&0x00ff;unsigned char buffer[32];fphzk = fopen("HZK16", "rb");  //以比特流读取点阵字库文件if(fphzk == NULL){fprintf(stderr, "error hzk16\n");}offset = (94*(unsigned int)(left-0xa1)+(right-0xa1))*32; //[94*(区号-1)+(位号-1)]*一个字模占用的字节数=汉字在HZK16中的绝对偏移位置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++){      //16行循环printf("\n");        for(i=0; i<2; i++){       //每行2字节for(k=0; k<8; k++){         //移位8次打印每个bit对应符号flag = buffer[j*2+i]&(0x80>>k);     //从左到右循环检测bit是否为1,是则打印*,否则打印空格printf("%s", flag?"* ":"  ");}}}/*for ( j = 0; j <16; j++)
{printf("\n");for (i = 0; i < 16; i++){flag = buffer[j]&(0x8000>>i);     //从左到右循环检测bit是否为1,是则打印*,否则打印空格printf("%s", flag?"* ":"  ");}}*/fclose(fphzk);fphzk = NULL;}
void LCD_ShowString(u16 *p)
{while(*p>0){LCD_ShowChar(p);p=p+1;}
}/*
int len(unsigned char *p)
{int L=0;while (*p!='\0'){L++;p++;}return L+1;
}
*/int main()
{const char  name[]="郑海峰";int num=strlen(name);int n=num/3;u16 gbArray[n];Utf8ToGb2312(name,num,gbArray); LCD_ShowString((u16*)gbArray);//此处写自己的名字或者任意汉字组合,utf8编码似乎不对,需要cp936//pause();return 0;
}

cp936.h
UTF-8toGB2312.c

#include <stdio.h>
#include <string.h>
#include "cp936.h"int GetUtf8ByteNumForWord(u8 firstCh)   //num表示firstCh中从最开始的连1的个数,utf8编码中代表该字符所占字节数,若为0则只占1字节
{u8 temp = 0x80;int num = 0;while (temp & firstCh){num++;temp = (temp >> 1);}//printf("the num is: %d\n", num);return num;
}u16 SearchCodeTable(u16 unicodeKey)     //搜索转码表,搜索成功则返回unicodeKey对应的GB2312编码,否则返回0
{int first = 0;int end = CODE_TABLE_SIZE - 1;int mid = 0;while (first <= end){mid = (first + end) / 2;if (code_table[mid].unicode == unicodeKey){return code_table[mid].gb;}else if (code_table[mid].unicode > unicodeKey){end = mid - 1;}else {first = mid + 1;}}return 0;
}void Utf8ToGb2312(const char* utf8, int len,u16* gbArray)   //utf8转为GB2312,len是utf8字符串长度
{int k=0;int byteCount = 0;int i = 0;int j = 0;char temp[10];u16 unicodeKey = 0;u16 gbKey = 0;//循环解析while (i < len){   switch(GetUtf8ByteNumForWord((u8)utf8[i])){case 0:temp[j] = utf8[i];byteCount = 1;break;case 2:temp[j] = utf8[i];temp[j + 1] = utf8[i + 1];byteCount = 2;break;case 3://这里就开始进行UTF8->Unicodetemp[j + 1] = ((utf8[i] & 0x0F) << 4) | ((utf8[i + 1] >> 2) & 0x0F);   //temp数组储存的是Unicode,字符长度为1或2字节temp[j] = ((utf8[i + 1] & 0x03) << 6) + (utf8[i + 2] & 0x3F);//取得Unicode的值memcpy(&unicodeKey, (temp + j), 2);//根据这个值查表取得对应的GB2312的值gbKey = SearchCodeTable(unicodeKey);    //printf("gbKey=0x%X\n",gbKey);gbArray[k++]=gbKey;         //gbArray数组储存GB2312码,字符长度为2字节byteCount = 3;break;case 4:byteCount = 4;break;case 5:byteCount = 5;break;case 6:byteCount = 6;break;default:printf("the len is more than 6\n");break;    }i += byteCount;if (byteCount == 1){j++;}else{j += 2;}}//return gbKey;
}

display.c

#include <stdio.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<string.h>#include <unistd.h>
//#include "encode.h"
#include "UTF-8toGB2312.c"
#define Black   0xFFFF
#define White   0x0000
#define Yellow  0xffe0
#define Blue    0x001f//  屏幕分辨率为320*240,所以横轴的长度为320个像素,竖轴长度为240个像素点,真彩色每个像素点16bit
unsigned short *fb=0;   //unsigned short 占2个字节,对应于一个真彩像素点的16bit,注意理解之后的像素打印//GB2312的编码储存在*word中;word是该汉字的GB2312编码的指针
void LCD_ShowChar(int x,int y,u16 *word)  //打印一个汉字:需要根据汉字编码所指位置从字库文件读入32字节
{FILE* fphzk = NULL;       //字库文件的文件指针int i, j, k, p, offset;int flag;unsigned char left=*word>>8,right=*word&0x00ff;unsigned char buffer[32];     //一个汉字的字模占32字节=16*2字节fphzk = fopen("HZK16", "rb");  //以比特流读取点阵字库文件if(fphzk == NULL){fprintf(stderr, "error hzk16\n");}offset = (94*(unsigned int)(left-0xa1)+(right-0xa1))*32; //[94*(区号-1)+(位号-1)]*一个字模占用的字节数=汉字在HZK16中的绝对偏移fseek(fphzk, offset, SEEK_SET);//SEEK_SET(对应 0):文件开头作为初始位置;加上偏移得到要读取的字模的初始地址fread(buffer, 1, 32, fphzk);   //从fphzk开始连续读取32个size为1字节的数据单元到buffer[32]//const void *buffer 为指向二进制数据来源的指针;size_t size 为每个数据单元所占的字节数;//size_t num 为需要读取的数据单元的个数;FILE *stream 为目的文件指针for(j=0; j<16; j++){      //16行循环printf("\n");        for(i=0; i<2; i++){       //每行2字节for(k=0; k<8; k++){         //移位8次打印该字节中每个bit对应符号flag = buffer[j*2+i]&(0x80>>k);     //从左到右循环检测bit是否为1,是则打印*,否则打印空格printf("%s", flag?"* ":"  ");if(flag==1){*(fb+(y+j)*320+x+i*8+k)=Black;     //对内存映射区地址赋值,在屏幕的(x,y)对应位置显示一个黄色像素点}}}}fclose(fphzk);    //关闭文件fphzk = NULL;    //释放文件指针fphzk,这带来一个问题,每打印一个汉字就要打开关闭文件一次}
void LCD_ShowString(int x,int y,u16 *p) //p指向每个汉字的GB码的第一个字节,由于一个汉字是2字节,故打印一个汉字p就要加2
{while(*p>0){LCD_ShowChar(x,y,p);p=p+1;x=x+20;   //(x,y)是打印起始点,打印完一个汉字后,打印起始点向右移动20个像素点,此处的x代表横轴像素点数是由之前的像素打印公式决定的}
}void clearScreen()  //Black 清屏
{int x,y;for(y=0;y<240;y++){for(x=0;x<320;x++){*(fb+y*320+x) = White;}}
}int main()
{const char  name[]="郑海峰";/*const char zhf[7];if(UTF8_to_GBK(name,10,zhf,7)<0){printf("error");return 0;}*/int num=strlen(name);int n=num/3;u16 gbArray[n];Utf8ToGb2312(name,num,gbArray); int fd_fb=0;int x=100,y=140;fd_fb=open("/dev/fb0",O_RDWR,0);fb=(unsigned short*)mmap(0,320*240*2,PROT_READ|PROT_WRITE,MAP_SHARED,fd_fb,0);clearScreen();LCD_ShowString(x,y,(u16*)gbArray);//此处写自己的名字或者任意汉字组合,utf8编码似乎不对,需要cp936//pause();         return 0;
}

北邮实验:ARM实验板移植Linux操作系统,LCD显示汉字相关推荐

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

    一.实验目的 1.熟悉点阵字库的使用 2.熟悉Linux操作系统的使用 3.熟悉ARM嵌入式系统开发的过程 二.实验内容 1.pc端编写用×和空格显示自己名字的c程序 2.安装交叉编译工具,修改程序, ...

  2. 北邮嵌入式linux开发,北邮嵌入式系统实验报告完整版

    北邮嵌入式系统实验报告完整版 北京邮电大学 嵌入式系统实验 实验报告 学院:电子工程学院 专业:电子信息科学与技术 班级:班 学号: 姓名: 2013年11月13日 一.实验目的 1.基本实验 搭建P ...

  3. [2021]Linux下C语言qrencode二维码生成库的基本使用和ARM开发板移植

    文章目录 一.前言 二.准备所用到的环境以及版本信息 1.Ubuntu和内核版本 2.gcc和g++版本 3.交叉编译gcc和g++版本 4.开发板信息 三.开发环境编译&安装qrencode ...

  4. 北邮数电实验三接球小游戏

    文章目录 前言 一.实验要求 二.设计思路 三.设计系统框图 四.源代码 五.遇到的问题和解决办法 六.总结 前言 北邮数电实验三"接球小游戏" 数电实验验收已经结束了,实验报告也 ...

  5. 北邮 计算机学院数据库实验报告二,北邮数据库_sql实验二报告.doc

    <北邮数据库_sql实验二报告.doc>由会员分享,提供在线免费全文阅读可下载,此文档格式为doc,更多相关<北邮数据库_sql实验二报告.doc>文档请在天天文库搜索. 1. ...

  6. 电脑向linux板卡传文件,ARM 开发板嵌入式linux系统与主机PC通过串口传输文件

    ARM 开发板嵌入式linux系统与主机PC通过串口传输文件 本来以为按以下两篇文章就可以几步轻松搞定这个问题,没想到遇到两个小麻烦: 1,我用的xp虚拟机下redhat9.0做主机,按照下面第一篇文 ...

  7. arm开发板移植 curl

    arm开发板移植 curl 一,下载curl源码 二,配置curl 三,移植到arm平台上 三,arm平台curl测试 一,下载curl源码 地址:https://curl.haxx.se/downl ...

  8. Xilinx zynq-7000系列FPGA移植Linux操作系统详细教程

    Xilinx zynq-7000系列FPGA移植Linux操作系统详细教程 一:前言 最近手上压了一块米联客的Miz7035,一块xilinx zynq-7000系列的开发板,想着正好学习一下linu ...

  9. 实战Linux操作系统双屏显示(转)

    实战Linux操作系统双屏显示(转) 现在市面上的大多数显示卡配有两个视频输出(双VGA或者双DVI或者VGA + DVI),在Windows XP下借助驱动程序我们很容易配置双显,获得双倍的显示面积 ...

最新文章

  1. 《强化学习周刊》第6期:强化学习应用之推荐系统
  2. 远看像乱序执行,近看是内存屏障的 BUG 是如何解决的?
  3. 无法连接MySQL_MySQL不能从外部 连接的解决方法
  4. 江湖救急,换对姿势比《颈椎病康复指南》更有效丨极客官舍
  5. Oracle中如何删除某个用户下的所有数据的方法
  6. Silverlight实用窍门系列:56.Silverlight中的Binding使用(一)【附带实例源码】
  7. Python 用pygame模块播放MP3
  8. Codeforces Round #503 (by SIS, Div. 2)
  9. 以编程方式管理IIS
  10. Hybrid APP的离线存储总结
  11. 算法题6 b站扭蛋机
  12. [AHK]如何更改键盘快捷方式,在 Windows 10 中的虚拟桌面之间切换
  13. 海淘转运攻略之2017年黑色星期五海淘转运公司对比推荐
  14. android11用石墨文档,轻协作 | 石墨文档 for Android 版轻体验
  15. 获得商品详情API接口
  16. 遭遇软件兼容问题——风云防火墙+江民杀毒软件+NetLimiter
  17. 絮絮叨叨的写一年毕业经历
  18. 项目管理 | 什么是项目管理计划?
  19. 使用Python操作CAD的dxf文件,批量绘制变形图的方法记录
  20. 周末的一点心得和总结(Latex技巧,多巴胺和韦伯-费希纳定律还有微商)

热门文章

  1. mysql floor 不准确_MYSQL的floor出现报错如何解决
  2. NB-IOT与物联网
  3. 台灯显色指数多少合适?专家教你护眼灯怎么选
  4. 你说的H5到底是什么,跟Html有什么关系,能吃吗
  5. Window server 2008 搭建FTP服务器
  6. 入门系列之改进小波阈值降噪
  7. C语言中strchr和strrchr函数及用法
  8. Python递归函数应用之计算阶乘
  9. matlab集群版,分布式Matlab计算集群建立方法与Demo
  10. 5个开发必备的 Python 工具,你用过几个?