avr timer1 16 位快速 PWM
avr timer1 16bit fast PWM
我正在使用 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 */
}
每当我使用内部振荡器并且事情 运行 快 (8x) 或慢 (8x) 时,我都会检查 CKDIV8 位设置。几乎总是那是罪魁祸首。
如果使用外部振荡器或时钟,奇怪的时序通常是由于未在保险丝设置中切换外部时钟,或者 F_CPU 设置与实际频率不同。
另外,有点跑题了,但是这样的代码是多余的:
TCCR1B &= ~(1 << 2); // set prescaler to 1x CS12
TCCR1B &= ~(1 << 1); // set prescaler to 1x CS11
默认情况下,这些位为零,因此没有理由清除它们,除非您在学习时为了清楚起见。
我正在使用 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 */
}
每当我使用内部振荡器并且事情 运行 快 (8x) 或慢 (8x) 时,我都会检查 CKDIV8 位设置。几乎总是那是罪魁祸首。
如果使用外部振荡器或时钟,奇怪的时序通常是由于未在保险丝设置中切换外部时钟,或者 F_CPU 设置与实际频率不同。
另外,有点跑题了,但是这样的代码是多余的:
TCCR1B &= ~(1 << 2); // set prescaler to 1x CS12
TCCR1B &= ~(1 << 1); // set prescaler to 1x CS11
默认情况下,这些位为零,因此没有理由清除它们,除非您在学习时为了清楚起见。