《51单片机应用开发范例大全(第3版)》——2.2 扩展芯片实现端口扩展

简介:

本节书摘来自异步社区《51单片机应用开发范例大全(第3版)》一书中的第2章,第2.2节,作者 张杰,宋戈,黄鹤松,员玉良,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.2 扩展芯片实现端口扩展

用串口扩展I/O口非常实用,但是串口是按位读取的,输入的数据必须重组后才能使用,速度受到限制,同时还需要严格的时钟配合。

在有些场合,利用串口扩展I/O口不是很理想,比如BCD码的输入及多组速率较高的并行数据的输入。所以,用并行数据端口扩展I/O口也是很有必要的。

2.2.1 【实例24】用8243扩展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引脚图,具体引脚说明如下。


screenshot

screenshot

PROG信号用于选择P2口的功能。在进行输入/输出时,先通过P2口传送选择端口及端口操作方式的控制命令,该命令由PROG的下跳沿所存至8243内部的指令寄存器和地址译码器,而进行的数据传送,由PROG的上跳沿将数据通过指定的端口输入/输出。P2传送命令时,由P2.1和P2.0指定端口地址,由P2.3和P2.2规定端口的工作方式,各位具体的定义如表2-1所示。


screenshot

表中的“或”、“与”方式是指分别把输出的数据与被寻址端口的内容进行“逻辑或”以及“逻辑与”运算后再写入该端口。

2.8243与单片机的接口设计

screenshot

以下是单片机串口驱动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);
}

2.2.2 【实例25】用8255A扩展I/O口

可编程并行I/O接口芯片8255A是Intel公司生产的标准外围接口电路。它采用NMOS工艺制造,用单一+5V电源供电,具有40条引脚,采用双列直插式封装。它有A、B、C共3个端口共24条I/O线,可以通过编程的方法来设定端口的各种I/O功能。由于它功能强,又能方便地与各种微机系统相连,而且在连接外部设备时,通常不需要再附加外部电路,所以得到了广泛的应用。

1.8255A的引脚介绍

8255A是一种有40个引脚的双列直插式标准芯片,其引脚如图2-9所示。除电源(+5V)和地址外,其他信号可以分为两组。


screenshot

与外设相连接的如下。

  • PA7~PA0:端口A数据线。
  • PB7~PB0:端口B数据线。
  • PC7~PC0:端口C数据线。

与CPU相连接的如下。

screenshot


screenshot

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所示。


screenshot

对工作方式控制字作如下说明。

  • 端口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置位/复位控制字。


screenshot

  • 在使用中,控制字每次只能对端口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与单片机的接口电路

screenshot

因为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];
}

2.2.3 【实例26】用8155扩展I/O口

8155是Intel公司生产的可编程多功能接口芯片。它的内部有两个可编程的8位并行I/O口、一个6位并行I/O口、一个14位定时/计数器以及256字节的RAM存储器。8155可以直接和MCS-51系列单片机连接,而不需增加硬件电路,它是单片机应用系统中最常用的芯片之一。8155的结构及引脚如图2-11所示。


screenshot

8155有3个可编程并行I/O端口:端口A、端口B、端口C。其中,端口A和端口B是8位,端口C是6位;1个14位可编程定时/计数器和256B的静态RAM,能方便地进行I/O端口扩展和RAM扩展。

8155共有40个引脚,按其功能特点分类说明如下。

screenshot


screenshot

1.8155的工作方式及基本操作

8155可作为通用I/O端口,也可作为片外256B RAM及定时器使用,在各种不同类型下使用时的基本操作如下。

screenshot

8155的I/O端口各种方式选择是通过对8155内部命令寄存器命令字来实现的。命令寄存器由8位锁存器组成,只能写入不能读出。命令字各位定义如表2-6所示。


screenshot

8155的工作状态由状态寄存器指出,与命令字寄存器用同一个地址,只能读出不能写入。状态字的格式如表2-7所示。


screenshot

端口操作如下。

  • 端口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所示。


screenshot

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与单片机接口电路。


screenshot

根据图中连线图,假设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);
    //写控制字
}
相关文章
|
1月前
|
传感器
单片机的输入输出端口
单片机的输入输出端口
68 2
高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
346 0
高通平台开发系列讲解(USB篇)USB端口的说明及切换方法
|
Python
pycharm开发flask指定ip、端口无效
pycharm开发flask指定ip、端口无效
514 0
pycharm开发flask指定ip、端口无效
|
网络协议 开发工具 Android开发
【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
280 0
【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )
|
Java 应用服务中间件 Android开发
tomcat开发远程调试端口以及利用eclipse进行远程调试
一、tomcat开发远程调试端口 方法1   WIN系统   在catalina.bat里:   SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.
1076 0