标题:
m16 time1 無法正確 1sec 跑一次 timer1_ovf_isr
[打印本页]
作者:
jemmy0938
时间:
2010-11-19 04:27
标题:
m16 time1 無法正確 1sec 跑一次 timer1_ovf_isr
學習進度: 1sec 霹靂燈(五顆LED來回閃爍 1~5~1)
實作目標: m16/內建1Mhz OSC/ timer1方式 1sec 跑一次 timer1_ovf_isr 點燈
問題未解: 以 ICC AVR 內建的 Applicate Builder 生成的 time1 無法正確 1sec 跑一次 timer1_ovf_isr
以下為實作源碼,請學長們指正.謝謝.
----------------------------------------------------------------------------
#include <iom16v.h>
#include <macros.h>
#include "delaytime.c"
#include "led.h"
#include "led.c"
unsigned int timer1_count=0 ;
void LED_Init(void)
{
DDRA|=0XE0;
PORTA&=0X1F;
DDRC|=0X03;
PORTC&=0XFC;
}
void key_Init(void)
{
DDRC|=0XE0;
DDRC&=0XE3;
PORTC&=0X1F;
}
//TIMER1 initialize - prescale:256
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Sec
// actual value: 1.000Sec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xF0; //setup
TCNT1L = 0xBE;
OCR1AH = 0x0F;
OCR1AL = 0x42;
OCR1BH = 0x0F;
OCR1BL = 0x42;
//OCR1CH = $OCR1CH$;
//OCR1CL = $OCR1CL$;
ICR1H = 0x0F;
ICR1L = 0x42;
TCCR1A = 0x00;
TCCR1B = 0x04; //start Timer
}
void Gpio_Init(void)
{
LED_Init();
key_Init();
timer1_init();
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
//compare occured TCNT1=OCR1A
}
#pragma interrupt_handler timer1_compb_isr:8
void timer1_compb_isr(void)
{
//compare occured TCNT1=OCR1B
}
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void) // 燈號運作正常但時序不正確無法掌控...
{
//TIMER1 has overflowed
TCNT1H = 0xF0; //reload counter high value
TCNT1L = 0xBE; //reload counter low value
timer1_count++;
switch(timer1_count)
{
case 1:
{
LED2_OFF;
LED1_ON;
} break;
case 2:
{
LED1_OFF;
LED2_ON;
} break;
case 3:
{
LED2_OFF;
LED3_ON;
} break;
case 4:
{
LED3_OFF;
LED4_ON;
} break;
case 5:
{
LED4_OFF;
LED5_ON;
} break;
case 6:
{
LED5_OFF;
LED4_ON;
} break;
case 7:
{
LED4_OFF;
LED3_ON;
} break;
case 8:
{
LED3_OFF;
LED2_ON;
timer1_count=0;
} break;
}
}
void main(void)
{
CLI(); //disable all interrupts
Gpio_Init();
ALL_ON;
delay_nms(500);
ALL_OFF;
delay_nms(500);
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x1C; //timer interrupt sources
SEI(); //re-enable interrupts
while(1)
{
// led();
}
}
作者:
andylee
时间:
2010-11-19 14:47
回复
1#
jemmy0938
不用采用那种方式,可以采用如下方式:
/********************************************************
* timer2_init: 初始化定时器2:普通模式定时0.02s *
* 输入:无 *
* 输出:无 *
********************************************************/
void timer2_init(void)
{
TCCR2=0; //无时钟源,普通模式
// OCR2=100; //定时0.02s/8M 100
TCNT2=100;
TIMSK|=(1<<TOIE2); //溢出中断允许
}
/*********************************
* timer2_start:开启定时器2 *
* 输入:无 *
* 输出:无 *
*********************************/
void timer2_start(void)
{
TCCR2=0b00000111;
}
/*******************************************************************
* timer2_isr: 定时器2中断处理函数 *
* 输入:无 *
* 输出:无 *
*******************************************************************/
#pragma interrupt_handler timer2_isr:5
void timer2_isr(void)
{
TCNT2=100;
timer2_count++;
switch (timer2_count)
{
//第0.2s
case 10:
{
//adc_start(0); //采集电流
} break;
}
}
复制代码
作者:
panfeng881112
时间:
2010-11-19 20:11
本帖最后由 panfeng881112 于 2010-11-19 21:25 编辑
回复
1#
jemmy0938
首先欢迎您来我们论坛提问!
这里有一个公式!不知道能帮到您多少!
发生溢出中断时间(us)=震荡主频(Hz)*(65535-(TCNT1H*256+TCNT1L))
如果还有疑问尽管来提!要相信我们一定可以帮您解决的!
作者:
jemmy0938
时间:
2010-11-20 03:50
感謝各位學長們教導..@@
經過多方驗證後發現應該是MCU主頻錯誤導致頻率誤差.
這幾天一直誤認 PROGISP 中的 fuse 設定就是由片內讀取的設定 int 1Mhz.
經重新 fuse 設 int. 8Mhz+64ms 以 256 除頻 timer1 得出正確結果 1sec.
下列程式執行正確無誤...@@
-------------------------------------------------------------------------------------
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x85; //setup
TCNT1L = 0xEF;
OCR1AH = 0x7A;
OCR1AL = 0x11;
TCCR1A = 0x00;
TCCR1B = 0x0C; //start Timer
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
timer1_count++;
}
void main(void)
{
CLI(); //disable all interrupts
Gpio_Init();
timer1_init();
ALL_ON;
delay_nms(200);
ALL_OFF;
delay_nms(200);
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x10;
SEI(); //re-enable interrupts
while(1)
{
switch(timer1_count)
{
case 1:
{
LED2_OFF;
LED1_ON;
} break;
case 2:
{
LED1_OFF;
LED2_ON;
} break;
case 3:
{
LED2_OFF;
LED3_ON;
} break;
case 4:
{
LED3_OFF;
LED4_ON;
} break;
case 5:
{
LED4_OFF;
LED5_ON;
} break;
case 6:
{
LED5_OFF;
LED4_ON;
} break;
case 7:
{
LED4_OFF;
LED3_ON;
} break;
case 8:
{
LED3_OFF;
LED2_ON;
timer1_count=0;
} break;
}
}
}
作者:
andylee
时间:
2010-11-20 13:18
调试通了,那就恭喜了。
作者:
火儿
时间:
2010-11-20 14:20
我是新手!谢谢分享!学习了!呵呵~
作者:
jemmy0938
时间:
2010-11-21 16:13
本帖最后由 jemmy0938 于 2010-11-21 16:23 编辑
請問各位學長們:
設定 PORTC=0X03/ DDRC=0X03 後,量第2,3,4 依然是5V.這樣有正確嗎?
目前正學 KEYPAD 用到 PORTC 2~7, 可是怎樣設2,3,4 電壓都是 5V.
各位學長們有這情況嗎?經設定 PORTC=0X03/ DDRC=0X03 測 PC2,3,4,5 為高.測 6,7 可受控.
設 PORTD=0x00 / DDRD =0x00 測 PD7 為高,其他都正常.
這現象是 mcu 故障了?
作者:
andylee
时间:
2010-11-23 14:46
回复
7#
jemmy0938
设定IO口输出方向:1 用或的方式;0用与的方式;
如 PC0要为输出,则 DDRC|=0X01;
如PC10要为输入,则 DDRC&=0XFE;
同理控制的时候。
作者:
jemmy0938
时间:
2010-11-24 00:29
謝謝學長教導:再問一個情況作為總結.
中斷 T/C1 OVL + comp A+B 三種一起使用可以嗎?
1)OVL 方式功能一直都正常
2) COMP A/B 偶不正常,如:開機進 COMP A 第一次就停了.
3)兩天前一直用OVL+COMPA+COMPB,今天忽然又無法使用了,是否是編譯器的問題?
代碼如下,
----------------------------------------------------------------------------
void timer1_init(void)
{
TCCR1B = 0x00;
TCNT1H = 0x85;
TCNT1L = 0xEE;
OCR1AH = 0x01;
OCR1AL = 0x38;
OCR1BH = 0x01;
OCR1BL = 0x38;
TCCR1A = 0x00;
TCCR1B = 0x0C; //start Timer
}
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x0F;
DDRB = 0x00;
PORTC = 0x0F; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
//compare occured TCNT1=OCR1A
keyVal = ((PINB&0x0F) ^0X0F);
}
#pragma interrupt_handler timer1_compb_isr:8
void timer1_compb_isr(void)
{
//compare occured TCNT1=OCR1B
timer1_count++;
}
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0x85; //reload counter high value
TCNT1L = 0xEE; //reload counter low value
}
void main(void)
{
CLI(); //disable all interrupts
port_init();
timer1_init();
ALL_ON;
delay_nms(200);
ALL_OFF;
delay_nms(200);
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x1C;
SEI(); //re-enable interrupt
while(1)
{
switch(timer1_count)
{
case 1:
{
LED2_OFF;
LED1_ON;
} break;
case 2:
{
LED1_OFF;
LED2_ON;
} break;
case 3:
{
LED2_OFF;
LED3_ON;
} break;
case 4:
{
LED3_OFF;
LED4_ON;
} break;
case 5:
{
LED4_OFF;
LED5_ON;
} break;
case 6:
{
LED5_OFF;
LED4_ON;
} break;
case 7:
{
LED4_OFF;
LED3_ON;
} break;
case 8:
{
LED3_OFF;
LED2_ON;
timer1_count=0;
} break;
// case 6:
// {
// ALL_OFF;
// timer1_count=0;
// } break;
}
}
}
作者:
jemmy0938
时间:
2010-11-27 10:54
經查 <ATMEGA16单片机中文说明> 後發現 CTC 模式下比較觸發後會將 TCNT1 清零,
若此.則溢出中斷根本就不會發生了.可是網路上卻有不少範例是用 CTC 比較+溢出中斷,非常不解.
欢迎光临 珩源工控论坛 (http://bbs.hymcu.com/)
Powered by Discuz! 7.2