第6章 通用IO接口基本结构与输出应用.docx
《第6章 通用IO接口基本结构与输出应用.docx》由会员分享,可在线阅读,更多相关《第6章 通用IO接口基本结构与输出应用.docx(48页珍藏版)》请在冰豆网上搜索。
第6章通用IO接口基本结构与输出应用
第6章通用I/O接口基本结构与输出应用
从本章开始,将从AVR单片机的基本功能单元入手,讲解其各个外围功能部件的基本组成和特性,以及它们的应用。
由于刚开始学习I/O的应用,读者还没有掌握中断和定时计数器的使用,所以在本章的实例中,调用了CVAVR提供的软件延时函数来实现时间延时等待的功能。
需要指出的是,使用软件延时的方式会造成MCU效率的下降,而且也不能实现精确的延时,所以在一般情况下应尽量不使用软件延时的方式。
在后面的章节里,会逐步介绍如何使用T/C和中断实现延时的正确方法。
ATmega16芯片有PORTA、PORTB、PORTC、PORTD(简称PA、PB、PC、PD)4组8位,共32路通用I/O接口,分别对应于芯片上32根I/O引脚。
所有这些I/O口都是双(有的为3)功能复用的。
其中第一功能均作为数字通用I/O接口使用,而复用功能则分别用于中断、时钟/计数器、USRAT、I2C和SPI串行通信、模拟比较、捕捉等应用。
这些I/O口同外围电路的有机组合,构成各式各样的单片机嵌入式系统的前向、后向通道接口,人机交互接口和数据通信接口,形成和实现了千变万化的应用。
6.1通用I/O口的基本结构与特性
6.1.1I/O口的基本结构
图6-1为AVR单片机通用I/O口的基本结构示意图。
从图中可以看出,每组I/O口配备三个8位寄存器,它们分别是方向控制寄存器DDRx,数据寄存器PORTx,和输入引脚寄存器PINx(x=A\B\C\D)。
I/O口的工作方式和表现特征由这3个I/O口寄存器控制。
图6-1通用I/O口结构示意图
方向控制寄存器DDRx用于控制I/O口的输入输出方向,即控制I/O口的工作方式为输出方式还是输入方式。
当DDRx=1时,I/O口处于输出工作方式。
此时数据寄存器PORTx中的数据通过一个推挽电路输出到外部引脚(图6-2)。
AVR的输出采用推挽电路提高了I/O口的输出能力,当PORTx=1时,I/O引脚呈现高电平,同时可提供输出20mA的电流;而当PORTx=0时,I/O引脚呈现低电平,同时可吸纳20mA电流。
因此,AVR的I/O在输出方式下提供了比较大的驱动能力,可以直接驱动LED等小功率外围器件。
当DDRx=0时,I/O处于输入工作方式。
此时引脚寄存器PINx中的数据就是外部引脚的实际电平,通过读I/O指令可将物理引脚的真实数据读入MCU。
此外,当I/O口定义为输入时(DDRx=0),通过PORTx的控制,可使用或不使用内部的上拉电阻(图6-3)。
图6-2通用I/O口输出工作方式示意图
图6-3通用I/O口输入工作方式示意图(带内部上拉)
表6.1是AVR通用I/O端口的引脚配置情况。
表6.1I/O口引脚配置表
DDRXn
PORTXn
PUD
I/O方式
内部上拉电阻
引脚状态说明
0
0
X
输入
无效
三态(高阻)
0
1
0
输入
有效
外部引脚拉低时输出电流(uA)
0
1
1
输入
无效
三态(高阻)
1
0
X
输出
无效
推挽0输出,吸收电流(20mA)
1
1
X
输出
无效
推挽1输出,输出电流(20mA)
表中的PUD为寄存器SFIOR中的一位,它的作用相当AVR全部I/O口内部上拉电阻的总开关。
当PUD=1时,AVR所有I/O内部上拉电阻都不起作用(全局内部上拉无效);而PUD=0时,各个I/O口内部上拉电阻取决于DDRXn的设置。
AVR通用I/O端口的主要特点为:
✓双向可独立位控的I/O口
ATmega16的PA、PB、PC、PD四个端口都是8位双向I/O口,每一位引脚都可以单独的进行定义,相互不受影响。
如用户可以在定义PA口第0、2、3、4、5、6位用于输入的同时定义第1、7位用于输出,互不影响。
✓Push-Pull大电流驱动(最大40mA)
每个I/O口输出方式均采用推挽式缓冲器输出,提供大电流的驱动,可以输出(吸入)20mA的电流,因而能直接驱动LED显示器。
✓可控制的引脚内部上拉电阻
每一位引脚内部都有独立的,可通过编程设置的,设定为上拉有效或无效的内部上拉电阻。
当I/O口被用于输入状态,且内部上拉电阻被激活(有效)时,如果外部引脚被拉低,则构成电流源输出电流(uA量级)。
✓DDRx可控的方向寄存器。
AVR的I/O端口结构同其它类型单片机的明显区别是,AVR采用3个寄存器来控制I/O端口。
一般单片机的I/O仅有数据寄存器和控制寄存器,而AVR还多了一个方向控制器,用于控制I/O的输入输出方向。
由于输入寄存器PINx实际不是一个寄存器,而是一个可选通的三态缓冲器,外部引脚通过该三态缓冲器与MCU的内部总线连接,因此,读PINx时是读取外部引脚上的真实和实际逻辑值,实现了外部信号的同步输入。
这种结构的I/O端口,具备了真正的读-修改-写(Read-Modify-Write)特性。
图6-4通用I/O口逻辑功能示意图
图6-4为AVR一个(位)通用I/O口的逻辑功能图。
右上面的两个D触发器为方向控制寄存器和数据寄存器。
1)使用AVR的I/O口,首先要正确设置其工作方式,确定其工作在输出方式还是输入方式。
2)当I/O工作在输入方式,要读取外部引脚上的电平时,应读取PINxn的值,而不是PORTxn的值。
3)当I/O工作在输入方式,要根据实际情况使用或不使用内部的上拉电阻。
4)一旦将I/O口的工作方式由输出设置成输入方式后,必须等待一个时钟周期后才能正确的读到外部引脚PINxn的值。
上面的第4点是由于在PINxn和AVR内部数据总线之间有一个同步锁存器(图6-4中的SYNCHRONIZER)电路,使用该电路避免了当系统时钟变化的短时间内外部引脚电平也同时变化而造成的信号不稳定的现象,但它有产生大约一个时钟周期(0.5~1.5)的时延。
6.1.2I/O端口寄存器
ATmega16的4个8位的端口都有各自对应的3个I/O端口寄存器,它们占用了I/O空间的12个地址(见表6.2)。
表6.2ATmega16I/O寄存器地址表
名称
I/O空间地址
RAM空间地址
作用
PORTA
$1B
0x003B
A口数据寄存器
DDRA
$1A
Ox003A
A口方向寄存器
PINA
$19
0x0039
A口输入引脚寄存器
PORTB
$18
0x0038
B口数据寄存器
DDRB
$17
Ox0037
B口方向寄存器
PINB
$16
0x0036
B口输入引脚寄存器
PORTC
$15
0x0035
C口数据寄存器
DDRC
$14
Ox0034
C口方向寄存器
PINC
$13
0x0033
C口输入引脚寄存器
PORTD
$12
0x0032
D口数据寄存器
DDRD
$11
Ox0031
D口方向寄存器
PIND
$10
0x0030
D口输入引脚寄存器
下面是PA口寄存器—PORTA、DDRA、PINA各个位的具体定义,以及其是否可以通过指令读写操作和RESET复位后的初始值。
其它3个口的寄存器的情况与PA口相同,只是地址不一样。
1)正确使用AVR的I/O口要注意:
先正确设置DDRx方向寄存器,再进行I/O口的读写操作。
2)AVR的I/O口复位后的初始状态全部为输入工作方式,内部上拉电阻无效。
所以,外部引脚呈现三态高阻输入状态。
3)因此,用户程序需要首先对要使用的I/O口进行初始化设置,根据实际需要设定使用I/O口的工作方式(输出还是输入),当设定为输入方式时,还要考虑是否使用内部的上拉电阻。
4)在硬件电路设计时,如能利用AVR内部I/O口的上拉电阻,可以节省外部的上拉电阻。
6.1.3通用数字I/O口的设置与编程
在将AVR的I/O口作为通用数字口使用时,要先根据系统的硬件设计情况,设定各个I/O口的工作方式:
输入或输出工作方式,既先正确设置DDRx方向寄存器,再进行I/O口的读写操作。
如将I/O口定义为数字输入口时,还应注意是否需要将该口内部的上拉电阻设置为有效,在设计电路时,如能利用AVR内部I/O口的上拉电阻,可以节省外部的上拉电阻。
AVR汇编指令系统中,直接用于对I/O寄存器的操作指令有以下3类,全部为单周期指令:
1)IN/OUT
IN/OUT指令实现了32个通用寄存器与I/O寄存器之间的数据交换,格式为:
INRd,A;从I/O寄存器A读数剧到通用寄存器Rd
OUTA,Rr;通用寄存器Rr数据送I/O寄存器A
2)SBI/CBI
SBI/CBI指令实现了对I/O寄存器(地址空间为I/O空间的0x00-0x31)中指定位的置1或清0,格式为:
SBIA,b;将I/O寄存器A的第b位置1
CBIA,b;将I/O寄存器A的第b位清0
3)SBIC/SBIS
SBIC/SBIS指令为转移类指令,它根据I/O寄存器(地址空间为I/O空间的0x00-0x31)的指定位的数值实现跳行转移(跳过后面紧接的一条指令,执行后序的第二条指令),格式为:
SBICA,b;I/O寄存器A的第b位为0时,跳行执行
SBISA,b;I/O寄存器A的第b位为1时,跳行执行
ATmega16的4个8位的端口共有12个I/O端口寄存器,它们在AVR的I/O空间的地址均在前32个之中,因此上面3类对I/O寄存器操作的指令都可以使用。
在第5章的例程Demo_5_1.asm中,使用了OUT指令设置PC口的工作方式为输出,输出全1:
.deftemp1=r20;定义寄存器R20用临时变量名temp1代表
。
。
。
。
。
。
。
。
。
sertemp1;置temp1(R20)为0XFF
outddrc,temp1;定义PC口为输出
outportc,temp1;PC口输出全“1”,LED不亮
在CVAVR中,我们可以直接使用C的语句对I/O口寄存器进行操作,如:
//定义PortC口的工作方式
PORTC=0x01;//PC口的第0位输出“1”,LED不亮
DDRC=0x01;//定义PC口的第0位为输出方式
PORTC.0=~PORTC.0;//PC口第0位输出取反
其中PORTC.0=0(或PORTC.0=1)是CVAVR中对C的扩展语句,它实现了对寄存器的位操作。
这种语句在标准C中是没有的,该扩展更加适合编写单片机的系统程序,因为在单片机的系统程序中,是经常需要直接对位进行操作的。
更加标准的C程序可以采用以下的写法:
#define BIT00
#define BIT11
#define BIT22
#define BIT33
#define BIT44
#define BIT55
#define BIT66
#defineBIT77
………
PORTC=1<<(BIT0)|1<<(BIT3);//PC口的第0位和第3位输出“1”,其它为“0”
这里,1<<(BIT0)表示逻辑1左移0位,结果为0b00000001;而1<<(BIT3)表示逻辑1左移3位,结果为0b00001000。
0b00000001在同0b00001000相与,结果为0b00001001。
以上的逻辑运算不产生具体的操作指令,是由CVAVR在编译时运算完成,得到结果,最后只是产生将结果赋值到PORTC寄存器的操作指令。
这种表示方式,比直接赋值0b00001001更容易理解程序的作用,如在下面的有关AVR的USART串口的程序中大量使用了这样的描述方式。
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<#define PARITY_ERROR (1<#define DATA_OVERRUN (1<#define DATA_REGISTER_EMPTY (1<#define RX_COMPLETE (1<………
charstatus;
status=UCSRA;
if ((status&(FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{……}//接收数据无错误处理过程
else
{……}//接收数据产生错误处理过程
程序中的UCSRA为ATmega16的串行接口USART的状态寄存器,UPE是UCSRA的第2位,当UPE为1时表示接收到的数据产生了校验错误。
程序中采用了定义语句,定义PARITY_ERROR为(1<因此一旦USART的值为PARITY_ERROR时,表示接受的数据产生了校验错误,使程序的阅读非常明了。
这样的程序编写方式,在AVR的汇编中也是可以使用的。
6.2通用I/O口的输出应用
6.2.1通用I/O输出设计要点
将通用I/O口定义为输出工作方式,通过设置该口的数据寄存器PORTx,就可以控制对应I/O口外围引脚的输出逻辑电平,输出“0”或“1”。
这样我们就可以通过程序来控制I/O口,输出各种类型的逻辑信号,如方波脉冲,或控制外围电路执行各种动作。
在应用I/O口输出时,在系统的软硬件设计上应注意的问题有:
✓输出电平的转换和匹配。
如一般AVR系统的工作电源为5伏(手持系统往往采用1.5v-3v电源),所以I/O的输出电平为5v。
当连接的外围器件和电路采用3v、9v、12v、15v等与5v不同的电源时,应考虑输出电平转换电路。
✓输出电流的驱动能力。
AVR的I/O口输出为“1”时,可以提供20mA左右的驱动电流。
输出为“0”时,可以吸收20mA左右的灌电流(最大为40mA)。
当连接的外围器件和电路需要大电流驱动或有大电流灌入时,应考虑使用功率驱动电路。
✓输出电平转换的延时。
AVR是一款高速单片机,当系统时钟为4M时,执行一条指令的时间为0.25us,这意味着将一个I/O引脚置“1”,再置“0”仅需要0.25us,既输出一个脉宽为0.25us高电平脉冲。
在一些应用中,往往需要较长时间的高电平脉冲驱动,如步进马达的驱动,动态LED数码显示器的扫描驱动等,因此在软件设计中要考虑转换时间延时。
对于不需要精确延时的应用,可采用软件延时的方法,编写软件延时的子程序。
如果要求精确延时,要使用AVR内部的定时器。
6.2.2LED发光二极管的控制
LED发光二极管是一种经常使用的外围器件,用于显示系统的工作状态,报警提示等,用大量的发光二极管组成方阵,就是构成一个LED电子显示屏,可以显示汉字和各种图形,如体育场馆中的大型显示屏。
下面设计一个带有一排8个发光二极管的简易彩灯控制系统。
例6.1简易彩灯控制系统
1)硬件电路设计:
发光二极管一般为砷化镓半导体二极管,其电路图6-5所示。
当电压U1大于U2约1V以上时,二极管导通发光。
当导通电流大于5mA时,人的眼睛就可以明显地观察到二极管的
图6-5LED电路
发光,导通电流越大,亮度越高。
一般导通电流不要超过10mA,否则将导致二极管的烧毁或I/O引脚的烧毁。
因此在设计硬件电路时,要在LED二极管电路中串接一个限流电阻,阻值在300~1000Ω之间,调节阻值的大小可以控制发光二极管的发光亮度。
导通电流与限流电阻之间的关系由下面的计算公式确定:
式中,Vled为LED的导通电压。
由于AVR的I/O口输出“0”时,可以吸收最大40mA的电流,因此采用控制发光二极管负极的设计比较好。
8个LED发光二极管控制系统的硬件电路见图6-6。
图6-68路LED发光二极管控制电路
在图6-6中,ATmega16的PA口工作在输出方式下,8个引脚分别控制8个发光二极管。
当I/O口输出“0”时LED导通发光,输出“1”时LED截止熄灭。
2)软件设计
下面给出一个简单的控制程序,其完成的功能是8个LED逐一循环发光1秒,构成“走马灯”。
程序非常简单,请读者自己分析。
/*********************************************
filename:
demo_6_1.c
Chiptype:
ATmega16
Programtype:
Application
Clockfrequency:
4.000000MHz
Memorymodel:
Small
ExternalSRAMsize:
0
DataStacksize:
256
*********************************************/
#include
#include
voidmain(void)
{
charposition=0;//position为控制位的位置
PORTA=0xFF;//PA口输出全1,LED全灭
DDRA=0xFF;//PA口工作为输出方式
while
(1)
{
PORTA=~(1<if(++position>=8)position=0;
delay_ms(1000);
};
}
3)思考与实践
✓调整程序中的delay_ms(),延时时间为1ms,彩灯闪亮有何变化?
为什么?
✓计算并验证当延时时间小于多少毫秒时,“走马灯”的效果变成“全亮”?
给出计算方法。
✓
设计一个4种闪烁方式交替循环的彩灯,闪烁方式见图6-7。
图6-74种不同控制方式的转换
提示:
在CVAVR中,提供intrand(void)和voidsrand(intseed)函数,请参考CVAVR手册,尝试使用这两个函数。
6.2.3继电器控制
在工业控制以及许多场合中,嵌入式系统要驱动一些继电器和电磁开关,用于控制马达的开启和关闭,阀门的开启和关闭等。
继电器和电磁开关需要功率驱动,驱动电流往往需要几百毫安,超出了AVR本身I/O口的驱动能力,因此在外围硬件电路中要考虑使用功率驱动电路。
例6.2控制恒温箱的加热的硬件电路设
图6-8继电器控制电路
恒温箱的加热源采用500W电炉,电炉的工作电压220v,电流2.3A。
选用HG4200继电器,开关负载能力为5A/AC220V,继电器吸合线圈的工作电压5v,功耗0.36W,计算得吸合电流为0.36/5=72mA。
因此,要能使继电器稳定的吸合,驱动电流应该大于80mA。
该电流已经超出AVR本身I/O口的驱动能力,因此外部需要使用功率驱动元件。
设计控制电路如图6-8所示,I/O引脚输出“1”时,三极管导通,继电器吸合,电炉开始加热。
I/O引脚输出“0”时,三极管截止,继电器释放,加热停止。
图中的三极管应采用中功率管,导通电流大于300mA。
电阻R1的作用是限制从I/O流出的电流太大,保护I/O端口,称为限流电阻。
注意:
三极管集电极的负载继电器吸合线圈在三极管截止时会产生一个很高的反峰电压,在吸合线圈两端并接一个二极管D,其用途是释放反峰电压,保护三极管和I/O口不会被反峰电压击穿,提高系统的可靠性。
吸合线圈两端并接的电容C,能对继电器动作时产生的尖峰电压变化进行有效的过滤,其作用也是为了提高系统的可靠性。
在设计PCB板时,二极管D和电容C应该仅靠在继电器的附近。
设计中还要考虑系统在上电时的状态。
由于AVR在上电时,DDRx和PORTx的值均初始化为“0”,I/O引脚呈高阻输入方式,因此电阻R2的作用是确保三极管的基极电位在上电时为“0”电平,三极管截止,保证了加热电炉控制系统上电时不会误动作。
在工业控制中,尤其应认真考虑系统上电初始化时以及发生故障时I/O口的状态,应在硬件和软件设计中仔细考虑,否则会产生误动作,造成严重的事故!
在驱动电感性负载时,在硬件上要考虑采取对反峰电压的吸收和隔离,防止对控制系统的干扰和破坏。
6.2.4步进电机控制
步进电机在自动仪表、自动控制、机器人、自动生产流水线等领域的应用相当广泛,如在打印机、磁盘驱动器、扫描仪中都有步进电机的身影。
关于步进电机工作原理请参考有关资料,本节介绍一种普通微型单极3相步进电机的控制。
单极3相步进电机有三个磁激励相,分别用A、B、C表示,每相有一个磁激线圈。
通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速,图6-9是单极3相步进电机的原理图。
单极3相步进电机有3相3拍和3相6拍两种驱动方式,图6-10给出它们的控制时序图。
3相3拍就是A、B、C三相分别通电,正转为A-B-C-A-B-C,反转为A-C-B-A-C-B,每拍转动3°。
3相6拍中有三拍是两相同时通电,正转为A-AB-B-BC-C-CA,反转为A-AC-C-CB-B-BA,每拍转动1.5°。
例6.3单极3相步进电机控制系统
1)硬件电路设计:
本例使用的3相步进电机,型号为45BC340C,步距角1.5°/3°,相电压12vDC,相电流0.4A,空载启动频率500Hz,控制硬件电路原理图见图6-11。
图中采用一片7位达林顿驱动芯片MC1413(Darlingtontransistorarrays),其驱动电流为0.5A,工作电压达50v。
当I/OA输出高电平“1”时,MC1413内部对应Q0的达林顿管导通,电流从电源正极(+12V)流过步进电机A相线圈,经O0端流入地线;输出低电平“0”时,MC1413内部对应O0的达林顿管截止,A相线圈中无电流流过。
电阻R1-R3为限流保护电阻。
系统上电时,AVR的I/O引脚为高阻,电阻R4-R6将MC1413的3个控制输入端拉低,以保证步进电机在上电时不会产生误动作。
图6-11步进电机控制电路
2)软件设计
/*********************************************
filename:
demo_6_3.c
Chiptype:
ATmega16
Programtype:
Application
Clockfrequency:
4.000000MHz
Memorymodel:
Small
ExternalSRAMsize:
0
DataStacksize:
256
*********************************************/
#include
#include
flashcharstep_out[6]={0x04,0x06,0x02,0x03,0x01,0x05};
voidmain(void)
{
chari=0;
intdelay=500;
PORTA=0x00;
DDRA=0x07;
while
(1)
{
PORTA=step_out[i];
if(++i>=6)i=0;