8255是用来扩充接口的芯片。
用上一片8255,就可以为系统增加3个8位的IO接口。
在单片机的教材上,总是使用“三总线”的方式来连接8255。
在这样的条件下,输入/输出数据的速度确实是比较快,一般用2个机器周期,就可以读/写一次。
但是,采用这种形式,电路则是相当麻烦的,必须加上一个锁存器芯片(74LS373);
并且,对于单片机的引脚,占用的也太多了,如P0、P2,还要占用P3.6、P3.7。
呵呵,占用了单片机自身2个半的接口,仅仅换来3个接口,有点得不偿失。
如果搞清楚了8255的读写时序,使用单片机的接口引线“直接控制”8255,效果则要好的多。
下图就是一个“直接控制”8255的电路。
在图中可以看出,仅仅使用了P0和P2的四个引脚,就近,和8255进行连接。
不但节省了引脚数目,而且非常灵活。
在设计实际应用的电路板时,可以随意的就近使用引脚,而不必拘泥于P0、P3.6、P3.7等引脚。
当把8255PA输入的开关量,输出到PC口,使用如下的程序即可。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
汇编语言:
;-----------------------------------
sbitRD_8255=P2^0;设定相关引脚
sbitWR_8255=P2^1;
sbitA0_8255=P2^2;
sbitA1_8255=P2^3;
;-----------------------------------
ORG0000H
MOVP0,#92H;PA输入,PBPC输出
CLRWR_8255;写入控制寄存器
SETBWR_8255
;---------------------
LOOP:
MOVP0,#255;输出1
CLRA1_8255;选定PA
CLRA0_8255
CLRRD_8255;读
NOP;稍延时,以保证宽度
MOVA,P0;读出
SETBRD_8255
;---------------------
SETBA1_8255;选定PC
CLRA0_8255
MOVP0,A;写
CLRWR_8255;写入
SETBWR_8255
;---------------------
SJMPLOOP
END
;-----------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C语言:
//----------------------------------
#include
sbitRD_8255=P2^0;
sbitWR_8255=P2^1;
sbitA0_8255=P2^2;
sbitA1_8255=P2^3;
main()
{
charaa;
P0=0x92;//控制字:PA输入,PBPC输出
A1_8255=1;A0_8255=1;//选中控制寄存器
WR_8255=0;WR_8255=1;//写
while(1){
P0=0xff;//先输出1
A1_8255=0;A0_8255=0;//选中PA
RD_8255=0;aa=P0;RD_8255=1;//读
P0=aa;//这是刚才读入的
A1_8255=1;A0_8255=0;//选中PC
WR_8255=0;WR_8255=1;//写
}
}
//----------------------------------
如果需要用PB输出数据,如下即可:
P0=0xB0;//输出数据
A1_8255=0;A0_8255=1;//选中PB
WR_8255=0;WR_8255=1;//写
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
因为没有使用“三总线”方式,所以,也就没有接口地址的问题。
那么,一般的教材中所说的片外地址,就没有用了。
下面这些C语言中的头文件、宏定义,也用不上了:
#include
#definePAXBYTE[0xE000]/*PA口地址*/
#definePBXBYTE[0xE001]/*PB口地址*/
#definePCXBYTE[0xE002]/*PC口地址*/
#defineCONXBYTE[0xE003]/*控制字地址*/
呵呵,好多知识,统统都没有用了,罪过罪过...
按照这种方式,读写IO口的速度,确实是降低了一些,但是,对于速度要求不太敏感的场合,还是非常适用的。
因为节省了一个锁存器芯片,PCB板的面积,也可以缩小,这就直接使硬件成本得到降低。
有时,一个产品,是否能够占领市场,成本才是关键,读写速度慢上几个微秒,对性能的影响极其微小。
本方案是问题由来:
【问】用at89C51和8255实现扩展I/O口的设计。现在我用8255实现扩展I/O口的设计,以下是我的仿真图片,我程序不知道出什么问题了,本人的程序和图片如下:
include
#include
#definePAXBYTE[0xE000]/*PA口地址*/
#definePBXBYTE[0xE001]/*PB口地址*/
#definePCXBYTE[0xE002]/*PC口地址*/
#defineCONXBYTE[0xE003]/*控制字地址*/
sbitwd=P3^6;//写命令控制端,低电平有效
sbitrd=P3^7;//读命令控制端,低电平有效
voiddelay(intx)//延时函数
{
inti,j;
for(i=x;i>0;i--)
for(j=110;j>0;j++);
}
voidwrite(charcom)//向8255写命令
{
P2=0x80;//选中PB口
wd=0;//写命令置0
delay(5);
P0=com;//写命令
PB=P0;
delay(5);
wd=1;//将写命令端拉高
}
charread()//从8255读命令
{
chardat;
rd=0;
P2=0x00;//选中PA口
delay(2);
if(PA!=0xff)//检测是否有按键按下
{
delay(10);
if(PA!=0xff)
{
dat=PA;//读取PA口德状态
}
}
//delay(5);
rd=1;
return(dat);
}
voidinit()
{
P2=0xc0;//选取控制寄存器
delay(1);
P0=0x90;//把PA设为输入,PB输出,工作方式0;
delay(5);
P2=0x80;//选取PB口
delay(5);
PB=0x00;
//PB=P0;
}
voidmain()
{
inttemp;
init();
delay(10);
while(1)
{
temp=read();
write(temp);
//delay(10);
}
}
8155的文章:http://www.eeskill.com/article/id/50589。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~