【发布时间】:2017-08-29 19:10:15
【问题描述】:
我正在使用 Atmega328p-pu。我正在尝试将定时器 1 用于 16 位 PWM 以及使用溢出中断来增加定时器。我的代码如下,我还在make文件中将F_CPU设置为8000000UL。
我希望有一个变量在定义的时间内计数,然后重置并继续。到目前为止,我预计它会计数 7.5 秒。我相信我应该有一个 8 MHz 的时钟频率,然后使用带有 1 个预分频器的快速 PWM 和 5000 的 ICR1,我预计中断发生在 1600 Hz。然后我让它计数 12000 个计数。我预计这需要 7.5 秒。但我测量它大约是 57 秒。我不确定我错过了什么,也许是寄存器设置中的某些东西,但我不确定在哪里。谢谢你的帮助,
这是我认为最重要的,
// values for timer1
// WGM 13 12 11 10 is
// fast PWM 1 1 1 0
TCCR1A |= (1 << 7); // output on A pin (COM1A1)
TCCR1A |= (1 << 1); // WGM 11
TCCR1A &= ~(1 << 0); // WGM 10
TCCR1B |= (1 << 4); // WGM 13
TCCR1B |= (1 << 3); // WGM 12
//for prescaler of 1 set CS12 CS11 CS10
0 0 1
TCCR1B &= ~(1 << 2); // set prescaler to 1x CS12
TCCR1B &= ~(1 << 1); // set prescaler to 1x CS11
TCCR1B |= (1 << 0); // set prescaler to 1x CS10
TIMSK1 = 0; // enable output compare A inturrupt
TIMSK1 |= (1 << 0); // Set the Overflow inturrupt
TCNT1 = 0; // set the counter to zero on startup
ICR1 = 5000; //Set the top of the counter
OCR1A = 0; //set the duty cycle
....
ISR(TIMER1_OVF_vect){
longTimer++;
....
if (longTimer >= 12000){
longTimer = 0;
这是完整的代码
/* Light Control */
// ------- Preamble -------- //
#include <avr/io.h> /* Defines pins, ports, etc */
#include <avr/interrupt.h>
// Global variables
volatile uint8_t tick = 0;
volatile uint8_t fastTimer = 0;
volatile uint16_t longTimer = 0;
volatile uint16_t fader = 0;
volatile uint16_t dayBrightness = 0;
volatile uint8_t nightBrightness = 0;
uint8_t Day = 0;
void init(void) {
// values for push button inturrupt
EIMSK = (1 << 0);
EICRA = (1 << 1) & (1 << 0);
// values for timer1
// WGM 13 12 11 10 is
// fast PWM 1 1 1 0
TCCR1A |= (1 << 7); // output on A pin (COM1A1)
TCCR1A |= (1 << 1); // WGM 11
TCCR1A &= ~(1 << 0); // WGM 10
TCCR1B |= (1 << 4); // WGM 13
TCCR1B |= (1 << 3); // WGM 12
//for prescaler of 1 set CS12 CS11 CS10
0 0 1
TCCR1B &= ~(1 << 2); // set prescaler to 1x CS12
TCCR1B &= ~(1 << 1); // set prescaler to 1x CS11
TCCR1B |= (1 << 0); // set prescaler to 1x CS10
TIMSK1 = 0; // enable output compare A inturrupt
TIMSK1 |= (1 << 0); // Set the Overflow inturrupt
TCNT1 = 0; // set the counter to zero on startup
ICR1 = 5000; //Set the top of the counter
OCR1A = 0; //set the duty cycle
sei();
// values for IO
DDRB |= 0b00000011; /* Data Direction Register B: writing a one to the bit enables output. */
DDRD = 0x00; /* zero sets all as input */
PORTD = 0xff; /* set all inputs as pull ups */
}
ISR(INT0_vect){
//longTimer = 0;
}
ISR(TIMER1_OVF_vect){
longTimer++;
if(Day){
fader++;
}
else{
if(fader > 0){
fader--;
}
}
}
int main(void) {
init();
// ------ Event loop ------ //
while (1) {
if(Day) {
if (fader >= 5000){
OCR1A = 5000;
}
else {
OCR1A = fader;
}
}
else {
OCR1A = fader;
}
if (longTimer >= 12000){
longTimer = 0;
if(Day){
fader = 5000;
}
else{
fader = 0;
}
tick = 1;
}
if (tick == 1){
Day ^= 1;
tick = 0;
}
} /* End event loop */
return 0; /* This line is never reached */
}
【问题讨论】:
-
您还记得实际将设备编程为以 8MHz 运行吗?
-
不,我认为 atmega328 默认为 8 Mhz。只是取消设置 CKDIV8 位会使设备以 8 MHz 运行吗?感谢您的帮助,
-
假设设备正在使用内部 RC 振荡器,是的。