首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

AVR单片机IO口结构分析(2)

AVR单片机IO口结构分析(2)

AVR IO具备多种IO模式:
1 高阻态 ,多用于高阻模拟信号输入,例如ADC数模转换器输入,模拟比较器输入
2 弱上拉状态(Rup=20K~50K),输入用。为低电平信号输入作了优化,省去外部上拉电阻,例如按键输入,低电平中断触发信号输入
3 推挽强输出状态,驱动能力特强(>20mA),可直接推动LED,而且高低驱动能力对称.
使用注意事项:
写用PORTx,读取用PINx
实验时,尽量不要把管脚直接接到GND/VCC,当设定不当,IO口将会输出/灌入 80mA(Vcc=5V)的大电流,导致器件损坏。
作输入时:
1、通常要使能内部上拉电阻,悬空(高阻态)将会很容易受干扰。(表面看好像是51的抗干扰能力强,是因为51永远有内部电阻上拉,)
2、尽量不要让输入悬空或模拟输入电平接近VCC/2,将会消耗太多的电流,特别是低功耗应用场合------CMOS电路的特点
3、如果先前I/O口为输出状态,设置为输入状态后,必须等待1个时钟周期后才能正确的读到外部引脚PINx的值。
4、功能模块(中断,定时器)的输入可以是低电平触发,也可以是上升沿触发或下降沿触发。
5、用于高阻模拟信号输入,切记不要使能内部上拉电阻,影响精确度。例如ADC数模转换器输入,模拟比较器输入      
作输出时:
采用必要的限流措施,例如驱动LED要串入限流电阻
复位时:
复位时内部上拉电阻将被禁用。如果应用中(例如电机控制)需要严格的电平控制,请使用外接电阻固定电平。
休眠时:
作输出的,依然维持状态不变
作输入的,一般无效,但如果使能了第二功能(中断使能),其输入功能有效。例如 外部中断的唤醒功能。AVR
的C语言IO操作:
AVR的C语言基于ANSI C,没有像51那样扩展了位操作(布尔操作),虽然汇编指令里面有SBI/CBI/SBIC/SBIS指令,        所以需要采用 位逻辑运算 来实现,这是必须要掌握的。
IO口和功能寄存器的操作方法一样,但对于部分功能寄存器的读写有特殊要求,请参看手册。
不必考虑代码效率的问题,如果可能,GCCAVR会自动优化为SBI/CBI/SBIC/SBIS指令,跟汇编的效率是一样的。
例如 iom16.h 里面定义了 #define PA7 7
  (这标准头文件定义了MCU的所有官方定义(包括寄存器,位,中断入口等),但管脚的第二功能没有定义)
想PA7为1           PORTA|=(1<<PA7);           
想PA7为0           PORTA&=~(1<<PA7);
想PA7取反          PORTA^=(1<<PA7);
想检测PA7是否为1    if(PINA&(1<<PA7)) { };
想检测PA7是否为0    if!(PINA&(1<<PA7)) { };
*   << 为左移运算符,不懂的就要好好复习C语言基础了。
注意IO操作的顺序:
  //上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
假设PA口驱动LED的负极,低电平灯亮
初始化方法1:
      PORTA=0xFF;    //内部上拉,高电平
      DDRA=0xFF;     //输出高电平---------灯一直是灭的
初始化方法2:
      DDRA=0xFF;     //输出低电平--------灯被错误点亮了
      PORTA=0xFF;    //输出高电平--------马上被熄灭了,时间很短(1个指令不到uS时间),灯闪了一下,眼睛无法察觉
但要是这个IO口是控制炸药包的点火信号呢?工控场合要考虑可靠性的问题     
模拟OC结构的IIC总线的技巧:
虽然AVR大多带有硬件IIC接口,但也有需要使用软件模拟IIC的情况
可以通过使用外部上拉电阻+控制DDRx的方法来实现OC结构的IIC总线。
AVR单片机I/O口结构分析
IIC的速度跟上拉电阻有关,内部的上拉电阻阻值较大(Rup=20K~50K),只能用于低速的场合

          #defineSDA     0    //PC0
          #defineSCL     1    //PC1
          (程序初始化设定 SDA和SCL都是 PORT=0,DDR=0)
          #defineSDA_0()   DDRA|=(1<<SDA)    //输出低电平
          #defineSDA_1()   DDRA&=~(1<<SDA)   //输入,外部电阻上拉为高电平
          #defineSCL_0()   DDRA|=(1<<SCL)    //输出低电平
          #defineSCL_1()   DDRA&=~(1<<SCL)   //输入,外部电阻上拉为高电平
       使用上面的SDA_0()/SDA_1()/SCL_0()/SCL_1()宏即可,直观,而且效率跟汇编是一样的
继承事业,薪火相传
返回列表