原创 avr中断

2013-3-1 22:28 2221 18 18 分类: MCU/ 嵌入式 文集: 单片机与ARM

使用一个新的单片机大概也就是下面的这个流程

1,开发环境以及使用

2,片上资源认识和最小系统

3,寄存器,时钟,复位和中断

让单片机跑起来

 

不断熟悉和使用各种muc资源

 

关于中断

中断教程

http://wenku.baidu.com/view/cc186efc700abb68a982fb1e.html

 

AVR使用范例--AVR外部中断范例

本页关键词: 单片机外部中断 外部中断的应用 AVR外部中断 INTERUPTS

关于AVR中断:

系统在正常运行主程序时,如果突然有一个重要的任务要马上处理,那么系统就要保存现在的工作,然后再去处理这个任务,执行这个重要任务完毕以后再返回原来的主程序继续运行,这就是中断。

主程序一旦进入中断服务程序,那么AVR芯片将自动的关闭全局中断,在这个期间不再执行其它的中断请求,直到中断程序结束以后芯片才自动的重新开放全局中断。(注意,在这个期间某些中断请求可能会被丢弃,某些请求会留下中断请求标致,一旦当前的中断执行完毕,这个有中断标致的请求就有可能马上得到响应,如INT0的下降沿触发就会留下中断请求标致,而低电平触发就不会流下中断请求标致)。如果你想在执行中断服务程序时响应另外一个更重要的中断,那么就要在中断服务程序中加入一条打开全局中断的语句。

使用ICC快速建立中断服务程序 程序文件[txt]

使用ICCAVR Application Builder进行如下图所示的设置。 可以设置是否使用中断,上升延,下降延,低电平,任意的逻辑电平变化。

设置外部中断可用

将生成的程序进行修改,DDRA = 0x01;PORTD = 0x0C; ,添加MAIN函数,如下

  • //ICC-AVR application builder : 2006-12-8 17:04:44
    // Target : M16
    // Crystal: 7.3728Mhz
    
    #include 
    #include 
    
    unsigned int i=0;
    
    void port_init(void)
    {
     PORTA = 0x00;
     DDRA  = 0x01;
     PORTB = 0x00;
     DDRB  = 0x00;
     PORTC = 0x00; //m103 output only
     DDRC  = 0x00;
     PORTD = 0x0C; //使INT0,INT1对应口上拉电阻有效
     DDRD  = 0x00; //必须设置INT0,INT1对应口为输入
    }
    
    #pragma interrupt_handler int0_isr:2
    void int0_isr(void)
    {
     //external interupt on INT0
     i++;  //在中断里进行操作
    }
    
    #pragma interrupt_handler int1_isr:3
    void int1_isr(void)
    {
     //external interupt on INT1
     PORTA = 0x01;     //在中断里进行操作
    }
    
    //call this routine to initialize all peripherals
    void init_devices(void)
    {
     //stop errant interrupts until set up
     CLI(); //disable all interrupts
     port_init();
    
     MCUCR = 0x08;  //INT1 的下降沿产生异步中断请求,INT0上升延
     GICR  = 0xC0;  //INT0和INT1使能
     TIMSK = 0x00; //timer interrupt sources
     SEI(); //re-enable interrupts
     //all peripherals are now initialized
    }
    
    void main(void)
    {
     init_devices();
     while(1)   //死循环等待中断
     ;
    }

 

AVR定时器0、1

ATmega16一共配置了2个8位和1个16位,共3个定时计数器,它们是8位的定时计数器T/C0、T/C2和16位的定时计数器T/C1。功能强大,但也非常复杂,不易掌握,欢迎大家讨论:
1、谈谈AVR定时器的学习方法,各定时器的优缺点及最佳使用场合
2、在使用AVR过程中,对AVR定时器的应用,欢迎贴出你的代码
3、你在使用AVR定时器过程中碰到的疑难问题,怎么解决的,或未解决的需要帮忙的


AVR定时器知识要点总结:
1、   定时器数量:分别是T/C0、T/C2、T/C1 ;ATmega16一共配置了2个8位和1个16位,共3个定时计数器,它们是8位的定时计数器T/C0、T/C2和16位的定时计数器T/C1。
2、   定时器中断源:ATmega16共有8个定时中断,分别是TIMER2 COMP、TIMER2 OVF、TIMER1 CAPT、TIMER1 COMPA、TIMER1 COMPB、TIMER1 OVF、TIMER0 OVF、TIMER0 COMP;从表1中可以得出如下结论:
a:定时器中断优先级低于复位中断、外部中断0、外部中断1,见表1;TC2的中断优先级高于TC1,TC1的中断优先级高于TC0;
b:定时器的中断向量号是从4~10,还有一个20(可以这样来记:复位中断是最高的,其次是外部中断,最后是定时中断,外部中断2是个特例,TC0比较匹配也是个特例)
c:定时器的匹配中断优先级高于其溢出中断(TC0是个特例,溢出中断优先级高于匹配中断),事件捕捉中断优先级高于匹配中断!
d:TC1有4个中断,TC0,TC2各有两个中断;

  
  表1   mega16的中断向量区
向量号 Flash空间地址     中断源                 中断定义说明
1   $000                 RESET             外部引脚电平引发的复位、
                                          上电复位、掉电检测复位、
                                            看门狗复位、JTAG AVR复位
2   $002                 INT0               外部中断请求0
3   $004                 INT1               外部中断请求1
4   $006               TIMER2 COMP     定时计数器2比较匹配
5   $008               TIMER2 OVF       定时计数器2溢出
6   $00A               TIMER1 CAPT       定时计数器1事件捕捉
7   $00C               TIMER1 COMPA   定时计数器1比较匹配A
8   $00E               TIMER1 COMPB   定时计数器1比较匹配B
9   $010               TIMER1 OVF       定时计数器1溢出
10   $012               TIMER0 OVF       定时计数器0溢出
19   $024               INT2               外部中断请求2
20   $026               TIMER0 COMP     定时计数器0比较匹配



3、    波形发生模式 T/C0、T/C2有4种波形模式,T/C1有16种波形
      a:T/C0、T/C2分别由TCCR0中的两位 WGM0[1:0](位3、6)、TCCR2中的两位 WGM2[1:0](位3、6)来控制;
      b: T/C1则由TCCR1B中的两位WGM1[3:2](位4、3)和TCCR1A中的两位WGM1[1:0](位1、0)
4、    比较匹配输出方式:T/C0、T/C2有4比较匹配输出模式,T/C1有16种波形
a:T/C0中的COM0[1:0](TCCR0位5,4)控制比较匹配输出模式,非PWM模式WGM = [0,2]有4种输出模式,PWM模式WGM = [1,2]有3种输出模式
b:T/C2中的COM2[1:0](TCCR2位5,4)控制比较匹配输出模式,非PWM模式WGM = [0,2]有4种输出模式,PWM模式WGM = [1,2]有3种输出模式
c:T/C1中的COM1A[1:0](TCCR1A位7,6)控制通道A比较匹配输出模式, T/C1中的COM1B[1:0](TCCR1A位5,4)控制通道B比较匹配输出模式,各有四种输出模式
5、    各定时器的最佳使用场合(不知道,望各位网友讨论补充)
a:TC0
b:TC1
c:TC2


第二部分:定时器0 T/C0
定时器0有两个中断源TIMER0 OVF(溢出中断)和TIMER0 COMP(比较匹配中断),中断向量号分别为10和20;在三个定时器中,T/C0的中断级别最低。(PS:既然TIMER0 OVF(溢出中断)比TIMER0 COMP(比较匹配中断)优先级要高,那么T/C0主要用在计数方面吧?^-^ ^-^)
1、   T/C0的时钟源 T/C0的计数时钟源可由来自外部引脚T0(PB0)的信号提供,也可来自芯片的内部。时钟源的选择由TCCR0中的3个标志位CS0[2:0]确定,共有8种选择:无时钟;内部时钟有5种分频选择(1,8,64,256,1024);外部时钟有2种(下降沿和上升沿)。
a:当定时计数器使用系统内部时钟作为计数源时,通常作为定时器和波形发生器使用。
注意:有5种分频选择(1,8,64,256,1024),同T/C1共用一个预定比例分频器,两者分别使用了CS02 CS01 CS00 和 CS12 CS11 CS10 两组控制逻辑来控制最后输出,互不影响;但有一个特定的情况,预分频器复位将会影响所有与其连接的T/C。
b:当定时计数器使用外部时钟作为计数源时,通常作为计数器使用,用于记录外部脉冲的个数。使用时,需注意以下几点:
A、   由于引脚上同步与边沿监测电路的存在,引脚T0/T1 上的电平变化需要延时2.5 到3.5 个系统时钟周期才能使计数器进行更新;
B、   外部时钟脉冲宽度必须大于一个系统时钟周期;
C、   外部时钟源的最高频率不大于 fclk_I/O/2.5;
D、   外部时钟源不送入预分频。
2、T/C0比较匹配单元 8位比较器持续对TCNT0和输出比较寄存器OCR0进行比较。一旦TCNT0等于OCR0,比较器就给出匹配信号。在匹配发生的下一个定时器时钟周期输出比较标志OCF0 置位。
注意:A、PWM 模式时,使能双缓冲功能,CPU 访问的是OCR0缓冲寄存器;
B、正常工作模式和CTC模式,禁止双缓冲功能时CPU 访问的则是OCR0 本身;
C、 强制输出比较,在非PWM 模式时,可以通过对强制输出比较位FOC0写”1” 的方式来产生比较匹配。强制比较匹配不会置位 OCF0 标志,也不会重载/ 清零定时器,但是OC0 引脚将被更新,好象真的发生了比较匹配一样;
D、 写TCNT0 操作将阻止比较匹配, CPU 对TCNT0 寄存器的写操作会在下一个定时器时钟周期阻止比较匹配的发生;
E、OC0 的设置应该在设置数据方向寄存器之前完成;在使用OC0 功能之前首先要通过数据方向寄存器的DDR_OC0 位将此引脚设置为输出;
PS:双缓冲可以将更新OCR0 寄存器与top 或bottom 时刻同步起来,从而防止产生不对称的PWM 脉冲,消除了干扰脉冲。不理解该段描述含意!
3、工作模式 工作模式- T/C 和输出比较引脚的行为- 由波形发生模式(WGM01:0) 及比较输出模式(COM01:0) 的控制位决定。比较输出模式对计数序列没有影响,而波形产生模式对计数序列则有影响。COM01:0 控制PWM 输出是否为反极性。非PWM 模式时COM01:0 控制输出是否应该在比较匹配发生时置位、清零,或是电平取反



表2.1 T/C0的工作模式
模式   WGM01   WGM00   COM01   COM00   T/C0工作模式   计数上限值   OCR0更新   TOV0置位   说明
0   0   0   0   0   普通模式   0xFF   立即   0xFF   PB3为通用I/O引脚
0   0   0   0   1   普通模式   0xFF   立即   0xFF   比较匹配时触发OC0
0   0   0   1   0   普通模式   0xFF   立即   0xFF   比较匹配时清零OC0
0   0   0   1   1   普通模式   0xFF   立即   0xFF   比较匹配时置位OC0
1   0   1   0   0   PWM,相位可调   0xFF   0xFF   0x00   PB3为通用I/O引脚
1   0   1   0   1   PWM,相位可调   0xFF   0xFF   0x00   保留
1   0   1   1   0   
PWM,相位可调   0xFF   0xFF   0x00   向上计数过程中比较匹配时清零OC0
                                        向下计数过程中比较匹配时置位OC0
1   0   1   1   1   
PWM,相位可调   0xFF   0xFF   0x00   向上计数过程中比较匹配时置位OC0
                                        向下计数过程中比较匹配时清零OC0
2   1   0   0   0   CTC模式   OCR0   立即   0xFF   PB3为通用I/O引脚
2   1   0   0   1   CTC模式   OCR0   立即   0xFF   比较匹配时触发OC0
2   1   0   1   0   CTC模式   OCR0   立即   0xFF   比较匹配时清零OC0
2   1   0   1   1   CTC模式   OCR0   立即   0xFF   比较匹配时置位OC0
3   1   1   0   0   快速PWM   0xFF   0xFF   0xFF   PB3为通用I/O引脚
3   1   1   0   1   快速PWM   0xFF   0xFF   0xFF   保留
3   1   1   1   0   快速PWM   0xFF   0xFF   0xFF   比较匹配时清OC0,计数值为0xFF   
                                                      时置位OC0
3   1   1   1   1   快速PWM   0xFF   0xFF   0xFF   比较匹配时置OC0,计数值为0xFF
                                                      时清零OC0

4、T/C0相关存储器
========================================================================

发一个跑表程序,该程序用的是T/C0溢住中断,四位数码管动态扫秒,每为显示2MS,显示时时间0~99.99秒,经过测试正确

/************************************************************
ICC-AVR application builder : 2008-4-17 16:11:30
Target : M16
Crystal: 4.0000Mhz
文件:timer_00
设计:raosibin
时间:2008-4-17
版本:ver1.0
功能说明:T/C0中断溢出实验,每10MS中断一次,刷新显示数据;
      动态扫描显示方式;
硬件说明:PA0~PA3接数玛管的A,B,C,D;PB0~PB6接a,b,c,d,e,f,g;
**************************************************************/
#include
#include

const unsigned char seg7_data[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
                      0x6f}; //0,1......9 段码
const unsigned char position_data[]={0xf1,0xf2,0xf4,0xf8}; //0,1,2,3, 位选通
unsigned char    timer[4];                    // 秒计数单元
unsigned char posit;
volatile char counter;
volatile char    flag_10ms;
volatile char    flag_2ms;

void port_init(void)
{
PORTA = 0x00;
DDRA = 0xFF;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}

void display(void)                // 4位LED数码管动态扫描函数
{
  PORTA = 0x00;    
   PORTB = seg7_data[timer[posit]]; 
   PORTA = position_data[posit]; 
   if (++posit >=4 ) posit = 0;
}

//TIMER0 initialize - prescale:64
// WGM: Normal
// desired value: 2mSec
// actual value: 2.000mSec (0.0%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x83; //set count
OCR0 = 0x7D; //set compare
TCCR0 = 0x03; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
//flag_10ms=1;
TCNT0 = 0x83; //reload counter value
flag_2ms=1;
if (++counter >=5)
{
counter=0;
flag_10ms=1;
}
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();

MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}


void main(void)
{
timer[0]=0;
timer[1]=0;
timer[2]=0;
timer[3]=0;
init_devices();
/*计数数值调整,显示的范围为99.99S*/
while(1)
{
  if (flag_10ms==1)
  {
  flag_10ms=0;
  if (++timer[0]>=10)
  {
    timer[0]=0;
    if (++timer[1]>=10)
    {
        timer[1]=0;
        if (++timer[2]>=10)
        {
          timer[2]=0;
           if (++timer[3]>=10)
           {
            timer[3]=0;
           }
        }
    }
    }
    }
    
  if (flag_2ms==1)
   {
    flag_2ms=0;
    display();
   }
 }
}

http://www.mculover.com/post/51.html

avr

文章评论0条评论)

登录后参与讨论
我要评论
0
18
关闭 站长推荐上一条 /2 下一条