rt
楼主本学期选修本课程,实验过程中在本站找到
北邮实验:ARM实验板移植Linux操作系统,LCD显示汉字参考教程,但在实际实验阶段发现有该教程存在一定的缺点或讲述不清的地方,经修正后,楼主将自身从零开始的全部实验流程记录在此,以供参考。口才有限,若有表述不清的地方还望批评指正:
实验目的与内容:
实验目的:
1. 熟悉点阵字库的使用
2. 熟悉Linux操作系统的使用
3. 熟悉ARM嵌入式系统开发的过程
实验内容:
1. PC端gcc实现读HZK16点阵字库文件,显示自己的姓名,用*和空格显示。
2. 安装交叉编译工具。
3. 修改程序,交叉编译。
4. 制作新的文件系统镜像、烧写。
一、安装32位ubuntu16.04
本实验课上采用MX1 ADS开发板,ARM9架构,32位系统;目前绝大部分电脑和使用的ubuntu虚拟机都是64位,若采用64位系统进行试验,虽可以完成实验内容点1,但后续安装交叉编译工具、编译时会出现不兼容问题。
建议从一开始就使用32位系统,防止做到后面各种问题导致心态崩掉。
我参照VMware 安装Ubuntu 16.04 32位 全过程安装了32位的Ubuntu16.04。第三步的3、4不用做;若第三步换源时出现无法复制粘贴的问题,可参照下方链接连接解决。
若安装完成后出现ubuntu无法全屏显示的问题(如下图)、无法粘贴复制的文本问题,可参考VMware中让Ubuntu全屏显示(也可解决虚拟机和主机的复制粘贴问题)解决。
已解决全屏显示问题及复制粘贴问题↓(若此时仍无法粘贴,关闭Ubuntu后重新启动即可)
至此,以完成系统安装
二、安装vscode(个人习惯vscode,实际不安装也可以)
参照Ubuntu32位安装VScode(亲测有效)进行安装
三、PC端gcc实现读HZK16点阵字库文件,显示自己的姓名,用*和空格显示
可参照文章开头链接中代码。但由于Ubuntu16.04的gcc版本为5.4.0,版本较低,编译过程中,申请gbArray时,虽然n为3,但实际分配给gbArray的大小远超过3,且值不为00,会导致在打印时出现一些莫名其妙的字符或空格,如下图红框内所示(在高版本的gcc上不会出现这个问题,Ubuntu20.04上没有该问题)
故对test.c进行修改:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "UTF-8toGB2312.c"
void LCD_ShowChar(u16* word)
{
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;
fseek(fphzk, offset, SEEK_SET);
fread(buffer, 1, 32, fphzk);
//一行2个字节,16行,32个字节
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(u16* p,int n)
{
while (*p > 0 && n >0)
{
LCD_ShowChar(p);
p = p + 1;
n = n - 1;
//此处加了一个n,即有多少个汉字。由于在申请gbArray时,虽然n为3,但实际分配的大小远超过3,且值不为00,会导致在打印时出现一些莫名其妙的字符或空格
}
}
int main()
{
const char name[] = "陈奇奇";
int num = strlen(name);
int n = num/3 ;
u16 gbArray[n];
Utf8ToGb2312(name, num, gbArray);
LCD_ShowString((u16*)gbArray,n);
return 0;
}
cp936.h与UTF-8toGB2312.c两个文件无需改动
新建ARM文件夹,将以上三个文件及下发的HZK16字库文件放在文件夹下,在该文件夹下打开terminal,输入gcc test.c -o test命令,在输入./test命令,即可在terminal上看到由*和空格组成的自己的姓名。
四、安装交叉编译工具
1、重设root密码(如果忘了的话)
使用sudo passwd root,后连续输入两次密码,密码不会显示出来
2、安装交叉编译工具arm-linux-gcc
1)sudo cp usr-local-arm-gcc.tar.gz /usr/local 将老师下发的usr-local-arm-gcc.tar.gz复制到 /usr/local 目录下
2)cd /usr/local 转移目录
3)sudo tar -xzf usr-local-arm-gcc.tar.gz 解压缩
4)配置环境:
terminal中输入vi /home/XXXX/.bash.profile 其中XXXX为用户名,例如我的是chenqiqi
在新打开文件中按“i”进入编辑模式,输入一下代码,配置路径
PATH=/usr/local/arm/arm-linux/bin/:/usr/local/arm/bin/:/usr/local/bin:$PATH
export PATH
先按“esc”,再输入:wq保存文件并退出
在terminal输入source /home/XXXX/.bash.profile,使路径配置立刻生效
为确保每次使用时不用重复配置环境,vi /home/chenqiqi/.bashrc ,在最后一行输入“source /home/chenqiqi/.bash.profile”
输入arm-linux-gcc -v,若有下图显示则成功安装交叉编译工具。
如果vi编辑文件时上下左右键出现ABCD现象,逐行执行以下代码,安装vim编辑器:
sudo apt-get update
sudo apt-get remove vim-common
sudo apt-get install vim
此时在chenqiqi用户下,已经完成arm-linux-gcc工具的安装,注意:chenqiqi用户下gcc版本降为3.2.3,root下gcc版本仍为5.4.0。
五、修改程序,交叉编译
对于display代码中的问题进行修改,其中判断条件flag==1改为flag,由于falg是两个字节的与结果,当且仅当flag为0000_0001时,flag==1判断为真,否则判断均为假,即,当falg=0010_0000时,此时应该输出,但是flag此时不为“1”,故不显示。最终结果是只显示一个字16列中的第8列和第16列像素点。
#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 "UTF-8toGB2312.c"
#define Black 0xFFFF
#define White 0x0000
unsigned short *fb=0;
void LCD_ShowChar(int x,int y,u16 *word)
{
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)]*一个字模占用的字节数。
fseek(fphzk, offset, SEEK_SET);
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)//判断条件从flag == 1改为flag
{
*(fb + (x + j * 2)*240 + y + i*16 + k*2) = Black;//xy交换位置
}
}
}
}
fclose(fphzk);
fphzk = NULL;
}
void LCD_ShowString(int x,int y,u16 *p,int n)
{
while(*p>0 && n > 0)
{
LCD_ShowChar(x,y,p);
p = p + 1;
x = x + 40;
n = n - 1;
}
}
void clearScreen() //清屏
{
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[] = "陈奇奇";
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(NULL, 320*240*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd_fb, 0);
clearScreen();
LCD_ShowString(x, y, (u16*)gbArray, n);
return 0;
}
六、制作新的文件系统镜像、烧写
1、首先执行gcc display.c -o display 和 arm-linux-gcc -o display display.c
2、由于ubuntu版本问题,需要安装cramfs工具,工具在下方百度网盘内
链接:https://pan.baidu.com/s/1x6JSxsZ2h8PlcZ4K8HCFwQ?pwd=5zcf
提取码:5zcf
将该压缩包放在ARM文件夹下,执行tar -xvf cramfs_1.1.tar.gz
3、将下发的root.cramfs文件放到ARM文件夹内,在ARM文件夹内新建disk文件夹和newdisk文件夹
4、mount -t cramfs -o loop root.cramfs disk,将 root 文件系统镜像Mount(挂载)到disk文件夹中
5、sudo cp -rf disk/* newdisk,将 disk 目录内的整个 root 文件系统复制到一个新文件夹(例如,newdisk)
6、umount disk,确定完整无误地复制了root文件系统后,Unmount(卸载)disk 内的文件系统
7、在newdisk中新建ARM文件夹,在terminal中输入chmod 777 ARM
8、apt install cramfsprogs,安装mkcramfs工具
9、mkcramfs newdisk newroot.cramfs,生成一个新的 root 文件系统镜像
至此已完成个人pc上的所有操作,到实验室时只需要将自己生成的root文件系统下载到实验板上,
在LCD上观察是否实现预期结果。
以上是个人从零开始完成实验的全部过程,仅供参考,中间部分过程可能会有些繁琐,也是第一次接触虚拟机和ubuntu,若有不完美或者操作繁琐的地方还望海涵。