实验一LED显示控制82C55A并行接口数码管显示控制实验.docx
- 文档编号:2086318
- 上传时间:2023-05-02
- 格式:DOCX
- 页数:24
- 大小:357.74KB
实验一LED显示控制82C55A并行接口数码管显示控制实验.docx
《实验一LED显示控制82C55A并行接口数码管显示控制实验.docx》由会员分享,可在线阅读,更多相关《实验一LED显示控制82C55A并行接口数码管显示控制实验.docx(24页珍藏版)》请在冰点文库上搜索。
实验一LED显示控制82C55A并行接口数码管显示控制实验
实验1LED显示控制、82C55A并行接口数码管显示控制
一、实验目的和内容
1.掌握三态门,锁存器构成简单I/O端口的原理及应用
2.完成流水灯及其控制的编程实验
3.进一步掌握8255的使用原理
4.掌握动态LED数码显示的原理
5.完成动态LED数码显示的编程实验
(LED显示控制部分)
二、实验电路及说明
实验电路图1,2,3所示,74ALS273锁存器的输出控制LED发光管的亮暗(1:
亮0:
暗)74ALS273的CLK被一些地址线所控制,它的地址为60H(16进制)
ADD7,ADD6,ADD5,ADD4,ADD3,ADD2,ADD1,ADD0
01100000
只有这时7430与非门才输出低电平(八段LED是阴极型)
在DOS下,它的真实地址为PCI接口板的I/O地址加上60H为真实地址。
如PCI的I/O起始地址0为E000H,I/O起始地址1为E400H。
74ALS273的地址为E460H。
注意:
PCI板卡分配了2块I/O空间,I/O空间0是分配给PCI板卡内部寄存器使用的,即9052专用,空间大小128BYTE。
I/O空间1是分配给PCI板卡用户电路使用的,其大小为256BYTE。
流水灯原理如下:
K1、K2是八位拔动开关(位于区域F)的左边第1、2位。
K1=K2=H发光管从上到下移位
K1=L,K2=H发光管从下到上移位
KI=H,K2=L发光管全部闪烁
K1=K2=L-退出
注:
ON方向为L,OFF方向为H
K1、K2为主板上J41数码拔动开关的1、2位。
图1
图2
图3
三、程序方框图
四、程序代码
录入程序时,请特别注意”1”与英文字母”l”的区别,文件的扩展名为C,即文件名一定是?
?
-?
?
.C。
在每个源程序的开头必须加上如下的注解,并按各人实际填写。
/*
源程序的文件名:
实验序号(01-08)-实验组号(01-24).C
实验名称:
___________________________
实验组号:
___________________________
学生姓名及学号:
________________________
*/
#include
#include
#include“PCIcard.h”
intd1=0,m_bit=0x1;
voidmain()
{
interr,rio,flagm;
intm_k0();
voidm_k1();
voidm_k2();
voidm_k3();
err=findPCIcard();
if(err!
=0)
{
printf("ThePCIcardisn'tfound!
!
!
\n");
flagm=0;
}
err=getPCIbase0();
iobase0=iobase0&0xfffc;
//从PCI配置空间读入的与地址空间有关的数据其bit0位为1,
printf("IOBase0=%xH\n",iobase0);
//表明此空间为IO空间参与PCI总线地址译码
err=getPCIbase1();
iobase1=iobase1&0xfffc;
printf("IOBase1=%xH\n",iobase1);
err=getPCImembase1();
err=getPCImembase0();
membase0=membase0+membase1<<16;
//左移16位,将高位地址变换成双字中的高位字
printf("MEMBase0=%lxH\n",membase0);
err=getPCIIRQ();
printf("PCIIRQ=%d\n",err);
//////////////////////////////////
ioadd1=ioadd1+iobase1;//获取步进电机驱动端口地址
flagm=1;
printf("PressK1andK2tolowtoexit.\n");//选择正、反转或退出
do//主循环
{
rio=inportb(ioadd1);//从IO端口读入数据
rio=rio&0x3;//保留低两位
switch(rio)//判断数据并做相应处理
{
case0:
//为0时LED全亮
flagm=m_k0();
break;
case1:
//为1时LED全部闪烁
m_k1();
break;
case2:
//为2时LED从下到上循环点亮
m_k2();
break;
case3:
//为3时LED从上到下循环点亮
m_k3();
break;
default:
break;
}
}while(flagm==1);
//////////////////////////////////////
return;
}
intm_k0()//LED全亮并退出程序
{
intflagk;
outportb(ioadd1,
(1));
flagk=0;
return(flagk);
}
voidm_k1()//LED闪烁
{
voiddelay1();
if(d1==0)
{
outportb(
(2));
(3);
d1=1;
}
else
{
outportb(ioadd1,0x0);
delay1();
(4);
}
return;
}
voidm_k2()//LED从下到上循环点亮
{
voiddelay1();
inttemp;
temp=m_bit&0x80;
(5);
if(temp==0x80)
m_bit=m_bit|1;
outportb(ioadd1,m_bit);
delay1();
return;
}
voidm_k3()//LED从上到下循环点亮
{
voiddelay1();
inttemp;
temp=m_bit&(6);
m_bit=m_bit>>(7);
if(temp==0x1)
m_bit=m_bit|0x80;
outportb(ioadd1,m_bit);
delay1();
return;
}
voiddelay1()//延时
{
inti,j,a=0;
for(i=1;i<=5000;i++)
{
for(j=1;j<=10000;j++)
{
a=a+0;
}
}
return;
}
将PCIcard.h与上述的C源程序存放在同一目录下,PCIcard.h的内容如下:
#include
#include
#include
unsignedlongintiobase0,iobase1,membase0,membase1;
unsignedlongintinterrupt_line,ioadd1=0x60;
unsignedcharbh;
unsignedcharbl;
intfindPCIcard(void);//找寻PCI卡的总线号及设备号及功能号
intgetPCIbase0(void);//获得PCI卡的IO0的地址
intgetPCIbase1(void);
intgetPCImembase0(void);
intgetPCImembase1(void);
intgetPCIIRQ(void);
structdx
{
intdl;
intdh;
}mydx;
intfindPCIcard(void)//找寻PCI卡的总线号及设备号及功能号
{
unionREGSregs;
regs.h.ah=0xb1;
regs.h.al=0x02;//寻找指定厂商和设备号的PCI卡的位置
regs.x.cx=0x8376;
regs.x.dx=0x10eb;//输入要寻找的厂商号和设备号
regs.x.si=0x00;//输入要寻找的PCI卡索引号
int86(0x1a,®s,®s);//调用指定的X86中断
bl=regs.h.bl;//返回的设备号高5位,低3位为功能号
bh=regs.h.bh;//返回的总线号
return(regs.h.ah);//返回状态
}
intgetPCIbase0(void)//获得PCI卡的IO0的地址
{
unionREGSregs;//定义用C语言调用BIOS中断所用的寄存器组合
regs.h.ah=0xb1;//调用PCIBIOS中断
regs.h.al=0x09;//配置空间用字的方式读入
regs.x.di=0x14;//PCI配置空间中基地址0的地址
regs.h.bl=bl;//要读入配置空间的PCI卡的设备号和功能号
regs.h.bh=bh;//要读入配置空间的PCI卡的总线号
int86(0x1a,®s,®s);//调用指定的X86中断
iobase0=regs.x.cx;//CX为返回的IO0的基地址
return(regs.h.ah);//返回状态
}
intgetPCIbase1(void)
{
unionREGSregs;//同上
regs.h.ah=0xb1;
regs.h.al=0x09;
regs.x.di=0x1c;//PCI配置空间基地址1的地址
regs.h.bl=bl;
regs.h.bh=bh;
int86(0x1a,®s,®s);
iobase1=regs.x.cx;
return(regs.h.ah);
}
intgetPCImembase0(void)
{
unionREGSregs;//同上
regs.h.ah=0xb1;
regs.h.al=0x09;
regs.x.di=0x18;//PCI配置空间存储器基地址0的低位地址
regs.h.bl=bl;
regs.h.bh=bh;
int86(0x1a,®s,®s);
membase0=regs.x.cx;
return(regs.h.ah);
}
intgetPCImembase1(void)
{
unionREGSregs;//同上
regs.h.ah=0xb1;
regs.h.al=0x09;
regs.x.di=0x1a;//PCI配置空间存储器基地址0的高位地址
regs.h.bl=bl;
regs.h.bh=bh;
int86(0x1a,®s,®s);
membase1=regs.x.cx;
return(regs.h.ah);
}
intgetPCIIRQ(void)
{
unionREGSregs;//同上
regs.h.ah=0xb1;
regs.h.al=0x09;
regs.x.di=0x3c;//PCI配置空间中断线的地址
regs.h.bl=bl;
regs.h.bh=bh;
int86(0x1a,®s,®s);
interrupt_line=regs.x.cx;
return(regs.h.cl);
}
五、思考题:
1、在图1中,从数据端口送出”1”使LED亮,还是使LED灭?
2、将K1L、K2L这一点亮退出功能修改为:
自上而下一个一个点亮,然后自下而上一个一个熄灭,循环不断。
3、根据框图和原理填写源程序中的空白处,并写出注解。
(82C55A并行接口数码管实验部分)
二、实验电路及说明
实验电路如图6所示。
动态LED数码显示的原理如下:
8255的A口工作简单输出方式(1:
亮,0:
暗)输出数据(段码)控制所有数码管的不同段。
PB0~3设置为输出,控制4个LED数码管公共端的电流通路(0:
通,1:
断),轮流使其中一个数码管亮,从而构成动态LED数码显示器。
编程要求:
设立一计数单元,该单元做0~9999的十进制加计数。
编制动态LED数码显示的子程序和计数单元计数并显示的主程序。
显示0~F数字并循环。
图6
图7
三、硬件实验步骤
本实验在板上由G与B部分组成,有短路块与跳线两种方式。
短路块为缺省方式。
下面介绍跳线方式。
1、把J16的短路块去掉
2、通过跳线把G区的PA0与数码管部分的B区A相连;
3、PA1与B相连
4、PA2与C相连
5、PA3与D相连
6、PA4与E相连
7、PA5与F相连
8、PA6与G相连
9、PA7与DP相连
10、把B区的J36、J38、J35、J39的短路块去掉
11、J37的第1脚与PB0相连
12、J37的第2脚与PB2相连
13、J37的第3脚与PB1相连
14、J37的第4脚与PB3相连
四、程序框图
BCD码头与7段码关系
00c0H,10f9H20a4H30b0H499H
592H682H70f8H880H998H
A88HB83HC0c6HD0a1HE86H
F8eH
五.程序代码(八段数码显示)
#include
#include
#include“PCIcard.h”
unsignedlongintic8255a=0x0,ic8255b=0x1,ic8255type=0x3;
intbuffer1[10]={0x0c0,0x0f9,0x0a4,0x0b0,0x99,
0x92,0x82,0x0f8,0x80,0x98};
intdis1[4]={0,0,0,0};
voidmain()
{
interr,count1,flagm=1,flag1=1;
voidplus1();
voidmydisp1();
intmypckey();
err=findPCIcard();
if(err!
=0)
{
printf("ThePCIcardisn'tfound!
!
!
\n");
flagm=0;
}
err=getPCIbase0();
iobase0=iobase0&0xfffc;
//从PCI配置空间读入的与地址空间有关的数据其bit0位为1,
printf("IOBase0=%xH\n",iobase0);
//表明此空间为IO空间参与PCI总线地址译码
err=getPCIbase1();
iobase1=iobase1&0xfffc;
printf("IOBase1=%xH\n",iobase1);
err=getPCImembase1();
err=getPCImembase0();
membase0=membase0+membase1<<16;
//左移16位,将高位地址变换成双字中的高位字
printf("MEMBase0=%lxH\n",membase0);
err=getPCIIRQ();
printf("PCIIRQ=%d\n",err);
ic8255a=ic8255a+iobase1;//获取8255A、B口和控制寄存器的地址
ic8255b=ic8255b+iobase1;
ic8255type=ic8255type+iobase1;
printf("Pressetoexit:
\n");//显示提示字符
outportb(
(1));//初始化8255
outportb(ic8255a,
(2));//灭所有的段
outportb(ic8255b,(3));//灭所有的位
do//主循环
{
count1=0xff;//设置计数值
plus1();//将显示数据加1
flag1=1;//将小循环标志置位
do//小循环
{
mydisp1();//调显示子程序
count1=count1-1;//计数值减1
if(count1==0)//判断是否退出小循环
flag1=0;
}while(flag1==1);
flagm=mypckey();//扫描键盘
}while(flagm==1);
////////////////////////////////////////////////////////////////////////////
return;
}
intmypckey()//扫描键盘子程序
{
intpckey1();
intflagk,judge;
judge=pckey1();
if(judge=='e')
flagk=0;
else
flagk=1;
return(flagk);
}
intpckey1()//调用int21H中断
{
unionREGSregs;
regs.h.ah=0x6;
regs.h.dl=0x0ff;
int86(0x21,®s,®s);
return(regs.h.al);
}
voidplus1()//加1子程序
{
inti;
dis1[0]=dis1[0]+1;
for(i=0;i<=2;i++)
{
if(dis1[i]>=10)
{
dis1[i]=dis1[i]-10;
dis1[i+1]=dis1[i+1]+1;
}
else
break;
}
if(dis1[3]>=10)
dis1[3]=0;
return;
}
voidmydisp1()//显示子程序
{
voiddelay1();
inti,a1,a2=0x0fe;
for(i=0;i<=3;i++)
{
outportb(ic8255a,0x0ff);
a1=buffer1[dis1[i]];
outportb(ic8255a,a1);
outportb(ic8255b,a2);
a2=a2<<1;
a2=a2|(4);//作用是:
(5)
delay1();
}
return;
}
voiddelay1()//延时子程序
{
inti,j,a=0;
for(i=1;i<=50;i++){
for(j=1;j<=1000;j++)a=a+0;
}
return;
}
思考题:
1.本实验采用的LED数码管是共阳的还是共阴的?
7407的作用是什么?
2.8255的端口是如何初始化的?
如何实现动态显示的?
用示波器观察PB口的波形,分别画出PB0,PB1,PB2,PB3的波形。
3.Delay1()的延时时间应在什么范围内,可以使LED没有闪烁感?
4.仔细观察LED为什么不该亮的段有隐隐的闪亮?
仔细分析mydiap1()中输出数据的先后关系,如何改进可以消除上述现象?
5.分析main(),CPU的时间主要花在哪个函数上?
常用什么方法可以减少对CPU的占用时间?
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 LED 显示 控制 82 C55A 并行 接口 数码管