Код для генерации импульсов ШИМ в AtMega32U4 - PullRequest
0 голосов
/ 20 декабря 2018

Итак, вот моя настоящая проблема, мне нужно контролировать напряжение полевого транзистора с помощью ШИМ-контакта от ATMEGA32U4.Есть два сигнала.Один сигнал включает и выключает светодиод, включается на 1 мс (1 МГц) и выключается на 0,1 мс.Вторым сигналом является ШИМ, который я хочу, чтобы он имел частоту 50 кГц с разрешением 30 из этих импульсов в течение этого периода времени 50 кГц в течение времени включения 1 мс.Надеюсь, что это имеет смысл.AtMega работает с тактовой частотой 16 МГц.

Так что я использую два таймера, один таймер использует прерывания для управления светодиодом, а другой контролирует сигнал ШИМ, который поступает на FET.

Я быдействительно ценю помощь.

Я до сих пор придумал это.пожалуйста, ведите меня.

#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)
{
}
}

Ответы [ 2 ]

0 голосов
/ 03 января 2019
#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)
{
}
}
0 голосов
/ 20 декабря 2018

Вот пример того, как использовать таймеры в зависимости от ваших требований.В основном он использует два таймера, которые оба подключены к выходным контактам для генерации ШИМ.Один из них дополнительно запускает прерывания для включения и выключения другого таймера.

Из кода, который вы дали, невозможно включить светодиод ровно на 1 мс.Вы подключили его к 8-битному таймеру, и нет комбинации часового делителя и значения сравнения, которое дает ровно 1 мс.Вместо этого вы должны подключить свой светодиод к 16-битному таймеру / счетчику 1.

ПРИМЕЧАНИЕ. У меня нет 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...