En este momento estoy tratando de generar una señal PWM usando timer1, pero es un error lamentable.
Estoy usando esta biblioteca disponible desde arduino para conectar el timer1.
El código que estoy ejecutando es este
#include "test.h"
volatile int step_count = 1;
test::test()
{
pinMode(10,OUTPUT);
Timer1.initialize(20);
Timer1.attachInterrupt(callback);
}
static void test::callback()
{
}
void test::test_pwm()
{
Serial.print("period: ");
Serial.println(period_used);
Serial.print('\n');
Serial.print("value: ");
Serial.print(value);
Serial.print('\n');
Timer1.pwm(10, (50.0 / 100) * 1023);
}
El constructor inicializa el temporizador.
void TimerOne::initialize(long microseconds)
{
TCCR1A = 0; // clear control register A
TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
setPeriod(microseconds);
}
SetPeriod()
debe ser uno que determine la frecuencia de la PWM
void TimerOne::setPeriod(long microseconds) // AR modified for atomic access
{
long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
oldSREG = SREG;
cli(); // Disable interrupts for 16 bit register access
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
SREG = oldSREG;
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock
}
No veo nada malo en la forma en que se implementó, pero estoy bastante seguro de que algo debe estar mal aquí, pero no puedo averiguar dónde está el error.
Y la función pwm está codificada aquí:
void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024)
{
if(microseconds > 0) setPeriod(microseconds);
if(pin == 1 || pin == 9) {
DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin
TCCR1A |= _BV(COM1A1); // activates the output pin
}
else if(pin == 2 || pin == 10) {
DDRB |= _BV(PORTB2);
TCCR1A |= _BV(COM1B1);
}
setPwmDuty(pin, duty);
resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM
// and the first one is in the middle of a cycle
}
el problema aquí es que no puedo crear una señal PWM que no tenga una frecuencia mayor o menor a 490 hz. Si intenta cambiar el valor, se inicializa el ciclo de trabajo, en lugar de la frecuencia ... ¿Qué podría estar mal aquí?
Molesto por la biblioteca, comencé a configurar las cosas manualmente
Aquí está el código. Debería crear una interrupción cada 1 hz, en la que se alterna el estado del pin. La frecuencia del cambio de pin se produce a 490 hz.
#include "test.h"
test::test()
{
pinMode(10,OUTPUT);
//Timer1 setup1 Interrup at 1hz
cli(); // Stop interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15624; // Compare register value = cpu_fre/(interrupt_freq*prescaler)-1 (must be <65536)
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12) | (1 << CS10);
TIMSK1 |= (1 << OCIE1A);
sei(); //allow interrupts
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(10,!digitalRead(10));
}