2、基于 ATMEGA-16 Timer 的 PWM 与 Proteus 仿真


   基于 Atmega16 的Timer 实现的 PWM 信号, 设置定时器的溢出中断和比较中断的不同时间,从而控制 PWM 的频率和占空比。代码比较简单,但可以了解 AVR 单片机的中断系统,以及定时器的使用。

开发环境    :ICC AVR

程序代码如下 :

#include
#include

#define PPM_PORT  PORTB
#define PPM_DIR   DDRB
#define PPM_Pin   BIT(7)

unsigned int timeValue = 2100;

#define Counter   (65536 - timeValue)
#define Compare   (Counter + 400)

/* PPM 初始化 */
void PPM_Init(void)
{
    /* -------------- GPIO 管脚初始化 -------------- */
    PPM_PORT |= PPM_Pin;
    PPM_DIR  |= PPM_Pin;


    /* -------------- 定时器初始化 -------------- */
    TCNT1 = Counter;     /* 定时器初值, 产生溢出中断 */ 
    OCR1A = Compare;    /* 匹配比较输出 - 0.4ms 高电平 */


    TIMSK  |= (1 << 4) | (1 << 2); /* 开启比较 A 中断和溢出中断允许 */
    TCCR1B |= 0x02;                   /* 启动定时器, 普通模式, 8 分频 */
}


void Peripheral_Init(void)
{
    /* 禁止所有中断 */
    CLI();           

    /* 禁止 JTAG */
    MCUCR  = 0x00;
    MCUCSR = 0x80;  
    GICR   = 0x00;

    PPM_Init();

    /* 开全局中断 */
    SEI();    
}


/* T1 比较中断服务程序, 在 TCNT1 = OCR1A */
#pragma interrupt_handler timer1_comp_isr:7
void timer1_comp_isr(void)
{
    /* 输出低电平, 持续到溢出中断 */ 
    PPM_PORT &= ~PPM_Pin;   
}


/* T1 溢出中断服务程序 */
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
{
    TCNT1 = Counter;

    /* 输出高电平, 持续到溢出中断, 也就是 0.4ms */
    PPM_PORT |= PPM_Pin;   
}


void main(void)
{
    Peripheral_Init();

    while(1)
    {
        NOP();
    }
}


proteus 仿真效果

2、基于 ATMEGA-16 Timer 的 PWM 与 Proteus 仿真_第1张图片


程序与仿真下载 :




你可能感兴趣的:(Atmega)