本节书摘来自异步社区《51单片机应用开发范例大全(第3版)》一书中的第2章,第2.2节,作者 张杰,宋戈,黄鹤松,员玉良,更多章节内容可以访问云栖社区“异步社区”公众号查看。
用串口扩展I/O口非常实用,但是串口是按位读取的,输入的数据必须重组后才能使用,速度受到限制,同时还需要严格的时钟配合。
在有些场合,利用串口扩展I/O口不是很理想,比如BCD码的输入及多组速率较高的并行数据的输入。所以,用并行数据端口扩展I/O口也是很有必要的。
BCD码由四位二进制数组成,有些设备直接以BCD码的形式收发数据。如果这类接口的设备比较多,就需要扩展4位并行接口。本设计利用单片机4个I/O接口,扩展成4个4位的并行I/O端口,用于4位并行数据的输入/输出。
1.8243简介
8243共有4个4位的并行I/O端口,即P4、P5、P6、P7口,这4个端口均可独立地设置为输入口或输出口。由于各端口均为4位。因此,十分适宜用于BCD码的输入/输出。图2-7所示为8243引脚图,具体引脚说明如下。
PROG信号用于选择P2口的功能。在进行输入/输出时,先通过P2口传送选择端口及端口操作方式的控制命令,该命令由PROG的下跳沿所存至8243内部的指令寄存器和地址译码器,而进行的数据传送,由PROG的上跳沿将数据通过指定的端口输入/输出。P2传送命令时,由P2.1和P2.0指定端口地址,由P2.3和P2.2规定端口的工作方式,各位具体的定义如表2-1所示。
表中的“或”、“与”方式是指分别把输出的数据与被寻址端口的内容进行“逻辑或”以及“逻辑与”运算后再写入该端口。
2.8243与单片机的接口设计
以下是单片机串口驱动8243的程序代码:
#include<reg52.h> sbit ContrBit0=P1^0; sbit ContrBit1=P1^1; sbit ContrBit2=P1^2; sbit ContrBit3=P1^3; sbit PROG=P1^4; sbit CS=P1^5; char driver8243(char sele_P,char sele_M,char out_data) { char in_data=0; char data_buf; PROG=1; //置PROG为高电平 //----------------------------开始写控制字------------------------------ if((sele_P&0x01)==0) //将控制字最低位送到8243的p2.0 ContrBit0=0; else ContrBit0=1; if((sele_P&0x02)==0) //将控制字第二位送到8243的p2.1 ContrBit1=0; else ContrBit1=1; //以上两位共同指定端口地址 //-------------------------写端口工作模式控制字-------------------------- if((sele_M&0x01)==0) //将端口工作模式控制字低位送到8243的p2.2 ContrBit2=0; else ContrBit2=1; if((sele_M&0x01)==0) //将端口工作模式控制字高位送到8243的p2.3 ContrBit3=0; else ContrBit3=1; //完成写控制字 PROG=0; //在PROG上产生下降沿 switch(sele_M&0x03) //判断工作模式 { case 0: break; //sele_M=B00为输入,不处理,等待上升沿 case 1: data_buf=out_data; break; //sele_M=B01为输出,直接送数据 case 2: data_buf=out_data; break; //sele_M=B10为逻辑或,直接送数据 case 3: data_buf=out_data; break; //sele_M=B11为逻辑与,直接送数据 } PROG=1; //产生上升沿 if((sele_M&0x03)==0) //sele_M=B00为输入,接收数据 in_data=(data_buf&0x0F); return(in_data); //sele_M=B00,返回接收到的数据 } //sele_M!=B00,返回0 void main( void) { char receive_data; receive_data=driver8243(1,0,5); }可编程并行I/O接口芯片8255A是Intel公司生产的标准外围接口电路。它采用NMOS工艺制造,用单一+5V电源供电,具有40条引脚,采用双列直插式封装。它有A、B、C共3个端口共24条I/O线,可以通过编程的方法来设定端口的各种I/O功能。由于它功能强,又能方便地与各种微机系统相连,而且在连接外部设备时,通常不需要再附加外部电路,所以得到了广泛的应用。
1.8255A的引脚介绍
8255A是一种有40个引脚的双列直插式标准芯片,其引脚如图2-9所示。除电源(+5V)和地址外,其他信号可以分为两组。
与外设相连接的如下。
PA7~PA0:端口A数据线。PB7~PB0:端口B数据线。PC7~PC0:端口C数据线。与CPU相连接的如下。
2.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下的控制线。
3.8255A的控制字及初始化
8255A为可编程接口芯片,以控制字形式对其工作方式和端口C各位的状态进行设置,它有两种控制字:工作方式控制字和端口C置位/复位控制字。
工作方式控制字用于确定各端口的工作方式及数据传送方向,其格式如表2-3所示。
对工作方式控制字作如下说明。
端口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各位是不能采用置位/复位操作来使其置位或复位的。其数值应视现场的具体情况而定。
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。
4.8255A与单片机的接口电路
因为8255A所有的寄存器、I/O端口都对应有读写地址,所以可以对8255A的各I/O口和控制字寄存器进行编址。令A15~A8为01111111,A6~A2为11111时,8255A才会工作。
PA地址:7F7CH。PB地址:7F7DH。PC地址:7F7EH。控制字地址:7F7FH。5.8255A驱动程序设计
8255A的驱动程序主要是涉及对端口A、B、C以及控制字的设置,8255A具体的驱动程序主要包括以下代码及函数。
(1)管脚定义及函数声明。
管脚定义是指端口A、端口B、端口C和控制字的地址说明以及状态标志位的定义;函数的声明包括端口A、端口B、端口C的读写函数和控制字以及C口配置函数,具体代码如下:
//------------------------函数声明,管脚定义--------------------------------- #include<reg52.h> #include<ABSACC.H> #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的当前输入输出状态 unsigned char const cfg_table[8]= { 0x80, //10000000b, c=out b=out a=out 0x90, //10010000b, c=out b=out a=in 0x82, //10000010b, c=out b=in a=out 0x92, //10010010b, c=out b=in a=in 0x89, //10001001b, c=in b=out a=out 0x99, //10011001b, c=in b=out a=in 0x8B, //10001011b, c=in b=in a=out 0x9B, //10011011b, c=in b=in a=in } unsigned char rd_PA(void); //读PA unsigned char rd_PB(void); //读PB unsigned char rd_PC(void); //读PC void wr_PA(unsigned char PA_data); //写PA void wr_PB(unsigned char PB_data); //写PB void wr_PC(unsigned char PC_data); //写PC void set_PC(unsigned char PC_num); //PC位操作,置位,PC_num为端口号0~7 void clr_PC(unsigned char PC_num); //PC位操作,复位,PC_num为端口号0~7 void PABC_config(void); //写8255A控制字(2)端口A、B、C读写函数。
端口A、B、C读写函数完成8255A端口A、B、C的数据读写,程序代码如下:
//----------------------------------------------------------------------- // 函数名称:rd_PA // 输入函数:无 // 输出参数:PA_data,PA输入的数据 // 功能说明:驱动PA实现输入功能,读入PA的并行数据 //----------------------------------------------------------------------- unsigned char rd_PA(void) //读PA { unsigned char PA_data; ACC=IO_flags; //把状态标志字读到ACC便于进行位操作 do { IO_flagsA=1; //置PA状态标志位为高--输入 IO_flags=ACC; PABC_config(); //调用配置子程序,完成对8255的设置 ACC=IO_flags; } while(IO_flagsA==0); //判断状态标志位是否为高 //控制字设置完成 PA_data=a8255_PA; //把PA的数据读到PA_data return(PA_data); //返回PA_data } //----------------------------------------------------------------------- // 函数名称:rd_PB // 输入函数:无 // 输出参数:PB_data,PB输入的数据 // 功能说明:驱动PB实现输入功能,读入PB的并行数据 //----------------------------------------------------------------------- unsigned char rd_PB(void) //读PB { unsigned char PB_data; ACC=IO_flags; //把状态标志字读到ACC便于进行位操作 do { IO_flagsB=1; //置PB状态标志位为高--输入 IO_flags=ACC; PABC_config(); //调用配置子程序,完成对8255的设置 } while(IO_flagsB==0); //判断状态标志位是否为高 //控制字设置完成 PB_data=a8255_PB; //把PB的数据读到PB_data return(PB_data); //返回PB_data } //----------------------------------------------------------------------- // 函数名称:rd_PC // 输入函数:无 // 输出参数:PC_data,PC输入的数据 // 功能说明:驱动PC实现输入功能,读入PC的并行数据 //----------------------------------------------------------------------- unsigned char rd_PC(void) //读PC { unsigned char PC_data; ACC=IO_flags; //把状态标志字读到ACC便于进行位操作 do { IO_flagsC=1; //置PC状态标志位为高--输入 IO_flags=ACC; PABC_config(); //调用配置子程序,完成对8255的设置 //ACC=IO_flags; } while(IO_flagsC==0); //判断状态标志位是否为高 //控制字设置完成 PC_data=a8255_PC; //把PC的数据读到PC_data return(PC_data); //返回PC_data } //----------------------------------------------------------------------- // 函数名称:wr_PA // 输入函数:PA_data,送PA输出的数据 // 输出参数:无 // 功能说明:驱动PA实现输出功能,输出数据到PA //----------------------------------------------------------------------- void wr_PA(unsigned char PA_data) //写PA { ACC=IO_flags; //把状态标志字读到ACC便于进行位操作 { IO_flagsA=0; //置PA状态标志位为低--输出 IO_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 PABC_config(); //调用配置子程序,完成对8255的设置 ACC=IO_flags; } while(IO_flagsA==1); //判断状态标志位是否为高, //为高,设置未完成,需从新设置 a8255_PA=PA_data; //将PA_data的内容送到PA } //----------------------------------------------------------------------- // 函数名称:wr_PB // 输入函数:PB_data,送PB输出的数据 // 输出参数:无 // 功能说明:驱动PB实现输出功能,输出数据到PA //----------------------------------------------------------------------- void wr_PB(unsigned char PB_data) //写PB { ACC=IO_flags; //把状态标志字读到ACC便于进行位操作 { IO_flagsB=0; //置PB状态标志位为低--输出 IO_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 PABC_config(); //调用配置子程序,完成对8255的设置 ACC=IO_flags; } while(IO_flagsB==1); //判断状态标志位是否为高,为高,设置未完成, //需从新设置 a8255_PB=PB_data; //将PB_data的内容送到PB } //----------------------------------------------------------------------- // 函数名称:wr_PC // 输入函数:PC_data,送PC输出的数据 // 输出参数:无 // 功能说明:驱动PC实现输出功能,输出数据到PC //----------------------------------------------------------------------- void wr_PC(unsigned char PC_data) //写PC { ACC=IO_flags; //把状态标志字读到ACC便于进行位操作 { IO_flagsC=0; //置PC状态标志位为低--输出 IO_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 PABC_config(); //调用配置子程序,完成对8255的设置 ACC=IO_flags; } while(IO_flagsC==1); //判断状态标志位是否为高, //为高,设置未完成,需从新设置 a8255_PC=PC_data; //将PC_data的内容送到PC }(3)端口C配置函数。
端口C配置函数可实现PC口具体某一位的输入/输出设置,程序代码如下:
//----------------------------------------------------------------------- // 函数名称:set_PC // 输入函数:PC_num,范围0~7 // 输出参数:无 // 功能说明:对PC进行位操作,置PC(PC_num)为高 //----------------------------------------------------------------------- void set_PC(unsigned char 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; } //----------------------------------------------------------------------- // 函数名称:clr_PC // 输入函数:PC_num,范围0~7 // 输出参数:无 // 功能说明:对PC进行位操作,清PC(PC_num)为低 //----------------------------------------------------------------------- void clr_PC(unsigned char 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; }(4)写控制字函数。
写控制字函数完成对控制字的写,从而实现对端口A、B、C口输入/输出的配置,程序
代码如下:
//----------------------------------------------------------------------- // 函数名称:PABC_config // 功能说明:写8255A的控制字寄存器 //----------------------------------------------------------------------- void PABC_config(void) { a8255_CON=cfg_table[IO_flags]; }8155是Intel公司生产的可编程多功能接口芯片。它的内部有两个可编程的8位并行I/O口、一个6位并行I/O口、一个14位定时/计数器以及256字节的RAM存储器。8155可以直接和MCS-51系列单片机连接,而不需增加硬件电路,它是单片机应用系统中最常用的芯片之一。8155的结构及引脚如图2-11所示。
8155有3个可编程并行I/O端口:端口A、端口B、端口C。其中,端口A和端口B是8位,端口C是6位;1个14位可编程定时/计数器和256B的静态RAM,能方便地进行I/O端口扩展和RAM扩展。
8155共有40个引脚,按其功能特点分类说明如下。
1.8155的工作方式及基本操作
8155可作为通用I/O端口,也可作为片外256B RAM及定时器使用,在各种不同类型下使用时的基本操作如下。
8155的I/O端口各种方式选择是通过对8155内部命令寄存器命令字来实现的。命令寄存器由8位锁存器组成,只能写入不能读出。命令字各位定义如表2-6所示。
8155的工作状态由状态寄存器指出,与命令字寄存器用同一个地址,只能读出不能写入。状态字的格式如表2-7所示。
端口操作如下。
端口A寄存器和端口B寄存器有完全相同的功能,可工作于基本I/O方式或选通I/O方式。端口C可工作于基本I/O方式,也可作为端口A、端口B选通方式工作时的状态控制信号线。当8155设定为方式1和方式2时,端口A、端口B、端口C均工作于基本输入/输出方式,由“MOVX”类指令进行输入/输出操作。设定为方式3时,端口A定义为选通输入/输出,由端口C低3位作为端口A联络线,端口C其余位作为I/O端口线。设定为方式4,端口A、端口B均定义为选通输入/输出方式,由端口C作为端口A、端口B的联络线。逻辑组态如表2-8所示。
INTR为中断请求输出线,作为CPU的中断源,高电平有效。当8155的端口A或端口B缓冲器接收到设备输入的数据或设备从缓冲器中取走数据时,中断请求线INTR升高(仅当命令字寄存器相应中断允许位为1),向CPU请求中断,CPU对8155的相应I/O端口进行一次读/写操作后,INTR自动变为低电平。
BF为I/O端口缓冲器标志输出线,缓冲器存有数据时,BF为高电平,否则为低电平。为设备选通信号输入线,低电平有效。
在I/O端口设定为输出口时,仍可用对应的端口地址执行读操作,读取输出端口的内容;设定为输入端口时,输出锁存器被清除,无法将数据写入输出锁存器。所以每次通道由输入方式转为输出方式时,输出端总是低电平。8155复位时,清除所有输出寄存器,3个端口都为输入方式。
2.8155与单片机的接口电路
图2-12所示为8155与单片机接口电路。
根据图中连线图,假设A14~A9均为高电平,8155才工作,所以会有下述信息。
存储器地址:0x7F00~0x7FFF。命令/状态寄存器地址:0x7E00(共有32个地址对应,选期中一个有效地址)。端口A地址:0x7E01(共有32个地址对应,选期中一个有效地址)。端口B地址:0x7E02(共有32个地址对应,选期中一个有效地址)。端口C地址:0x7E03(共有32个地址对应,选期中一个有效地址)。定时器寄存器A地址:0x7E04(共有32个地址对应,选期中一个有效地址)。定时器寄存器B地址:0x7E05(共有32个地址对应,选期中一个有效地址)。3.8155驱动程序设计
8155驱动程序主要是涉及对端口PA、PB、PC、控制字以及定时器的设置,主要包括以下代码及函数。
(1)相关函数声明及管脚定义。
管脚定义主要是指端口PA、端口PB、端口PC、控制字以及定时器A、B和存储器首地
址和相关标志位的定义;函数的声明涉及存储器及端口PA、端口PB、端口PC的读写函数、中断的开关函数和定时器相关函数,具体代码如下。
//------------------------函数声明,管脚定义------------------------------*/ #include<reg52.h> #include<ABSACC.H> #define a8155_PA XBYTE[0x7E00] //控制字地址 #define a8155_PB XBYTE[0x7E01] //PA地址 #define a8155_PC XBYTE[0x7E02] //PB地址 #define a8155_CON XBYTE[0x7E03] // PC地址 #define Timer_A XBYTE[0x7E04] // 定时器寄存器A #define Timer_B XBYTE[0x7E05] // 定时器寄存器B #define mem_head XBYTE[0x7F00] // 存储器首地址 unsigned char bdata IO_flags; //用于表示PA、PB、PC的当前输入输出状态 //内容不能被其他程序改写 sbit IO_flagA=IO_flags^0; //PA的当前输入输出状态 sbit IO_flagB=IO_flags^1; //PB的当前输入输出状态 sbit IO_flagC=IO_flags^2; //PC的当前输入输出状态 sbit IO_flagC1=IO_flags^3; //PC的当前输入输出状态 sbit Int_flagA=state_flags^4; //PA的当前输入输出状态 sbit Int_flagB=state_flags^5; //PB的当前输入输出状态 sbit Timer_flag1=state_flags^6; sbit Timer_flag2=state_flags^7; //Timer 的状态置位表示计数中 unsigned char rd_mem(unsigned char mem_ad); //读存储器 void wr_mem(unsigned char mem_ad,unsigned char mem_data); //写存储器 char rd_PA(void); //读PA char rd_PB(void); //读PB char rd_PC(void); //读PC void wr_PA(unsigned char PA_data); //写PA void wr_PB(unsigned char PB_data); //写PB void wr_PC(unsigned char PC_data); //写PC void Dint_PA(void); //关端口A中断 void Eint_PA(void); //开端口A中断 void Dint_PB(void); //关端口B中断 void Eint_PB(void); //开端口B中断 void setting_PC0int(void); void setting_PC4int(void); void start_timer(void); //开始计数器计数 void stop_timer(void); //停止计数器计数 void setting_zero_stop(void); //设定计数到零停止计数 int rd_timer(void); //读计数值 void setting_timerout_mode(unsigned char mode); //设定输出模式(2)读写外RAM函数。
读写外RAM函数对外部存储器指定单元数据进行读写,程序代码如下。
//----------------------------------------------------------------------- // 函数名称:rd_mem // 输入函数:mem_ad,范围0~255 // 输出参数:mem_data,存储对应数据 // 功能说明:读外部RAM,输入相对地址,返回数据 //----------------------------------------------------------------------- unsigned char rd_mem(unsigned char mem_ad) //读存储器 { unsigned char mem_data; unsigned int AD_mem; AD_mem=&mem_head; AD_mem=AD_mem+mem_ad; mem_data=XBYTE[AD_mem]; return(mem_data); } //----------------------------------------------------------------------- // 函数名称:wr_mem // 输入函数:mem_ad,mem_data 相对地址和数据 // 输出参数:无 // 功能说明:写数据到外部RAM,把数据写到相应的地址 //----------------------------------------------------------------------- void wr_mem(unsigned char mem_ad, unsigned char mem_data) //写存储器 { unsigned int AD_mem; AD_mem=&mem_head; AD_mem=AD_mem+mem_ad; XBYTE[AD_mem]=mem_data; }(3)端口PA、端口PB以及端口PC的读写设置函数。
端口PA、端口PB以及端口PC的读写设置函数主要完成对8155端口的输入输出设置及
数据读写,程序代码如下。
//----------------------------------------------------------------------- // 函数名称:rd_PA // 输入函数:无 // 输出参数:PA_data // 功能说明:返回PA数据 //----------------------------------------------------------------------- char rd_PA(void) //读PA { unsigned char PA_data; ACC=state_flags; //把状态标志字读到ACC便于进行位操作 do { IO_flagA=0; //置PA状态标志位为低--输入 state_flags=ACC; a8155_CON=state_flags; //重写控制字,完成对8155的设置 } while(IO_flagA==1); //判断状态标志位是否为高 //控制字设置完成 PA_data=a8155_PA; //把PA的数据读到PA_data return(PA_data); //返回PA_data } //----------------------------------------------------------------------- // 读PB、PC的函数:rd_PB和rd_PC程序代码与rd_PA类似,不再赘述 //----------------------------------------------------------------------- // 函数名称:wr_PA // 输入函数:PA_data // 输出参数:无 // 功能说明:把PA_data送到PA输出 //----------------------------------------------------------------------- void wr_PA(unsigned char PA_data) //写PA { ACC=state_flags; //把状态标志字读到ACC便于进行位操作 { IO_flagA=1; //置PA状态标志位为高--输出 state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } while(IO_flagA==0); //判断状态标志位是否为低 //为低,设置未完成,需从新设置 a8155_PA=PA_data; //将PA_data的内容送到PA } //----------------------------------------------------------------------- // 写PB、PC的函数:wr_PB和wr_PC程序代码与wr_PA类似,不再赘述 //-----------------------------------------------------------------------(4)端口PA、端口PB以及端口PC的中断设置函数。
① 端口PA、端口PB以及端口PC的中断设置函数完成各个端口的中断开启和关断,程序代码如下。
// 函数名称:Eint_PA // 输入函数:无 // 输出参数:无 // 功能说明:PA中断允许 //----------------------------------------------------------------------- void Eint_PA(void) //开端口A中断 { ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Int_flagA=1; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } //----------------------------------------------------------------------- // 函数名称:Dint_PA // 输入函数:无 // 输出参数:无 // 功能说明:PA中断禁止 //----------------------------------------------------------------------- void Dint_PA(void) //关端口A中断 { ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Int_flagA=0; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } //----------------------------------------------------------------------- // 开关PB中断的函数Eint_PB、Dint_PB和Eint_PA、Dint_PA程序代码类似,不再赘述 //-----------------------------------------------------------------------② 端口PC上下半口配置函数可实现端口PC上半口配置为PA状态输出和PC下半口配置为PB状态输出。程序代码如下。
//----------------------------------------------------------------------- // 函数名称:PC0_PAint // 输入函数:无 // 输出参数:无 // 功能说明:设置PC上半口为PA状态输出,PC0=INTRa,PC1=BFa,PC2=/STBb //----------------------------------------------------------------------- void PC0_PAint(void) //PC上半口为PA状态输出 { //PC0=INTRa,PC1=BFa,PC2=/STBa ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Int_flagA=1; IO_flagC1=1; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } //----------------------------------------------------------------------- // 函数名称:PC4_PBint // 输入函数:无 // 输出参数:无 // 功能说明:设置PC下半口为PB状态输出,PC3=INTRb,PC4=BFb,PC5=/STBb //----------------------------------------------------------------------- void PC4_PBint(void) //PC下半口为PB状态输出 { //PC0=INTRa,PC1=BFa,PC2=/STBa ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Int_flagA=1; IO_flagC1=1; IO_flagC=1; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 }③ 计数器设置函数完成计数器的起停和读写和输出模式设置,具体程序代码如下。
//---------------------------------------------------------------------- // 函数名称:start_timer // 输入函数:无 // 输出参数:无 // 功能说明:开始计数器计数 //----------------------------------------------------------------------- void start_timer(void) //开始计数器计数 { ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Timer_flag1=1; Timer_flag2=1; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } //----------------------------------------------------------------------- // 函数名称:stop_timer // 输入函数:无 // 输出参数:无 // 功能说明:停止计数器计数 //----------------------------------------------------------------------- void stop_timer(void) //停止计数器计数 { ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Timer_flag1=1; Timer_flag2=0; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } //----------------------------------------------------------------------- // 函数名称:size_zero_stop // 输入函数:无 // 输出参数:无 // 功能说明:设定计数到零停止计数 //----------------------------------------------------------------------- void stop_timer(void) //停止计数器计数 { ACC=state_flags; //把状态标志字读到ACC便于进行位操作 Timer_flag1=1; Timer_flag2=0; state_flags=ACC; //位操作完成,把ACC的内容写回状态标志字 a8155_CON=state_flags; //写控制字,完成对8155的设置 } //----------------------------------------------------------------------- // 函数名称:rd_timer // 输入函数:无 // 输出参数:time // 功能说明:读计数值 //----------------------------------------------------------------------- int rd_timer(void) //读计数值 { int time; char timea; time=Timer_B; timea=Timer_A; time=time<<8; time=((time&timea)&0x3F); return(time); } //----------------------------------------------------------------------- // 函数名称:setting_timerout_mode // 输入函数:mode,范围0~3 // 输出参数:无 // 功能说明:设定 输出模式 //----------------------------------------------------------------------- void setting_timerout_mode(unsigned char mode) //设定输出模式 { Timer_B=(mode&0x03); //写控制字 }