8255A是一种有40个引脚的双列直插式标准芯片,其引脚如图2-9所示。除电源(+5V)和地址外,其他信号可以分为两组。
与外设相连接的如下
PA7~PA0:端口A数据线。
PB7~PB0:端口B数据线。
与CPU相连接的如下
PC7~PC0:端口C数据线。
D7-D0:8255A的数据线,和系统数据总线相连RESET
复位信号,高电平有效。当RESET有效时,所有内部寄存器都被清除,同时,3个数据端口被自动设为输入方式。
CS:片选信号,低电平有效。只有当CS有效时,芯片才被选中,允许8255A与CPU交换信息。
RD’:读信号,低电平有效。当RD’有效时,CPU可以从 8255A读取输入数据。
WR’:写信号,低电平有效。当WR’有效时,CPU可以往8255A中写控制字或数据
A1、A0:端口选择信号。8255A内部有3个数据端口和1个控制口,当A1A0=00时选中端口A;A1A0=01时选中端口B,A1A0=10时选中端口C,A1A0=11时选中控制口A1、A0和RD’、WR’、CS’组合所实现的各种功能如表所示。
A1 | A0 | RD’ | WR | CS’ | 操作 |
0 | 0 | 0 | 1 | 0 | 端口A从CPU得到指示 |
0 | 1 | 0 | 1 | 0 | 端口B从CPU得到指示 |
1 | 0 | 0 | 1 | 0 | 端口C从CPU得到指示 |
0 | 0 | 1 | 0 | 0 | CPU从端口A读取数据 |
0 | 1 | 1 | 0 | 0 | CPU从端口B读取数据 |
1 | 0 | 1 | 0 | 0 | CPU从端口C读取数据 |
1 | 1 | 1 | 0 | 0 | CPU控制控制寄存器 |
x | x | x | x | 1 | 数据总线为三态 |
1 | 1 | 0 | 1 | 0 | 非法状态 |
x | x | 1 | 1 | 0 | 数据总线为三态 |
8255A的工作方式
8255A共有3种工作方式,即工作方式0、工作方式1和工作方式2.这些工作方天用软件编程来指定。
(1)工作方式0
工作方式0也叫基本输入/输出方式。这种工作方式不需任何选通信号,端口A、端口B及端口C的高4位和低4位都可以设定为输入或输出。作为输出端口时,输出的数据均被锁存:作为输入端口时,端口A的数据能锁存,端口B与端口C的数据不能锁存。
(2)工作方式1
工作方式1也叫选通输入/输出方式。在这种工作方式下,端口A可由编程指定为输入口或输出口,端口C的高4位用来作为输入/输出操作的控制联络信号;端口B同样可由程指定为输入口或输出口,端口C的低4位用来作为输入/输出操作的控制联络信号。在方式
1下,端口A和端口B的输入数据或输出数据均能被锁存。
(3)工作方式2
8255A的工作方式2仅适合于端口A,这种工作方式下,端口A可作为8位的双向数据传输端口,即可发送数据,也可接收数据。端口C的PC7~PC3用来作为输入/输出的同步控制信号。此时,端口B和PC2~PC0只能编程为方式0或方式1工作,而端口C剩下的3条线可作为输入或输出线使用或用作端口B方式1下的控制线。
8255A的控制字及初始化
8255A为可编程接口芯片,以控制字形式对其工作方式和端口C各位的状态进行设置,它有两种控制字:工作方式控制字和端口C置位/复位控制字。
工作方式控制字用于确定各端口的工作方式及数据传送方向,其格式如表所示。
对工作方式控制字作如下说明
端口A有3种工作方式,而端口B只有2种工作方式。
A组包括端口A与端口C的高4位,B组包括端口B与端口C的低4位。在方式1或方式2下,对端口C的定义(输入或输出)不影响作为联络使用的端口C各位的功能。
最高位(D7)为标志位,D7为方式控制字。
利用端口C置位/复位控制字可以很方便地使端口C8位任一位清0或置1,控制字的格式如表2-4所示。D7位为控制字的标志位,D7=0为端口C置位/复位控制字。
在使用中,控制字每次只能对端口C的一位进行置位或复位。
应注意的是,作为联络信号使用的端口C各位是不能采用置位/复位操作来使其置位或复位的。其数值应视现场的具体情况而定。
工作方式控制字
D0 | 端口C(下口):1输入,0输出 | B组 |
D1 | 端口B(下口):1输入,0输出 | |
D2 | 方式选择:0=方式0,1=方式1 | |
D3 | 端口C(上口):1输入,0输出 | A组 |
D4 | 端口A:1输入,0输出 | |
D5 | 方式选择:D6D5:00=方式0;01=方式1;1x=方式2 | |
D6 | ||
D7 | D7为工作方式控制字标志位 |
端口C置位/复位控制字
D0 | 所选位 置位或复位 设定 | 1=置位,0=复位 |
D3D2D1 | 000=bit0;001=bit1; 010=bit2;011=bit3; 100=bit4; 101=bit5; 110=bit6; 111=bit7; | |
D6D5D4 | 无关位,置000; | |
D7 | D7=0为端口C置位/复位控制字标志位 |
8255A初始化的内容就是向控制寄存器写入工作方式控制字或端口C置位/复位控制字。
这两个控制字可按同一地址写入且不受先后顺序限制,因为两个控制字标志位的状态不同,因此8255A能加以区分。
例如对8255A各口作如下设置:端口A方式0输入,端口B方式0输出,端口C高位部分为输出、低位部分为输入,假设控制寄存器的地址为03FFH,则其工作方式控制字可设置如下。
D0=1:端口C低半部分输入。
D1=0:端口B输出。
D2=0:端口B方式0。
D3=0:端口C高半部分输出。
D4=0:端口A输入。
D6D5=00:端口A方式0。
D7=1:工作方式字标志。
因此工作方式控制字为10010001B,即91H.
8255A与单片机的接口电路
如图2-10所示为8255A与单片机的接口电路。8255A中D7~D0用作地址端口,A0~A1用作地址端口,WR、RD、CS、RESET用作控制端口。
因为8255A所有的寄存器、1/O端口都对应有读写地址,所以可以对8255A的各10□和控制字寄存器进行编址。令A15~A8为01111111,A6~A2为11111时,8255A才会工作。
PA地址:7F7CH。
PB地址:7F7DH。
PC地址:7F7EH。
控制字地址:7F7FH.
8255A代码
#include #include#define a8255_PA XBYTE[0x7f7c] //PA地址#define a8255_PB XBYTE[0x7f7D] //PB地址#define a8255_PC XBYTE[0x7f7E] //PC地址#define a8255_CON XBYTE[0x7f7F]//控制字地址unsigned char bdata IO_flags;//用于表示PA、PB、PC、的当前状态//内容不能被其他程序修改sbit IO_flagsA=IO_flags^0; //PA的当前的输入输出状态sbit IO_flagsB=IO_flags^1; //PB的当前的输入输出状态sbit IO_flagsC=IO_flags^2; //PC的当前的输入输出状态void PABC_cinfig(void);void set_PC(unsigned char PC_num);void clr_PC(unsigned char PC_num);unsigned char const cfg_table[8]={0x80,0x90,0x82,0x92,0x89,0x99,0x8b,0x9b};unsigned char rd_PA(void);//读PAunsigned char rd_PB(void);//读PBunsigned char rd_PC(void);//读PCunsigned char wr_PA(unsigned char PA_data);//写PAunsigned char wr_PB(unsigned char PB_data);//写PBunsigned char wr_PC(unsigned char PC_data);//写PCvoid set_PC(unsigned char PC_num);//PC位操作,置位,PC_num为端口号 0~7void clr_PC(unsigned char PC_num);//PC位操作,复位,PC_num为端口号 0~7void PABC_cinfig(void); //写8255A控制字//写8255A控制字函数//写8255A控制字寄存器void PABC_cinfig(void){a8255_CON=cfg_table[IO_flags];}//端口C配置函数void set_PC(unsigned char PC_num)//置PC(PC_num)为高{ACC=IO_flags;IO_flagsC=0;ACC=IO_flags;PC_num=PC_num<<1;PC_num=(PC_num|0x01);a8255_CON=PC_num;}void clr_PC(unsigned char PC_num)//清PC(PC_num)为低{ACC=IO_flags;IO_flagsC=1;ACC=IO_flags;PC_num=PC_num<<1;PC_num=(PC_num&0xfe);a8255_CON=PC_num;}//端口A、B、C读函数//输出参数PA_data, PA输入的数据//驱动PA实现输入功能,读入PA的并行数据unsigned char rd_PA(void){unsigned char PA_data;ACC=IO_flags;//把状态标志字读到ACC便于进位操作do{IO_flagsA=1;//置PA状态标志字为高 输入IO_flags=ACC;PABC_config();//调用配置子程序,完成对A8255的设置ACC=IO_flags;}while(IO_flagsA==0);//判断状态标志位是否为高 控制字设置完成PA_data=a8255_PA;//把PA的数据读到PA_datareturn(PA_data);//返回PA_data}unsigned char rd_PB(void){unsigned char PB_data;ACC=IO_flags;do{IO_flagsB=1;IO_flags=ACC;PABC_config();//ACC=IO_flags;}while(IO_flagsB==0);PB_data=a8255_PB;return(PB_data);}unsigned char rd_PC(void){unsigned char PC_data;ACC=IO_flags;do{IO_flagsC=1;IO_flags=ACC;PABC_config();//ACC=IO_flags;}while(IO_flagsC==0);PC_data=a8255_PC;return(PC_data);}//写端口A、B、C端口函数//输入函数:PA_data,送PA输出的数据//驱动PA实现输出功能,输出数据到PAunsigned char wr_PA(unsigned char PA_data){ACC=IO_flags;//把状态标志字读到ACC便于进行位操作{IO_flagsA=0;//置PA状态标志位位低_输出IO_flags=ACC;//位操作完成,把ACC的内容写回状态标志字PABC_config();//调用配置子程序,完成A8255的设置ACC=IO_flags;}while((IO_flagsA)==1);//判断状态标志字是否为高 为高,设置未完成,需从新设置a8255_PA=PA_data;//将PA_data的内容送到PA}unsigned char wr_PB(unsigned char PB_data){ACC=IO_flags;{IO_flagsB=0;IO_flags=ACC;PABC_config();ACC=IO_flags;}while((IO_flagsB)==1);a8255_PB=PB_data;}unsigned char wr_PC(unsigned char PC_data){ACC=IO_flags;{IO_flagsC=0;IO_flags=ACC;PABC_config();ACC=IO_flags;}while((IO_flagsC)==1);a8255_PC=PC_data;}