AVRA开发I/O与中断简介

 

AVR 通用I/O控制:以端口A为例

(1)首先对I/O口工作方式初始化,即根据需要正确设置DDRA寄存器,确定是输出方式还是输入方式。当DDRA=0xff时,A的每个端口都设置为输出方式,当DDRA=0x00时,A的每个端口都设置为输入方式。

(2)当I/O工作在输入方式时,要读取外部引脚时,应读取PINAn的值,而不是PORTAn的值。

注:DDRA是PA口的方向寄存器,在写DDRA时,就是在设定PA口的工作方式——输入口还是输出口。在读DDRA时则是在查询PA口的工作方式。

PORTA是PA口的数据寄存器,在写PORTA时,就是在控制PA的引脚数据。

PINA只允许读操作,从PINA口读入的数据反映A口引脚逻辑状态。

程序实例代码:

/************************************************************************

File name : led.c

Chip type : ATmega32

Program type : Application

AVR Core Clock frequency : 4.000000 Mhz

Memory model : Small

External RAM size : 0

Data Stack Size : 512

****************************************************************/

#include<mega32.h>                                   //不知道为什么错了?????????

#include<ioavr.h>                 //该文件是编译器自带的,这个头文件功能是根据所选择的芯片型号自动选择相应的寄存器地址定义头文件

void delay(unsigned int time);       //延时函数

void main()

{

  unsigned char position = 0;       //led点亮位置的控制

  /******初始化PORTA**********************/

  PORTA = 0xff;                     //初始化端口状态,全是1

  DDRA = 0xff;                      //A端口全部设置为输出状态

  /******流水灯点亮**********************/

  while(1)

  {

    PORTA = ~(1<<position);

    if(++position>=8)position=0;

    delay(1000);

  }

}

void delay(unsigned int time)

{

  for(;time>0;time--);

}

 

 

引脚配置为输入时,若PORTAn为“1”,则上拉电阻使能。如果需要关闭这个上拉电阻,则可以将PORTAn清零,或者将这个引脚配置为输出。复位时各引脚为高阻态。

引脚配置为输出时,若PORTAn为“1”,引脚输出高电平,若PORTAn为“0”,引脚输出低电平。

****************************************************************************************************************************************

****************************************************************************************************************************************

****************************************************************************************************************************************

****************************************************************************************************************************************

针对AVR的开发,在不同的软件开发环境之下,会有不同的一些开发规则,本人在IAR 下进行的开发,此下都是基于IAR开发环境的。

首先在头文件的使用时,一般使用#include<iomxx.h>其中xx表示型号,eg:使用ATmega32芯片,则头文件使用iom32.h。

下面主要说说中断的一些知识:

状态寄存器SREG:(I,T,H,S,V,N,Z,C),

I:全局中断使能位,当I为1时,开启全局中断,当I为0时,关闭所有中断。

T(位复制标志),H(半进位标志),S(符号标志),V(溢出标志),N(复数标志),Z(零标志),C(进位标志)。

控制寄存器MCUCR:(SE,SM2,SM1,SM0,ISC11,ISC10,ISC01,ISC00)

ISC11

ISC10

说明

0

0

INT1为低电平时产生中断请求

0

1

INT1引脚上任意的逻辑电平变化都将引发中断

1

0

INT1的下降沿产生异步中断请求

1

1

INT1的上升沿产生异步中断请求

如果是边沿触发或者电平变化触发,那么持续时间必须大于一个时钟周期,才能触发中断,时间不能过短,如果选择低电平触发,则低电平必须保持到当前指令的结束。

ISC01,ISC00是对INT0的控制,同样如INT1。

中断控制寄存器GICR(INT1,INT0,INT2,-,-,-,IVSEL,ICVE),前三位分别是INT1,INT0,INT2,的外部中断使能位。

中断标志寄存器GIFR(INT1,INT0,INT2,-,-,-,-),前三位分别是INT1,INT0,INT2外部中断标志位,当中断发生时自动置位,进入中断服务程序后此标志自动清零。

下面是在IAR环境下,中断服务程序的写法,

(1)在头文件iom32.h中找到中断向量(中断入口)

Eg:#define    RESET_vect           (0x00)

       #define    INT0_vect            (0x04)

       #define    INT1_vect            (0x08)

       #define    INT2_vect            (0x0C)

(2)根据以上介绍的各种寄存器,对要使用的中断进行初始化。

(3)#pragma vector=INT0_vect               //这是一个关于外部中断0的中断服务程序

__interrupt void INT0_process()                        //interrupt前有两个下划线

{

  ************************        //要实现的功能

       ****************

}

Eg

#include<iom32.h>

void delay_ms(unsigned int time);       //延时函数

/******中断处理函数*************************/

 

void main()

{

  unsigned char position = 0;             //LED灯位置

  /*******I/O初始化*******************/

  PORTA = 0xff;                       //初始化PA口

  DDRA = 0xff;                        //PA工作方式为输出

 /********外部中断初始化**************/

  GICR = 0x40;                       //外部中断请求0使能

  MCUCR = 0x02;                        //INT0的下降沿产生异步中断请求

  SREG = 0x80;                          //全局中断使能

  while(1)

  {

    PORTA = ~(1<<position);

    if(++position>=8)position = 0;

    delay_ms(1000);            

  }

}

void delay_ms(unsigned int time)

{

  for(;time>0;time--);

}

#pragma vector=INT0_vect

__interrupt void INT0_process()

{

  PORTD = PORTD | 0x20;                   //把PD5置1,DDRD初始值是0x00,即PD端口全为输入口

  delay_ms(2000);                          //延时2s

  PORTD = PORTD & 0xdf;                   //解除警报

}

本函数实验用PD5检测外部中断报警,正常情况时led流水灯点亮。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AVRA是一个用于AVR单片机的汇编语言编程工具,实现呼吸灯程序可以使用AVR单片机的PWM模块。下面是一个在AVRA下实现呼吸灯效果的示例程序: ``` .DEVICE ATmega328P ;设备型号 .INCLUDE "m328pdef.inc" ;寄存器定义文件 .ORG 0x0000 ;程序入口地址 ;端口定义 .LED_PORT = PORTB .LED_DDR = DDRB .LED_PIN = PINB1 ;常量定义 .LOOP_COUNT = 100 ;循环次数,可调整呼吸频率 .PWM_TOP = 255 ;PWM计数器最大值 ;初始化 INIT: ;设置PWM模式为快速PWM,频率为1MHz/256=3.9kHz ldi r16, (1<<WGM01)|(1<<WGM00)|(1<<COM1A1)|(0<<COM1A0)|(0<<CS12)|(1<<CS11)|(0<<CS10) out TCCR1A, r16 ldi r16, (0<<FOC1A)|(0<<OCIE1A)|(0<<OCIE1B)|(0<<TOIE1) out TCCR1B, r16 ldi r16, PWM_TOP ;设置计数器最大值 out OCR1A, r16 ;设置LED引脚为输出模式 sbi LED_DDR, LED_PIN ;初始化计数器为0 ldi r16, 0 out TCNT1, r16 LOOP: ;计数器递增 inc r16 out TCNT1, r16 ;判断计数器是否达到循环次数 cpi r16, LOOP_COUNT brne LOOP ;计算PWM输出占空比(呼吸灯效果) ldi r16, PWM_TOP/2 sub r16, TCNT1 lsr r16 out OCR1A, r16 ;延时一段时间 ldi r16, 0 WAIT: inc r16 cpi r16, 100 brne WAIT ;跳转回循环 jmp LOOP ``` 该程序使用AVR单片机的16位定时器/计数器1实现PWM输出,计算占空比来控制LED亮度。关键部分为计算PWM输出占空比的代码,即: ``` ldi r16, PWM_TOP/2 sub r16, TCNT1 lsr r16 out OCR1A, r16 ``` 其中,PWM_TOP为PWM计数器最大值,TCNT1为当前计数器值。该代码计算出占空比为PWM_TOP/2 - TCNT1/2,实现呼吸灯效果。 注意:具体实现细节可能因单片机型号、外设配置等不同而有所差异,需要按照实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值