嵌入式实训报告.docx
《嵌入式实训报告.docx》由会员分享,可在线阅读,更多相关《嵌入式实训报告.docx(22页珍藏版)》请在冰豆网上搜索。
嵌入式实训报告
Cortex-M3课程设计
专业:
电子信息工程
班级:
学号:
姓名:
指导老师:
完成时间:
一、实训的目的
学习和了解了嵌入式在生活中的重要作用和发展过程,熟练掌握arm硬件体系结构,熟悉linux下的嵌入式编程流程,积累自己的软件编写经验,能够参与并实现一个真实和完整的嵌入式项目,为今后的学习和将从事的技术工作打下坚实的基础。
二、实训内容
(一)安装环境
1.安装虚拟机VMware12
直接双击运行虚拟机的安装程序
建议勾选快捷方式的创建,其他可不选
安装完毕后需要输入许可信息
许可信息在文档中,随意选择一个输入即可
2.安装镜像Ubuntu12.04
直接解压Ubuntu标准教学系统,解压位置可随意选择
打开虚拟机,通过虚拟机去访问打开镜像
3.编辑软件
为方便后续程序查看、编辑
4.开发板相关工具安装
4.1首先安装转串口对应驱动
4.2安装串口访问、操作软件、第一次打开时需要输入许可信息、相关许可信息在“说明.txt”中。
4.3设置相关的串口数据,使其连接访问开发板
协议serial
端口COMx有设备管理器查看所得
波特率115200
数据位8
奇偶校验位none
停止位1
数据流控制全部关闭
(二)Linux的基本操作指令
cd切换工作目录
格式:
cdxxx(目标目录的路径)
路径的描述方式:
1.绝对路径:
相对于根目录所做的路径描述
2.相对路径:
相对于当前目录所做的路径描述
ls查看目标文件或目标目录的相关信息
格式:
ls默认查看当前目录下有哪些非隐藏文件
ls-l默认查看当前目录下有哪些非隐藏文件,且附带相关信息
ls-a默认查看当前目录下的所有文件
cp复制并粘贴
格式:
cpxxx(目标文件)xxx(目的目录)
把目标文件复制到目的目录
mv剪切并粘贴/移动
格式:
mvxxx(目标文件)xxx(目的目录)
把目标文件移动到目的目录
rm删除目标
格式:
rmxxx(目标文件或目录)-rf
mkdir创建目录
格式:
mkdirxxx
touch创建文件
格式:
touchxxx
vi/vim
man手册命令
1.manman
1Executableprogramsorshellcommands
命令手册
2Systemcalls(functionsprovidedbythekernel)
系统函数
3Librarycalls(functionswithinprogramlibraries)
库函数
2.man-fxxx(目标)
查看目标所在手册的编号
3.manx(手册编号)xxx(目标)
查看目标在对应编号手册中的具体信息
gcc/arm-linux-gcc
本地编译命令/交叉编译命令
gcc编译生成的文件在Ubuntu中执行
arm-linux-gcc编译生成的文件在开发板上执行
格式:
gcc-oxxx(目标文件)xxx.c(源文件)
或者
gccxxx.c(源文件)-oxxx(目标文件)
-----------------------------------------------
创建共享文件夹:
windows和Ubuntu实现共享
1.点击虚拟机上方菜单的“虚拟机”选项
2.在弹出框中选择“设置”
3.在弹出框中选择“选项”
4.选择“共享文件夹”
5.选择“总是启用”,然后添加自己的共享文件夹
前提是现在windows下有这么个以备共享的文件夹
共享文件夹在Ubuntu中的访问路径:
/mnt/hgfs/
过程:
gec@ubuntu:
~/Desktop$cd/mnt/hgfs/
gec@ubuntu:
/mnt/hgfs$ls
Vmarefile
gec@ubuntu:
/mnt/hgfs$cdvmarefile
gec@ubuntu:
/mnt/hgfs/vmarefile$ls
gec@ubuntu:
/mnt/hgfs/varefile$
文件IO:
input/output
open打开目标文件
#include
#include
#include
intopen(constchar*pathname,intflags);
打开已存在文件
intopen(constchar*pathname,intflags,mode_tmode);
可以打开不存在的文件,即是可以创建并打开文件
intcreat(constchar*pathname,mode_tmode);
创建目标文件
参数:
pathname:
目标文件的所在位置
flags:
权限标志,即是权限的选择
必选项,三选其一
只读O_RDONLY
只写O_WRONLY
可读可写O_RDWR
其它选项:
创建O_CREAT
mode:
文件权限,创建文件时进行赋予
返回值:
成功时,返回一个文件描述符,范围是0~1023
失败时,返回-1
close关闭目标文件
#include
intclose(intfd);
参数;
fd:
目标文件的文件描述符
返回值:
成功时,返回值为0
失败时,返回值为-1
read读取目标文件的数据,到程序空间
#include
项目1:
将1.txt中的内容全部复制到2.txt中
主要代码:
intCopyData(char*pathName1,char*pathName2);
intmain(void)
{
char*pathName1="./1.txt";
char*pathName2="./2.txt";
//WriteDataToFile(pathName2);
CopyData(pathName1,pathName2);
return0;
}
intCopyData(char*pathName1,char*pathName2)
{
intopenFileData_1=open(pathName1,O_RDONLY);//打开文件1
if(-1==openFileData_1)
{
printf("open%serror!
\n",pathName1);
return-1;
}
intopenFileData_2;
if(-1==access(pathName2,F_OK))//目录中文件2不存在
{
openFileData_2=creat(pathName2,S_IRWXU);
if(-1==openFileData_1)
{
printf("create%serror!
\n",pathName2);
return-1;
}
}
else//文件2存在
{
openFileData_2=open(pathName2,O_RDWR);
if(-1==openFileData_2)
{
printf("open%serror!
\n",pathName2);
return-1;
}
}
while
(1)
{
charbuff[1024];
intreadFileData_1=read(openFileData_1,buff,sizeof(buff));//返回值是读到的字节数
if(-1==readFileData_1)
{
printf("can'tread%s\n",pathName1);
return-1;
}
intwriteFileData_2=write(openFileData_2,buff,readFileData_1*sizeof(char));//字节数就是刚才读到字节
if(-1==writeFileData_2)
{
printf("can'twrite%s\n",pathName2);
return-1;
}
if(0==writeFileData_2)//写完跳出
{
break;
}
}
if(-1==close(openFileData_1)||-1==close(openFileData_2))
{
printf("can'tclose%s",openFileData_1==-1?
pathName1:
pathName2);
return-1;
}
}
(三)在ARM开发板上利用LCD模块显示颜色
LCD的使用:
宽度:
800像素点
高度:
480像素点
像素点的位深度:
32位即是4字节
ARGB分别占有一个字节的数据位
A透明度无用
R红色
G绿色
B蓝色
使用数据表示颜色,数据越大,表示对应颜色越深范围是0~255
LCD的设备文件:
/dev/fb0
测试LCD的设备文件:
cat/bin/ls>>/dev/fb0
LCD的像素点排列顺序:
从左向右逐行从上向下
操作流程:
1.在虚拟机中对源程序进行交叉编译(arm-linux-gcc)
2.把交叉编译生成的可执行程序下载到开发板上
2.1在开发板的终端输入rxxxx(目标文件),然后回车
目标文件即是交叉编译生成的可执行文件
2.2点击开发板终端上方的“传输”按钮,选择“发送XModem”
2.3在弹出框中浏览选择目标文件,然后发送
3.下载到开发板的文件默认是没有执行权限的,所以需要赋予其执行权限后,才能被执行
chmod777xxx(下载的目标文件)
4.运行目标文件
./xxx
(四)在开发板上画一个彩虹
主要代码:
intmain()
{
//打开LCD的设备文件
intfd_lcd=open("/dev/fb0",O_RDWR);
if(-1==fd_lcd)
{
printf("openLCDfailed!
\n");
return-1;
}
//映射LCD
int*mmap_lcd=mmap(NULL,
800*480*4,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd_lcd,
0);
if(mmap_lcd==MAP_FAILED)
{
printf("mampLCDfailed!
\n");
return-1;
}
intcolor[7]={
0x00FF0000,
0x00FF7F00,
0x00EAEAAE,
0x0000FF00,
0x0000FFFF,
0x000000FF,
0x00FF00FF
};
intx,y;
intr=120;
//为LCD的每一个像素点填入颜色数据
for(y=0;y<480;y++)//行480
{
for(x=0;x<800;x++)//列800
{
*(mmap_lcd+y*800+x)=0x00FFFFFF;
if((y-240)*(y-240)+(x-400)*(x-400){
*(mmap_lcd+y*800+x)=0x00FFFFFF;
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+10)*(r+10))
{
*(mmap_lcd+y*800+x)=color[0];
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+20)*(r+20))
{
*(mmap_lcd+y*800+x)=color[1];
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+30)*(r+30))
{
*(mmap_lcd+y*800+x)=color[2];
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+40)*(r+40))
{
*(mmap_lcd+y*800+x)=color[3];
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+50)*(r+50))
{
*(mmap_lcd+y*800+x)=color[4];
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+60)*(r+60))
{
*(mmap_lcd+y*800+x)=color[5];
}
elseif((y-240)*(y-240)+(x-400)*(x-400)<(r+70)*(r+70))
{
*(mmap_lcd+y*800+x)=color[6];
}
if(y>240)
{
*(mmap_lcd+y*800+x)=0x00FFFFFF;
}
}
}
//取消LCD的映射
munmap(mmap_lcd,800*480*4);
//关闭LCD的设备文件
close(fd_lcd);
return0;
}
实验结果:
(五)在开发板上完整的显示一张图片
映射:
把目标文件的物理空间映射到程序的内存空间中
#include
void*mmap(void*addr,size_tlength,intprot,intflags,
intfd,off_toffset);
申请一块连续的堆空间,进行映射
intmunmap(void*addr,size_tlength);
释放申请的映射空间
参数:
addr:
映射空间的地址
一般可填NULL,表示由系统自动分配
length:
映射空间的大小,单位字节
prot:
对映射空间属性的选择设置
读写属性的选择设置
PROT_READ
PROT_WRITE
flags:
对映射空间属性的选择设置
共享属性的选择设置
MAP_SHARED
fd:
目标文件的文件描述符
offset:
映射的偏移量
一般,若非特别说明,偏移量为0
返回值:
成功时,返回映射的地址
失败时,返回MAP_FAILED
问题:
LCD作为映射目标,应该申请多大的空间?
800*480*4字节
映射LCD的设备文件成功之后,应该使用什么类型的指针进行接收?
char*可以
int*可以更合适
因为LCD的像素点是4字节
--------------------------------------------------
显示一张800*480大小的24位的bmp图片:
图片文件的大小:
800*480*3+54=1152054字节
问题:
1.图片的颜色数据不足占满全屏
原因:
bmp的像素点位深度是24位
而LCD的像素点位深度是32位
即RGB对ARGB
即每个像素点均少了一个A的字节数据
解决:
为bmp的RGB数据加上一个A的数据
即是需要把3字节的RGB数据填充整合成4字节的ARGB数据
假设:
bmp图片的像素点颜色数据是按照从左向右,从上向下逐行对应
失败
2.图片的颜色显示不对
红底--》蓝底黄色(红+绿)--》青色(蓝+绿)
原因:
bmp的颜色数据的存储顺序是BGR
而不是RGB
解决:
按照正确的顺序重新对应
填充整合成正确的ARGB
3.图片显示上下颠倒
原因:
bmp图片的像素点颜色数据是按照
从左向右,从下向上逐行对应
解决:
把bmp图片的像素点对应数据
上下翻转过后,在给到指定的对应像素点
问题:
像素点(x,y)上下颠倒后,所对应的像素点坐标是?
?
(x,479-y)x的范围:
0~799y的范围:
0~479
4.图片显示发生了偏移
原因:
文件的54字节描述信息在文件头的位置
解决:
移动文件光标,读取正确的颜色数据
方法:
1.直接使用lseek偏移文件光标,然后再读取颜色数据
2.读取文件头的54字节数据,然后再读取颜色数据
显示一张宽度能被4整除的24位bmp图片:
5.显示宽度能被4整除的24位bmp图片
处理:
把针对800*480的处理过程
通过大小的修改,改为针对的图片的大小
文件头的54字节数据信息:
图片的宽度:
第19~22字节的数据信息
图片的高度:
第23~26字节的数据信息
显示一张任意大小的24位bmp图片:
bmp图片存在一个叫做字节补齐的问题
当bmp图片的一行的颜色数据的字节总和不能被4整除时
会在每一行颜色数据之后的位置补上1~3个字节
直至该行能内4整除
即是判断w*3/4的余数是否为0
若需要进行字节补齐,每一行会被补齐几个字节?
直至能被4整除为止,所以一行最多被补上3个字节
计算式:
4-(w*3%4)
处理方式:
1.先把所有的颜色数据和被补齐的数据都读到程序中
然后再进行后续处理
2.循环读取每一行的颜色数据
没读取一行的颜色数据,利用文件光标偏移忽略掉被补齐的字节
主要代码:
intmain()
{
//打开LCD的设备文件
intfd_lcd=open("/dev/fb0",O_RDWR);
if(-1==fd_lcd)
{
printf("openLCDfailed!
\n");
return-1;
}
//映射LCD
int*mmap_lcd=mmap(NULL,
800*480*4,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd_lcd,
0);
if(mmap_lcd==MAP_FAILED)
{
printf("mampLCDfailed!
\n");
return-1;
}
//intcolor=0x00FF0000;
//打开图片文件
intfd_bmp=open("./good.bmp",O_RDWR);
if(-1==fd_bmp)
{
printf("openbmpfailed!
\n");
return-1;
}
charbuf_bmp[800*480*3];
//读取目标图片的颜色数据
read(fd_bmp,buf_bmp,sizeof(buf_bmp));
inti;
intbuf_lcd[800*480];
for(i=0;i<800*480;i++)
{
//ARGBBGRA
buf_lcd[i]=buf_bmp[i*3]|buf_bmp[i*3+1]<<8|buf_bmp[i*3+2]<<16|0x00<<24;
}
close(fd_bmp);
intx,y;
//为LCD的每一个像素点填入颜色数据
for(y=0;y<480;y++)//行480
{
for(x=0;x<800;x++)//列800
{
*(mmap_lcd+y*800+x)=buf_lcd[(479-y)*800+x];
}
}
//取消LCD的映射
munmap(mmap_lcd,800*480*4);
//关闭LCD的设备文件
close(fd_lcd);
return0;
}
(六)将一组图片在屏幕上进行连贯的流水动作
主要代码:
intmain()
{
inti=0;
lcd_open();
for(i=0;i<35;i++)
{
charbuf_pathname[30];
bzero(buf_pathname,sizeof(30));
sprintf(buf_pathname,"abc%d.jpg",i);
usleep(10);
printf("%s\n",buf_pathname);
lcd_draw_jpg(0,0,buf_pathname,NULL,0,0);//显示目标图片
}
close_lcd();
return0;
}
(七)读取磁卡ID,在磁卡中存入数据
实验原理:
GFD引脚
VCC5.0电源正极入输,5~9V
TXD模块数据输出,接MCU的RXD
RXD模块数据输入,接MCU的TXD
GND电源地
主要代码:
intrfid_ctl(introom_id,introom_day,intmod)
{
intret,i;
intfd;
/