2.1 ATmega128单片机的I/O端口
在ATmega128单片机中,提供了53个可编程的I/O端口,分别为PA~PG口。当用SBI或CBI指令改变某个I/O引脚的输出/输入方向,改变引脚的输出电平或在禁止/允许引脚的内部上拉电阻时,其他引脚的状态不会被改变。同时它可以输出或吸收大电流,直接驱动LED显示器。
2.1.1 ATmega128单片机I/O端口的基本结构
AVR的所有I/O端口都具有与电压无关的上拉电阻,当上拉电阻被激活且引脚被拉低时该引脚会输出电流,如图2-1所示。
图2-1 I/O引脚等效原理图
PA~PG口都对应三个I/O寄存器位,它们分别为POPTxn、DDxn以及PINxn。其中POPTxn位于数据寄存器PORTx中,DDxn位于数据方向控制寄存器DDRx中,PINxn位于端口输入引脚寄存器PINx中,x为n端口的序号。数据寄存器和数据方向控制寄存器为读/写寄存器,而端口输入引脚寄存器为只读寄存器。如图2-2所示为I/O端口引脚的说明。
图2-2 I/O端口引脚图
寄存器SFIOR的上位禁止位PUD相当于I/O端口上拉电阻的总开关。当上拉禁止位PUD置位时,所有上拉电阻均失效,当其为0时,各个上拉电阻的阻值取决于DDxn的设置。
(1)数据方向控制寄存器DDRx 数据方向控制寄存器用来控制I/O端口的输入输出方向,当DDxn为“1”时,I/O端口处于输出工作状态,此时数据寄存器中的数据可输出到外部引脚,当DDxn为“0”时,I/O端口处于输入工作状态,此时端口输入引脚寄存器中的数据就是外部引脚的实际电平。
(2)数据寄存器PORTx 当I/O端口工作于输入方式时,如果PORTxn为“1”,上拉电阻将使能。通过将PORTxn清零或将该引脚配置为输出两种方式可不使用内部的上拉电阻。
当I/O端口工作于输出方式时,如果设置POTxn为“1”,端口引脚被驱动为高电平,此时可输出20mA的电流。如果将POTxn清零,端口引脚被拉低,此时可吸收20mA的电流(输出低电平)。
(3)端口输入引脚寄存器PINx 当DDxn为“1”时,对应的Pxn为输出引脚,当DDxn为“0”时,对应的Pxn为输入引脚。如表2-1所示为AVR通用I/O口的引脚配置情况。
表2-1 端口引脚配置表
不论将方向寄存器DDxn配置为何种状态,都可以通过读PINxn寄存器来获得外部引脚的当前电平。如图2-2所示,PINxn寄存器的各个位与锁存器组成了一个同步锁存电路。这样做的优点是可以避免当外部引脚电平的改变出现在系统时钟边缘产生一个不稳定的值。而其缺点就是形成了一个锁存延迟。
如图2-3所示为读取引脚电平时的同步锁存时序图。最大和最小传输延迟分别用tpd.max和tpd.min来表示。
图2-3 读取引脚电平时的同步锁存时序图
第一个系统时钟下降沿开始进行同步锁存,当时钟信号为低时锁存器是关闭的,而时钟信号为高时锁存器导通,如图2-4所示为读取软件赋予的引脚电平的同步锁存时序图。
图2-4 读取软件赋予的引脚电平的同步锁存时序图
当时钟信号为低,即锁存器关闭时,外部引脚的值被锁存在锁存器之中,在紧接着的系统时钟上升沿处再锁存到PINx寄存器中。
如图2-3中tpd.max和tpd.min所示,引脚上的信号转换最后被锁存在PINx中,且延迟介于1/2~3/2个系统时钟。
如果要读取软件赋予的引脚电平,在输出指令out和输入指令in之间需要插入一条NOP指令,如图2-4所示。输出指令out在时钟的上升沿将同步锁存信号SYNC-LATCH置位,可将外部引脚实际电平锁存,在紧接着的系统时钟上升沿处再锁存到PINx中,此时同步器的延迟时间tpd为一个系统时钟。
下面分别通过汇编程序和C程序来说明如何置位端口B的引脚0和1,清零引脚2和3,并且配置4~7号引脚为输入引脚,并且为引脚6和7设置上拉电阻,然后回读设置的引脚电平值。如前面讨论的那样,在输入和输出语句之间插入了一个NOP指令,使得能够正确地回读那些设定好的引脚值。
(1)汇编代码例程
…… ;定义上拉电阻和设置高电平输出 ;为端口引脚定义方向 ldi r16,(1< < PB7)|(1< < PB6)|(1< < PB1)|(1< < PB0) ldi r17,(1< < DDB3)|(1< < DDB2)|(1< < DBB1)|(1< < DBB0) out PORTB,r16 out DDRB,r17 ;为了同步插入 nop指令 Nop ;读取端口引脚 In r16,PINB ……
(2)C代码例程
Unsigned char i; …… /* 定义上拉电阻和设置高电平输出* / /* 为端口引脚定义方向* / PORTB= (1< < PB7)|(1< < PB6)|(1< < PB1)|(1< < PB0) DDRB= (1< < DDB3)|(1< < DDB2)|(1< < DBB1)|(1< < DBB0) /* 为了同步插入 nop指令* / _Nop(); /* 读取端口引脚* / i= PINB; ……
2.1.2 数字输入使能和睡眠模式
当引脚作为数字I/O口时,在施密特触发器的前端,数字输入信号可以钳位到地。当MCU处于各种睡眠模式时,SLEEP信号将被置位,将触发器的前端钳位到地,以防止在输入悬空或模拟输入电平接近VCC/2时消耗过多的电流。
当引脚作为外部中断输入时,SLEEP信号会跳过这些引脚。若外部中断源没有被使能,SLEEP信号对这些引脚仍然起作用。在使能引脚的第二功能时SLEEP也让位于第二功能。
如果异步外部中断引脚被设置为“任意逻辑电平变化均可引发中断”状态,即使外部中断没有使能,当该引脚被置位时,MCU从睡眠唤醒时相应的外部中断标志将置位。这是由于睡眠时在SLEEP信号的作用下,内部信号被钳位到地,而唤醒后外部高电平输入到内部逻辑,产生了低电平到高电平的信号变化。
2.1.3 I/O端口的第二功能
除了作为一般的数字I/O之外,大多数端口引脚都具有第二功能。如图2-5所示说明了简化出来的端口引脚控制信号是如何被第二功能所屏蔽的。这些被屏蔽的信号被转换用于第二功能,且不会出现在所有的端口引脚,本图要看作是适用于AVR系列处理器所有端口引脚的一般描述。
图2-5 I/O口第二功能控制逻辑电路
如表2-2所示列出了由第二功能模块内部产生的控制屏蔽信号的功能。
表2-2 第二功能模块控制屏蔽信号简述
2.1.4 I/O端口的特点
AVR的大部分I/O端口都具有双重功能,可分别与片内的各种不同功能的外围接口电路组合成一些可以完成特殊功能的I/O口,如定时器、计数器、串行接口、模拟比较器、捕捉器等。AVR通用I/O端口的主要特点如下:
(1)可自行定义输入输出工作方式 ATmega128的PA~PF都为8位双向I/O口,PG口为5位的双向I/O口,其每一位引脚都可以单独地进行定义,相互不受影响。例如,用户可以将PA口的第1、2、3、5、6位定义为输入,同时将第0、4、7位定义为输出。
(2)输出/吸收大电流 每个I/O口输出方式均采用推挽式缓冲器输出,提供大电流的驱动,可以输出(吸入)20mA的电流,因而能直接驱动LED。如果允许端口电平达到1V以上,电流最大可以达到40mA。
(3)内部上拉电阻可控性 每一位引脚内部都有内部上拉电阻,该电阻可通过编程设置其为上拉有效或无效。当I/O口处于输入工作方式时,可以三态输入,也可以带上拉电阻,这样就可以省去外电路的上拉电阻。
(4)DDRx可控的方向寄存器 在AVR单片机中,除了数据寄存器和控制寄存器外,还包括一个方向控制寄存器,由这3个寄存器共同来控制其I/O口。其中,方向控制寄存器用于控制I/O口的输入、输出方向。由于输入寄存器PINx实际上不是一个寄存器,而是一个可选的三态缓冲器,外部引脚通过该三态缓冲器与MCU的内部总线相连,因此,读PINx时是读取外部引脚上的实际逻辑值,实现了外部信号的同步输入,这种结构使I/O端口具备了真正的读-修改-写的特性。
2.1.5 I/O端口使用时的注意事项
使用I/O端口应注意以下事项:
①当要使用AVR的I/O口时,首先要定义I/O的方向,对方向寄存器的某位置1时工作于输出状态,清零时工作于输入状态。
②当I/O口工作于输入方式时,若需要上拉电阻,可将数据寄存器相应位置上1,这样可省去外部电流的上拉电阻。
③当I/O口工作于输入方式时,若要读取外部引脚上的电平,应该读取PINxn的值,而不是PORTAxn的值。
④当I/O口工作于输出方式时,上拉电阻已断开,对应数据寄存器相应位置1,推挽输出高电平;对应数据寄存器相应位清零,推挽输出低电平。
⑤如果将I/O口由输出状态设置成输入状态后,必须等待一个时钟周期后才能正确地读到外部引脚的值。