×
单片机 > 单片机程序设计 > 详情

AVR单片机定时器、PWM、ICP范例

发布时间:2020-06-08 发布时间:
|

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


****      AVR 定时器使用范例                   ***


****                                              ***


**** 编译器:WINAVR20050214                   ***


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


/*


本程序简单的示范了如何使用ATMEGA16的定时器


AVR定时器的要点介绍


T0工作于CTC模式,输出1KHz/2KHz 50%占空比的方波


T1工作于快速PWM模式兼输入捕捉


T2工作于相位修正PWM模式,输出490Hz的8bit PWM波


      


出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器


对于定时器,AVRstudio的软件仿真是不准确的。


*/


#include


#include


#include


//时钟定为8MHz,F_CPU=8000000


//管脚定义


#define ICPKEY        6 //ICP1  PD6 按键模拟ICP输入


#define PWM0        3 //OC0   PB3


#define PWM1A        5 //OC1A  PD5


#define PWM1B        4 //OC1B  PD4


#define PWM2        7 //OC2   PD7


//宏定义


#define PWM1A_ON()        PORTD|= (1<


#define PWM1A_OFF()        PORTD&=~(1<


//全局变量


volatile unsigned int ICP_Time;        //记录ICP输入捕捉事件的发生时刻


volatile unsigned char T2PWM;        //设置T2的PWM值


volatile unsigned char T0OCR;        //设置T0的时间值


//仿真时在watch窗口,监控这些变量。


void timer0_init(void) //CTC模式输出1KHz/2KHz方波


{


OCR0  = T0OCR;  //设定TOP值


//TOP=8000000/(2*64*1000)-1=61.5  选61  1.008KHz(0.992mS)


//TOP=8000000/(2*64*2000)-1=30.25 选30  2.016KHz(0.496ms)


TCCR0 = (1<


//64分频,CTC模式,OC0取反输出方波


}


void timer1_init(void)


{


OCR1A  = 39062;        //设定TOP值.时间5S(0.2Hz)


//TOP=8000000/(1024*0.2)=39062.5


OCR1B  = 15624;        //设定OC1B的PWM值 约2秒钟 40%


TCCR1A = (1<


TCCR1B = (0<


//1024分频,WGM1=15 快速PWM模式,TOP=OCRnA,ICP下降沿触发,OC1B正向PWM输出,OC1A为普通IO


}


SIGNAL(SIG_INPUT_CAPTURE1) //输入捕捉中断


{


   ICP_Time=ICR1;  //读取ICP输入捕捉事件的发生时刻


}


SIGNAL(SIG_OUTPUT_COMPARE1A)//T1输出比较A匹配中断


{


//在WGM1=15 快速PWM模式下,TOP=39062等同于5S左右的定时中断


T2PWM+=10;


OCR2=T2PWM;        //修改T2的PWM值


if (T0OCR==61)


T0OCR=30;        //改成1KHz


else 


   T0OCR=61;        //改成2KHz


OCR0=T0OCR;        //修改T0的时间值


}


void timer2_init(void)//相位修正PWM模式


{


OCR2  = T2PWM;  //设定PWM值(最大值固定为255,8bit)


TCCR2 = (0<


//32分频,相位修正PWM模式,PWM频率为490Hz,OC2正向PWM输出


//fPWM=fclk_IO/(2*N*TOP)=8000000/(2*32*255)=490Hz


}


int main(void)


{


    //上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻


    PORTA =0xFF;        //不用的管脚使能内部上拉电阻。


    PORTC =0xFF;


    PORTB =~ (1<


    DDRB  =  (1<


    PORTD =~((1<


    DDRD  =  (1<


    


    


    T2PWM=0x80;


    T0OCR=30;


    ICP_Time=0x0000;


    


timer0_init();


timer1_init();


timer2_init();


TIMSK = (1<


    sei();        //使能全局中断


    while (1)


    {


    if (ICP_Time>15624)


    PWM1A_ON();        //如果数值大于15624(约2秒),OC1A输出高电平


    else 


    PWM1A_OFF();        //否则输出低电平


    }


}


/*


程序运行效果


     引脚OC0(每5秒钟切换)交替输出1KHz和2KHz的50%占空比方波,接到无源蜂鸣器上,能听到不同频率的声音


     引脚OC1B输出0.2Hz的40%占空比的PWM波,精度39061级(略大于15bit)


     引脚OC2输出490Hz的PWM波,精度8bit,每5秒钟PWM值增大10级,对应的LED亮度将会随之变化)


     


     ICP由引脚ICP1上的按键触发,ICP_Time将会记录下时间发生的时刻(相对于T1定时器的本次计数开始时间),


     如果数值大于15624(约2秒),OC1A输出高电平,否则输出低电平(刚好跟OC1B反相)


     如果使用AVR-51实验板作本实验,注意输出电平和LED的关系。还有蜂鸣器的声音较大,耳朵比较难受)


*/


/*


附录 AVR定时器的要点介绍


(大部分摘自 M16中文手册,未能一一测试)


  M16的T1 16位定时器一共有15种工作模式,其他2个8位定时器(T0/T2)相对简单,除了T2有异步工作模式用于RTC应用外


                       (可以利用溢出中断和比较匹配中断作定时功能)


  分5种工作类型


  1  普通模式 WGM1=0


    跟51的普通模式差不多,有TOV1溢出中断,发生于TOP时


    1 采用内部计数时钟     用于 ICP捕捉输入场合---测量脉宽/红外解码


        (捕捉输入功能可以工作在多种模式下,而不单单只是普通模式)


    2 采用外部计数脉冲输入  用于 计数,测频


    其他的应用,采用其他模式更为方便,不需要像51般费神


    


  2 CTC模式 [比较匹配时清零定时器模式] WGM1=4,12


  跟51的自动重载模式差不多


  1 用于输出50%占空比的方波信号


  2 用于产生准确的连续定时信号


  WGM1=4时, 最大值由OCR1A设定,TOP时产生OCF1A比较匹配中断


  WGM1=12时,最大值由ICF1设定, TOP时产生ICF1输入捕捉中断


  注:WGM=15时,也能实现从OC1A输出方波,而且具备双缓冲功能


  计算公式: fOCn=fclk_IO/(2*N*(1+TOP))


     变量N 代表预分频因子(1、8、32,64、256,1024)。          


     


  3 快速PWM模式 WGM1=5,6,7,14,15 


    单斜波计数,用于输出高频率的PWM信号(比双斜波的高一倍频率)


    都有TOV1溢出中断,发生于TOP时


    比较匹配后可以产生OCF1x比较匹配中断.


           WGM1=5时, 最大值为0x00FF, 8位分辨率


           WGM1=6时, 最大值为0x01FF, 9位分辨率


           WGM1=7时, 最大值为0x03FF,10位分辨率 


  WGM1=14时,最大值由ICF1设定, TOP时产生ICF1输入捕捉中断 (单缓冲)


  WGM1=15时,最大值由OCR1A设定,TOP时产生OCF1A比较匹配中断(双缓冲,但OC1A将没有PWM能力,最多只能输出方波)


  改变TOP值时必须保证新的TOP值不小于所有比较寄存器的数值


    注意,即使OCR1A/B设为0x0000,也会输出一个定时器时钟周期的窄脉冲,而不是一直为低电平


    计算公式:fPWM=fclk_IO/(N*(1+TOP))


  4 相位修正PWM模式 WGM1=1,2,3,10,11 


    双斜波计数,用于输出高精度的,相位准确的,对称的PWM信号


    都有TOV1溢出中断,但发生在BOOTOM时


    比较匹配后可以产生OCF1x比较匹配中断.


           WGM1=1时, 最大值为0x00FF, 8位分辨率


           WGM1=2时, 最大值为0x01FF, 9位分辨率


           WGM1=3时, 最大值为0x03FF,10位分辨率 


  WGM1=10时,最大值由ICF1设定, TOP时产生ICF1输入捕捉中断 (单缓冲)


  WGM1=11时,最大值由OCR1A设定,TOP时产生OCF1A比较匹配中断(双缓冲,但OC1A将没有PWM能力,最多只能输出方波)


    改变TOP值时必须保证新的TOP值不小于所有比较寄存器的数值


    可以输出0%~100%占空比的PWM信号


    若要在T/C 运行时改变TOP 值,最好用相位与频率修正模式代替相位修正模式。若TOP保持不变,那么这两种工作模式实际没有区别


    计算公式:fPWM=fclk_IO/(2*N*TOP)


  5 相位与频率修正PWM模式 WGM1=8,9 


    双斜波计数,用于输出高精度的、相位与频率都准确的PWM波形


    都有TOV1溢出中断,但发生在BOOTOM时


    比较匹配后可以产生OCF1x比较匹配中断.


WGM1=8时,最大值由ICF1设定, TOP时


关键字:AVR  单片机  定时器  PWM  ICP范例 


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
用Atmega 16单片机驱动字符型液晶显示芯片