电子科技大学微机实验报告含思考题河畔下的哈实验6教材.docx
《电子科技大学微机实验报告含思考题河畔下的哈实验6教材.docx》由会员分享,可在线阅读,更多相关《电子科技大学微机实验报告含思考题河畔下的哈实验6教材.docx(14页珍藏版)》请在冰豆网上搜索。
电子科技大学微机实验报告含思考题河畔下的哈实验6教材
实验六
基于ARM的键盘及数码管驱动实验
1.掌握键盘及数码管驱动原理。
2.掌握ZLG7290芯片的使用方法。
3.掌握I2C总线的协议标准。
4.掌握Linux下键盘驱动的实现方法。
编写测试程序控制键盘和数码管。
1.了解ARM9处理器结构
2.了解i2c协议
硬件:
ARM嵌入式开发平台,PC机Pentium100以上。
软件:
PC机Linux操作系统+MINICOM+AMRLINUX开发环境
1、ZLG7290寄存器介绍
ZLG7290内部有16个8bits寄存器,访问这些寄存器需要通过I2C总线接口来实现.访
问内部寄存器要通过“I2C总线地址+子地址”的方式来实现。
ZLG7290B的I2C总线器件
地址是70H(写操作)和71H(读操作)。
?
键值寄存器Key(地址:
01H)
如果某个普通键(K1~K56)被按下,则微控制器可以从键值寄存器Key中读取相应
的键值1~56。
如果微控制器发现ZLG7290的INT引脚产生了中断请求,而从Key中读
到的键值是0,则表示按下的可能是功能键。
键值寄存器Key的值在被读走后自动变成0。
?
显示缓冲区DpRam0~DpRam7(地址:
10H~17H)
DpRam0~DpRam7这8个寄存器的取值直接对应8个数码管的显示内容。
每个寄存器
的8个位分别对应数码管的a,b,c,d,e,f,dp段,MSB对应a,LSB对应dp。
例如大写字母H
的字型数据为6EH(不带小数点)或6FH(带小数点)。
?
命令缓冲区CmdBuf0和CmdBuf1(地址:
07H和08H)
通过向命令缓冲区写入相关的控制命令可以实现段寻址、下载显示数据、控制闪烁等功
能。
2、ZLG7290控制命令介绍
寄存器CmdBuf0(地址:
07H)和CmdBuf1(地址:
08H)共同组成命令缓冲区。
通过
向命令缓冲区写入相关的控制命令可以实现段寻址、下载显示数据、控制闪烁等功能。
?
下载数据并译码(Download)
在指令格式中,高4位的0110是命令字段;A3A2A1A0是数码管显示数据的位地址(其
中A3留作以后扩展之用,实际使用时取0即可),位地址编号依次为0,1,2,3,4,5,6,7,代表
8个数码管,dp控制小数点是否点亮,0-点亮,1-熄灭;flash表示是否要闪烁,0-正
常显示,1-闪烁;d4d3d2d1d0是要显示的数据,包括10种数字和21种字母。
?
闪烁控制(Flash)
在命令格式中,高4位的0111是命令字段;xxxx表示无关位,通常取值0000;第2字
节的Fn(n=0~7)控制数码管相应位的闪烁属性,0-正常显示,1-闪烁。
复位后,所有
位都不闪烁。
3、Linux下i2c驱动接口函数介绍
Linux为我们提供了一系列的接口函数,通过调用这些函数可以很方便的访问到我们的
I2C设备,达到对它的操作和控制。
在本实验中,就是通过调用这些函数,完成对zlg7290
内部寄存器的配置,从而驱动键盘和数码管按照我们需要的方式工作
?
打开设备:
在linux下编程实现对具体设备的操作,首先要做的就是打开要操作的设备文件,zlg7290
设备的设备文件是“/dev/zlg7290/0”。
具体实现函数是:
fd=open(“/dev/zlg7290/0”,O_RDWR)
?
向设备写数据:
具体实现过程是先写入要配置的寄存器的地址,然后写入要配置的值,具体实现函数是:
unsignedchartemp[2];//定义一个数组用于存放要发送的数据,包括寄存器地址和
要写入该寄存器内的值
temp[0]=address;//将要配置的寄存器的地址address写入temp[0]中。
temp[1]=data;//将要写入该寄存器中的值data写入//temp[1]中。
write(fd,temp,2);//用write函数向设备写入数据temp,首先写入地址address,
然后写入值data。
配置一般的寄存器都是这个步骤,但是唯一例外的是配置命令寄存器cmdbuf0和
cmdbuf1,因为写入命令寄存器中的命令码均为16bit,因此需要通过两步完成对命令码的发
送,具体实现代码如下:
unsignedchartemp[3];
temp[0]=address;
temp[1]=cmd1;//要写入的命令码的高八位
temp[2]=cmd2;//要写入的命令码的低八位
write(fd,temp,3);
?
关闭设备:
close(fd);
1.在数码管上显示数据有两种方法,一种方法是直接向8个数据缓冲区DpRam0~
DpRam7写入数据分别控制每个数码管的8个独立led的亮灭,使其显示不同的数据。
2.在数码管上显示数据的另一种方法是直接向命令寄存器cmdbuf0或cmdbuf1写入“下
载数据并译码”命令,直接控制数码管的显示内容,具体译码规则如表一所示。
3.当某个按键被按下时,可以通过读取“键值寄存器Key(地址:
01H)”的值来得到
键值,将所按键的键值显示在数码管上。
4.zlg7290提供数码管的闪烁功能,通过向命令寄存器发送闪烁控制命令可以控制某个
数码管闪烁。
通过按键控制数码管的闪烁,具体功能是当按下键盘1-4时,控制数
码管1-4闪烁。
5.打开一个终端1,将四个源文件交叉编译成arm下的可执行文件example1-example4
(具体参见实验五一些步骤)
6.重新打开一个终端2,输入命令minicom进入ARM开发板的命令行界面,检查硬
件是否连接好后,上电开发板,进入ARM-linux操作系统的命令行。
7.在终端2的ARM-linux操作系统的命令行下依次运行example1-example4可执行程
序,观察结果。
步骤1程序:
#include
#include
#include
#include
//#include"i2c.h"
#defineZLG7290_ADDR_DpRam00x10
intfd;
voidzlg7290_disp(unsignedchar*buf,unsignedcharnum);
intmain()
{
intret,i;
unsignedcharbuf[8];
fd=open("/dev/zlg7290/0",O_RDWR);
if(fd==-1)
{
printf("Can'topenI2Cdevice!
\n");
exit(-1);
}
buf[7]=0xe0;
buf[6]=0xbe;
buf[5]=0xb6;
buf[4]=0x66;
buf[3]=0xf2;
buf[2]=0xda;
buf[1]=0x60;
buf[0]=0xfc;
zlg7290_disp(buf,8);
close(fd);
return0;
}
/******************************************************************************
***************************
**Functionname:
zlg7290_disp
**Descriptions:
controlzlg7290todriverled
**
**Input:
unsignedchar*buf:
displaybuffer
unsignedcharnum:
displaynumber
**Output:
NULL
*******************************************************************************
*************************/
voidzlg7290_disp(unsignedchar*buf,unsignedcharnum)
{
unsignedchari;
unsignedchartemp[2];
for(i=0;i{
temp[0]=ZLG7290_ADDR_DpRam0+i;
temp[1]=*buf;
write(fd,temp,2);
buf++;
usleep(5000);
}
}
/**************************************************************************
**EndOfFile
**************************************************************************/
步骤2程序:
#include
#include
#include
#include
//#include"i2c.h"
#defineZLG7290_ADDR_cmdbuf00x07
intfd;
voidzlg7290_disp(unsignedchar*buf,unsignedcharnum);
intmain()
{
intret,i;
unsignedcharbuf[8];
fd=open("/dev/zlg7290/0",O_RDWR);
if(fd==-1)
{
printf("Can'topenI2Cdevice!
\n");
exit(-1);
}
buf[7]=0x07;
buf[6]=0x06;
buf[5]=0x05;
buf[4]=0x04;
buf[3]=0x03;
buf[2]=0x02;
buf[1]=0x01;
buf[0]=0x00;
zlg7290_disp(buf,8);
close(fd);
return0;
}
/******************************************************************************
***************************
**Functionname:
zlg7290_disp
**Descriptions:
controlzlg7290todriverled
**
**Input:
unsignedchar*buf:
displaybuffer
unsignedcharnum:
displaynumber
**Output:
NULL
*******************************************************************************
*************************/
voidzlg7290_disp(unsignedchar*buf,unsignedcharnum)
{
unsignedchari;
unsignedchartemp[2];
for(i=0;i{
temp[0]=ZLG7290_ADDR_cmdbuf0;
temp[1]=0x60+i;
temp[2]=*buf;
buf++;
write(fd,temp,3);
usleep(5000);
}
}
/**************************************************************************
**EndOfFile
**************************************************************************/
步骤3程序:
#include
#include
#include
#include
//#include"i2c.h"
intfd;
intzlg7290_getkey(char*key);
voidzlg7290_disp(unsignedchar*buf,unsignedcharnum);
intmain()
{
intret,i;
unsignedcharbuf[9];
charkey;
fd=open("/dev/zlg7290/0",O_RDWR);
if(fd==-1)
{
printf("Can'topenI2Cdevice!
\n");
exit(-1);
}
zlg7290_disp(buf,8);
for(;;)
{
if(zlg7290_getkey(&key)!
=0)
{
printf("Readkeyvaluefail\n");
exit(-1);
}
buf[0]=key%10;
buf[1]=key/10;
zlg7290_disp(buf,2);
usleep(1000000);
}
close(fd);
return0;
}
/******************************************************************************
***************************
**Functionname:
zlg7290_getkey
**Descriptions:
getthekeyvaluefromzlg7290
**
**Input:
unsignedshort*key:
thegottenkeyvalue
**Output:
0:
OK-1:
fail
*******************************************************************************
*************************/
intzlg7290_getkey(char*key)
{
unsignedchartemp[2];
temp[0]=1;
temp[1]=0;
if(write(fd,temp,1)!
=1)
return-1;
if(read(fd,temp,2)!
=2)
return-1;
*key=temp[0]+(temp[1]*256);
return0;
}
/******************************************************************************
***************************
**Functionname:
zlg7290_disp
**Descriptions:
controlzlg7290todriverled
**鎺у埗zlg7290椹卞姩led
**Input:
unsignedchar*buf:
displaybuffer
unsignedcharnum:
displaynumber
**Output:
NULL
*******************************************************************************
*************************/
voidzlg7290_disp(unsignedchar*buf,unsignedcharnum)
{
unsignedchari;
unsignedchartemp[3];
for(i=0;i{
temp[0]=0x07;
temp[1]=0x60+i;
temp[2]=*buf;
buf++;
write(fd,temp,3);
usleep(5000);
}
}
/**************************************************************************
**EndOfFile
**************************************************************************/
1.I2C总线数据传输的基本格式?
答:
从左到右依次为:
S:
起始位(START);
SA:
从机地址(SlaveAddress),7位从机地址;
W:
写标志位(Write),1位写标志;
R:
读标志位(Read),1位读标志;
A:
应答位(Acknowledge),1位应答;
?
:
非应答位(NotAcknowledge),1位非应答;
D:
数据(Data),每个数据都必须是8位;
P:
停止位(STOP);
2.要实现控制数码管闪烁的功能,除了向命令寄存器中写入“闪烁控制命令”以外,还有什
么办法可以完成?
答:
向命令寄存器中写入Download指令,其具体值为0110xxxxx10xxxxx.
3.怎么修改数码管闪烁的快慢和时间?
答:
修改闪烁控制寄存器
FlashOnOff(地址:
0CH)的值,复位值为0111,0111B。
高4位表
示闪烁时亮的持续时间,低4位表示闪烁时灭的持续时间。
值为00H时频率最高。
本实验实现了基于ARM的键盘及数码管驱动。