2.4 通用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寄存器之间的数据交换,格式为:
IN Rd,A;从I/O寄存器A读取数据到通用寄存器Rd
OUT A,Rr;将通用寄存器Rr数据送至I/O寄存器A
(2)SBI/CBI SBI/CBI指令实现了对I/O寄存器(地址空间为I/O空间的0x00~0x31)中指定位的置1或清0,格式为:
SBI A,b;将I/O寄存器A的第b位置1
CBI A,b;将I/O寄存器A的第b位清0
(3)SBIC/SBIS SBIC/SBIS指令为转移类指令,它根据I/O寄存器(地址空间为I/O空间的0x00~0x31)的指定位的数值实现跳行转移(跳过后面紧接的一条指令,执行后序的第二条指令),格式为:
SBIC A,b;I/O寄存器A的第b位为0时,跳行执行
SBIS A,b;I/O寄存器A的第b位为1时,跳行执行
ATmega128的4个8位的端口共有12个I/O端口寄存器,它们在AVR的I/O空间的地址均在前32个之中,因此,上面3类对I/O寄存器操作的指令都可以使用。
在ICCAVR中,可以直接使用C语句对I/O寄存器进行操作,如:
①PA口配置为输出。
DDRA=0xFF; PORTA=0x55; //输出值为0x55
②PA口配置为不带上拉输入。
DDRA=0x00; PORTA=0xFF; i=PINA;
③PA口配置为带上拉输入。
DDRA=0x00; PORTA=0xFF; i=PINA;
④BIT(x)定义为1<<(x),就是将1左移x位。
BIT(0)=0 0 0 0 0 0 0 1//将1左移0位 BIT(3)=0 0 0 0 1 0 0 0//将1左移3位 ~BIT(3)=1 1 1 1 0 1 1 1//将1左移3位后取反
⑤将PB0定义为输出,且输出为高电平。
DDRB=BIT (0); //定义PB0为输出 PORTB|=BIT (0);//PB0输出高电平
⑥将PB0、PB1定义为输出,PB0、PB1均为高电平。
DDRB|=BIT (0)|BIT(1); //定义PB0、PB1为输出 PORTB|=BIT (0)|BIT(1); //PB0、PB1输出高电平
⑦将PB0数据寄存器的数值翻转,即如果是1则变成0,如果是0则变成1。
PORTB∧=BIT(0);//翻转PB0口
⑧将PB0、PB1数据寄存器的数值翻转,即如果是1则变成0,如果是0则变成1。
PORTB∧=BIT(0)|BIT(1); //翻转PB0、PB1口
⑨将PB2、PB3定义为输入,不带上拉电阻。
DDRB&=~(BIT(2)|BIT(3));//定义PB2、PB3为输入 PORTB&=~(BIT(2)|BIT(3));//将PORT置0,不带上拉电阻
⑩将PB2、PB3定义为输入,带上拉电阻。不引用引脚时,默认值为高电平。
SFIOR&=~BIT(PUD); //SFIOR寄存器的上拉电阻控制位PUD置0,在整个代码 中,这句话可 //以不出现,或仅出现一次即可,因为它是一个控制全部上 拉电阻的控制位 DDRB&=~(BIT(2)|BIT(3)); //定义PB2、PB3为输入 PORTB|=BIT(2)|BIT(3); //将PORT置1,满足上拉电阻的另一个条件 DDRB=BIT(0)|BIT(1)与DDRB|=|BIT(0)|BIT(1)的区别 在执行上面两句指令前,DDRB的状态为:10000000。 执行DDRB=BIT(0)|BIT(1),DDRB的状态变为:00000011。 执行DDRD|=BIT(0)|BIT(1),DDRB的状态变为:10000011。
前一句会先清空以前的所有状态,后一句保留前面的状态,在实际应用中,后一句更常用。
将PB口第三位置1的方法总结如下:
DDRB|=BIT(3); DDRB|=1<<3; DDRB|=0x08; DDRB|=0b00001000;