powtran 发表于 2011-7-29 10:39:22

定时器产生脉冲同步问题

要实现以上波形,PB0(T0)接收外部开关的信号(频率在改变),波形为第1个。AVR M16程序参考马老师的例子8.3 N分频系统实现8分频,占空比为1:8,输出波形如图2 ,分频后的信号从PD7输出(以上2步都实现并验证过)。图中1的周期《=1MS ,想让图3中脉冲宽度=0.5MS .考虑使用定时器2实现,思路如下:在图2波形的上升沿,启动TC2,TC2工作在CTC模式,采用比较匹配中断,比较匹配中断时间设置为0.5MS,在比较匹配中断中复位PD7,并且停止TC2工作。再在TC0的比较匹配中断中启动TC2,保证图2和图3的脉冲同步。程序如下,但是PD7没有输出波形,不知道哪里出了问题,请各位高手帮忙分析一下。程序如下:
#include <iom16v.h>
#include <macros.h>
#defineuchar unsigned char
#defineuintunsigned int
unsigned int value_ovf,value_comp;

void port_init(void)
{
PORTA = 0x00;
DDRA= 0x00;//设置PA0为输入方式

PORTB = 0x00;
DDRB= 0x00;   //设置PB0(TO)为输入方式

PORTC = 0x00;   //m103 output only
DDRC= 0x00;

PORTD = 0x00;   //PD口输出低电平
DDRD= 0xFF;   //设置PD口为输出方式
}

//定时器T0初始化
void timer0_init(void)
{
//T/C0初始化
   TCCR0=0X07;            //设置T/C0工作普通模式,T0上升沿触发
   TCNT0=value_ovf;         //PB0口信号8分频,PD口输出
   OCR0=value_comp;         // 设置OCR0的比较值,>TCNT0的初始值,<0xFF
   TIMSK=0X03;            //允许T/C0的溢出和比较匹配中断
   SEI();                   //开放全局中断
}
//Timer 0溢出中断服务
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
   TCNT0=value_ovf;         // 重新设置TCNT0的初值
   PORTD&=0X7F;            //使PD7复位,其它位保持不变0111 1111
   
}
// Timer 0 比较匹配中断服务
#pragma interrupt_handler timer0_comp_isr:20
void timer0_comp_isr(void)
{
PORTD|=0X80;      //使PD7置1,其它位保持不变 1000 0000
TCCR2=0X0E;         //启动TC2
}

//定时器T2初始化
void timer2_init(void)
{ // T/C2初始化
TCCR2=0x0C; // 内部时钟,64分频(4M/64=62.5KHz),CTC模式
//0000 1100(110为64分频)
TCNT2=0x00;
OCR2=0x0C;// OCR2 = 0x0C(30),(300+1)/62.5=0.496ms
TIMSK=0x80; // 允许T/C2比较匹配中断
SEI();
}

//********************T/C2中断服务函数********************//
#pragma interrupt_handler Timer2_comp:4
void Timer2_comp(void)
{
PORTD&=0X7F;            //使PD7清零,其它位保持不变
TCCR2=0X08;             //停止TC2
}

void main(void)
{
   port_init();            //端口初始化程序
   value_ovf=255-8+1;   //8为8分频
   value_comp=255-1;      //占空比调节
   timer0_init();      //定时器T0初始化
   timer2_init();      //定时器T2初始化
   
   while(1)
   {
    NOP;
}

http://cache.amobbs.com/bbs_upload782111/files_43/ourdev_661809G3QK5E.GIF
波形图示 (原文件名:波形图.GIF)

powtran 发表于 2011-8-1 10:24:02

没有人回答,自己顶一个。

machao 发表于 2011-8-1 13:39:56

问题出在2个定时器初始化过程中:

timer0_init();      //定时器T0初始化   =====》    TIMSK=0X03;            //允许T/C0的溢出和比较匹配中断

timer2_init();      //定时器T2初始化   =====》    TIMSK=0x80;            // 允许T/C2比较匹配中断(但前面T0中断允许被清掉了!)


你PD7的控制使用了“ PORTD|=0X80;      //使PD7置1,其它位保持不变 1000 0000”
奇怪的是TIMSK的设置为什么没有使用这样的方式?

因此我觉的你的学习方法还是需要改进,每个概念、每个方法、每条语句都要真正的去掌握,全面的考虑。而不是简单的拼代码,做组合。

另外,开全局中断的语句不要放在各个接口的初始化模块中,应该在全部系统初始化后,最后统一开启。

===============================

下面给你另外一个比较简单的办法是:

1。TO只要工作在比较匹配(ctc)输出方式,输出触发方式为置1(参考例8.5),比较值为7。每计数8个,T0会自己将PD7置1,将TCNT0清零,并进入中断。

2。在T0的比较匹配中断中开启T2:
   void timer0_comp_isr(void)
   {
      //PORTD|=0X80;      //使PD7置1,其它位保持不变 1000 0000   这句不要,T0比较匹配会自动置PD7为1的(初始化输出触发方式为置1)
      TCNT2 = 0;         //清零TC2计数器(保证0.5ms更准些)   
      TCCR2=0X0E;         //启动TC2
   }

3。T2按原来方式工作在CTC方式,中断中清零PD7,并停止自己计数。

powtran 发表于 2011-8-1 17:22:59

谢谢马老师。
页: [1]
查看完整版本: 定时器产生脉冲同步问题