所以这是我的实际问题,我需要使用ATMEGA32U4的PWM引脚控制FET的电压。有两个信号。一个信号打开和关闭LED,打开1ms(1MHz),然后关闭0.1ms。第二个信号是一个PWM,我希望它是50kHZ的频率,在1ms导通时间内在那个50kHz的时间段内具有30个这些脉冲的分辨率。希望有道理。 AtMega以16MHz时钟运行。
所以我正在使用两个定时器,一个定时器使用中断来控制LED,另一个定时器控制发送到FET的PWM信号。
我非常感谢您的帮助。
到目前为止,我已经提出了这个建议。请引导我。
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
uint8_t tot_overflow;
void timer1_init()
{
TCCR1A |= (1 << CS01); // set up timer with prescaler = 8
TCNT1 = 0;
TIMSK1 |= (1 << TOIE1);
sei();
tot_overflow = 0;
}
ISR(TIMER1_OVF_vect)
{
tot_overflow++;
}
int main(void)
{
DDRD |= (1 << 0); //set Port D
timer1_init();
while(1)
{
if (tot_overflow >= 250)
{
PORTD ^= (1 << 0); // toggles the led
TCNT1 = 0; // reset the counter
tot_overflow = 0; // reset the overflow counter
}
}
}
void pwm_init()
{
DDRB = 1<<6; // Generate 30kHz PWM signal on PB6
TC4H = (319) >> 8; // Set TOP, write upper bits first.
OCR4B = (319) & 0xFF;
TCCR4A = (1<<COM4A1) | (1<<PWM4A);
TCCR4B = (1<<CS40); // Start timer
TC4H = (320) >> 8; // Set 100% duty cycle
OCR4A = (320) & 0xFF;
while(1)
{
}
}
答案 0 :(得分:1)
以下是根据您的要求使用计时器的示例。它基本上使用两个定时器,这两个定时器都连接到输出引脚以产生PWM。其中一个额外触发中断以打开和关闭另一个计时器。
根据您提供的代码,您无法在1ms内完全打开LED。您将其连接到8位定时器,并且没有时钟分频器和比较值的组合(精确地为1ms)。您应该将LED连接到16位Timer / Counter1。
注意:我手头没有32u4,因此无法在真实的硬件上进行测试。考虑该代码“正在进行中”和越野车。
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
void timer1_init()
{
OCR0A = 69; // Set TOP (maximum value that counter counts to)
OCR0B = 63; // Set duty cycle to ~10/11
// Trigger interrupts when comparison is reached and at top
TIMSK0 = (1 << OCIE0B) | ( 1 << TOIE0);
// Set fast PWM on OC0B, turn pin low when counter reaches OCR0B
TCCR0A = (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
// Set fast PWM on OC0B, start timer with prescaler of 256
TCCR0B = (1 << WGM02) | (1 << CS01);
}
void pwm_init()
{
TC4H = (320) >> 8; // Set TOP (maximum value that counter counts to)
OCR4C = (320) & 0xFF;
TC4H = (160) >> 8; // Set 50% duty cycle
OCR4B = (160) & 0xFF;
TCCR4A = (1<<COM4B1) | (1<<PWM4B); // Set fast PWM on OC4B
}
// This ISR is called when the timer reaches the top value
ISR(TIMER0_OVF_vect)
{
// Turn on PWM
TCCR4B = (1 << CS40);
}
// This ISR is called when the timer reaches the compare value
ISR(TIMER0_COMPB_vect)
{
// Turn off PWM
TCCR4B = 0;
}
int main(void)
{
DDRD = (1 << 0); // Set pin PD0 as output (LED)
DDRB = (1 << 6); // Set pin PB6 as output (FET)
pwm_init();
timer1_init();
sei();
}
答案 1 :(得分:0)
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
void timer1_init()
{
OCR1A = 319; // Set TOP (maximum value that counter counts to)
OCR1B = 290; // Set duty cycle to ~10/11
// Trigger interrupts when comparison is reached and at top
TIMSK1 = (1 << OCIE1B) | ( 1 << TOIE1);
// Set fast PWM on OC0B, turn pin low when counter reaches OCR0B
TCCR1A = (1 << COM1B1) | (1 << WGM11) | (1 << WGM10);
// Set fast PWM on OC0B, start timer with prescaler of 8
TCCR1B = (1 << WGM12) | (1 << CS11);
}
// This ISR is called when the timer reaches the top value
ISR(TIMER1_OVF_vect)
{
// Turn on PWM
TCCR1B = (1 << CS10);
}
// This ISR is called when the timer reaches the compare value
ISR(TIMER1_COMPB_vect)
{
// Turn off PWM
TCCR1B = 0;
}
void pwm_init()
{
//define PC6 as output
DDRC |= (1 << 6);
//drive pins low
PORTC = 0x00;
//max counter value (50kHz)
ICR3 = 0x14;
//set duty to half
OCR3A = 0x0A;
//compare output mode:
TCCR3A = (1 << COM3A0) | (0 << COM3A0) | (0 << WGM31) | (0 << WGM30);
//prescaler/start timer:
TCCR3A = (1 << WGM33) | (0 << WGM12) | (0 << CS32) | (0 << CS31) | (1 << CS30);
}
int main(void)
{
timer1_init();
pwm_init();
while(1)
{
}
}