搜索
bottom↓
回复: 4

定时器0,2无法同时工作在CTC模式问题

[复制链接]

出0入0汤圆

发表于 2009-8-19 20:42:44 | 显示全部楼层 |阅读模式
我设置ATmega16的定时器0,2都工作在CTC模式,单独用定时器0或者单独用定时器2都没有问题,但是一起工作时只有一个能正常工作,详细说明如下:
硬件连线:PINC2 -- +LED1- --PINC3
          PINC2 -- +LED2- --PINC7
PINC2连LED1,LED2的正极,LED1的负极连PINC3,LED2的负极连PINC7
预期程序功能:Timer0匹配中断后控制PINC7取反,LED2闪烁
              Timer2匹配中断后控制PINC3取反,LED1闪烁
实际效果:在主程序中初始化Timer0,不初始化Timer2,LED2闪烁
          在主程序中初始化Timer2,不初始化Timer0,LED1闪烁
          在主程序中先初始化Timer0,再初始化Timer2,LED1闪烁,LED2灭
          在主程序中先初始化Timer2,再初始化Timer0,LED2闪烁,LED1灭
  
程序:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//M16 at 12MHz

#define SET_BIT(io ,bit) (  io |=  (1<<bit) )
#define CLR_BIT(io ,bit) (  io &= ~(1<<bit) )
#define GET_BIT(pin,bit) ( pin &   (1<<bit) )
#define SET_IN( dir,bit) ( dir &= ~(1<<bit) )
#define SET_OUT(dir,bit) ( dir |=  (1<<bit) )

unsigned char flag0 = 0;
unsigned char flag2 = 0;

void Timer0Init (void)
{
        TCCR0 = _BV(CS02)|_BV(CS00)|_BV(WGM00)|_BV(WGM01);
        OCR0 = 200;
        TIMSK = _BV(OCIE0);
}

void Timer2Init (void)
{
        TCCR2 = _BV(WGM21)|_BV(CS22)|_BV(CS21)|_BV(CS20);
        OCR2 = 200;
        TIMSK = _BV(OCIE2);
}

SIGNAL(SIG_OUTPUT_COMPARE2)
{
        if (flag2 == 0)
        {SET_BIT(PORTC,3);flag2=1;}
        else
        {CLR_BIT(PORTC,3);flag2=0;}
}  

SIGNAL(SIG_OUTPUT_COMPARE0)
{
        sei();
//这里“sei();”加与不加是一样的
        if (flag0 == 0)
        {SET_BIT(PORTC,7);flag0=1;}
        else
        {CLR_BIT(PORTC,7);flag0=0;}
}
int main(void)
{
        SET_OUT(DDRC,2);//设置输出
        SET_OUT(DDRC,3);
        SET_OUT(DDRC,7);
       
        SET_BIT(PORTC,2);//初始LED1,2灭
        SET_BIT(PORTC,3);
        SET_BIT(PORTC,7);

        Timer0Init ();//这两句前后顺序有影响
        Timer2Init ();//
       
        sei();
        while(1);
}
我用的编译器是站内下载的WinAVR-20060421
思考:如果Timer0在中断程序中,Timer2中断发生,AVR的中断有优先级,Timer2匹配中断比Timer0匹配中断优先级高,在Timer0中断程序中加入“sei()”,但是看上去效果还是一样的;如果程序在一个中断A(指这里的Timer0或Timer2中断)处理过程中,另一个中断B(指这里的Timer0或Timer2中断)发生了,那也会在A中断处理完之后处理B中断了啊。。。
找了很久没有找到原因,也没搜到相关的讨论,只好发帖求救了。。。

出0入0汤圆

 楼主| 发表于 2009-8-20 09:06:35 | 显示全部楼层
今天我安装了CVAVR,实现了上述功能,用CodeViewzardAVR设置了定时器0,2的工作模式,用如下程序:
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.9 Standard
Automatic Program Generator
?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 2009-8-20
Author  : F4CG                           
Company : F4CG                           
Comments:


Chip type           : ATmega16
Program type        : Application
Clock frequency     : 12.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega16.h>

#define SET_BIT(io ,bit) (  io |=  (1<<bit) )  
#define CLR_BIT(io ,bit) (  io &= ~(1<<bit) )  
#define GET_BIT(pin,bit) ( pin &   (1<<bit) )  
#define SET_IN( dir,bit) ( dir &= ~(1<<bit) )  
#define SET_OUT(dir,bit) ( dir |=  (1<<bit) )

unsigned char flag0 = 0;
unsigned char flag2 = 0;

// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
// Place your code here
   if (flag0 == 0)
        {SET_BIT(PORTC,7);flag0=1;}
   else  
        {CLR_BIT(PORTC,7);flag0=0;}
}

// Timer 2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
// Place your code here
   if (flag2 == 0)
        {SET_BIT(PORTC,3);flag2=1;}
   else  
        {CLR_BIT(PORTC,3);flag2=0;}
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 11.719 kHz
// Mode: CTC top=OCR0
// OC0 output: Disconnected
TCCR0=0x0D;
TCNT0=0x00;
OCR0=0xC8;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 11.719 kHz
// Mode: CTC top=OCR2
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x0F;
TCNT2=0x00;
OCR2=0xC8;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x82;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts     

SET_OUT(DDRC,2);//设置输出
SET_OUT(DDRC,3);
SET_OUT(DDRC,7);

SET_BIT(PORTC,2);//初始LED1,2灭
SET_BIT(PORTC,3);
SET_BIT(PORTC,7);

#asm("sei")

while (1)
      {
      // Place your code here

      };
}
///////////////////////////////////////////////////////////////////////
今天起的太早了,现在都有点迷糊了,要上班了,空的时候再找下问题出在哪里。。。

出0入0汤圆

 楼主| 发表于 2009-8-20 10:11:48 | 显示全部楼层
在楼主位的程序和1楼的程序有如下区别:
1. 楼主位的程序中没有以下3句:
   a。 TCNT2=0x00;
   b。 TCNT0=0x00;
   c。 ACSR=0x80;//模拟比较器禁用
2. TCCR0设置不一样
   楼主位:TCCR0 = _BV(CS02)|_BV(CS00)|_BV(WGM00)|_BV(WGM01);
   设置Timer0工作在快速PWM模式了

修改以上不用处程序,再用WinAVR编译,测试,现象还是一样。

在发此帖之前是用Timer0和Timer1溢出中断处理的,m16的datasheet上说Timer0和Timer1是用同一个预分频器,在主程序初始化定时器后开中断前“SFIOR = _BV(PSR10);//复位预分频器”,现象还是一样的。。。

出0入0汤圆

 楼主| 发表于 2009-8-25 21:21:19 | 显示全部楼层
void Timer0Init (void)
{
TCCR0 = _BV(CS02)|_BV(CS00)|_BV(WGM00)|_BV(WGM01);
OCR0 = 200;
TIMSK = _BV(OCIE0);
}

void Timer2Init (void)
{
TCCR2 = _BV(WGM21)|_BV(CS22)|_BV(CS21)|_BV(CS20);
OCR2 = 200;
TIMSK = _BV(OCIE2);
}

上面代码中对TIMSK操作有问题!
应改为:TIMSK |= _BV(OCIE0);TIMSK |= _BV(OCIE2);

出0入0汤圆

发表于 2009-11-1 20:36:34 | 显示全部楼层
学习了!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 11:07

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表