Tengo un ATMEGA324P que controla un circuito de controlador de motor dual. Estoy usando el contador 1 del temporizador de 16 bits en el modo correcto de fase y frecuencia para crear (2) salidas PWM utilizando el ICR1 como valor TOP y OCR1A y OCR1B para generar las señales PWM en los pines de salida. El problema persiste igual en OCR1A y OCR1B, así que he deshabilitado OCR1A para simplificar la resolución de problemas.
El problema que estoy experimentando es cuando alguna otra interrupción en el sistema se dispara, como UART o PCINT, el ciclo de trabajo PWM se invertirá. Por ejemplo, si el ciclo de trabajo se establece en 75%, se invertirá a 25% y se desplazará hacia adelante y hacia atrás cuando otras interrupciones disparen, lo que hace que la salida sea extremadamente errática. Las tomas de alcance debajo muestran la salida deseada en la parte superior y la invertida en la parte inferior. He podido activar esta inversión por UART RX ISR, ISR de interrupción de cambio de pin, y el contador de temporizador 0 y 2 Compare A & B ISR's. Por ejemplo, enviar un carácter al UART hará que se invierta.
Todoparecefuncionarenmicódigo(acontinuación),exceptoporesteproblema.Heprobadounanuevaplacadecircuitoymostróelmismocomportamientoquesugierequenoesunproblemadehardware.LoquecreoquepodríaestarsucediendoesquelainterrupciónOCR1Bseactivadealgunamaneracuandolaotrainterrupciónsedispara,loqueprovocauncambioadicionaldeOCR1Benelpindesalida.Unavezqueestosucede,siguefuncionandocomodebería,alternandoelpinperoenunestadoinvertido.Estoseilustraenelsiguientediagramadetiempo.
EsposiblequetengaalgúnerrorconmipilayqueladirecciónISRestédañada.LasdireccionesqueheprobadosemuestranacontinuaciónconlaXyladireccióndedestinoconlaflecha.Apreciocualquierayuda.
#define SS_Hi() PORTB |= _BV(4)
#define SS_Lo() PORTB &= ~ _BV(4)
#define SS_IN() (PINB&_BV(PINB4))
void init_TCNT1(void) {
// setup timer counter 1
// PWM, Phase Frequency Correct 8-bit. TOP = ICR1
TCCR1A |= _BV(WGM11);
TCCR1B |= _BV(WGM13);
TCCR1B |= _BV(CS11);
ICR1 = 40;
TIMSK1 |= _BV(OCIE1A);
// TIMSK1 |= _BV(OCIE1B);
OCR1A = 10;
OCR1B = 10;
TCNT1 = 0;
}
ISR(TIMER1_COMPA_vect) {
if ((EnA_1() != 0) && (EnB_1() != 0)) { // only if both enable pins are high
// if (PWM_PIN_1() == 0) PWMIN_1_Hi(); else PWMIN_1_Lo();
}
else PWMIN_1_Lo();
} // End Timer 1 Compare A ISR
ISR(TIMER1_COMPB_vect) {
// ISR For Motor 2
if (SS_IN() == 0) SS_Hi(); else SS_Lo();
} // End Timer 1 Compare B ISR