Señales PWM consecutivas con diferentes configuraciones de preescalador

1

Mi circuito ATtiny85 genera señales como esta en PB1 (OC0B) usando PWM rápido (preámbulo, datos de 16 bits, pulso de parada):

Tengo problemas con el pulso más a la izquierda. En este momento utilizo sentencias simples _delay_us para generarlo, pero a veces presenta fallas más tarde cerca del final de las partes de PWM (naranja y amarillo).

Me pareció inteligente cambiar al uso de los temporizadores para esta parte, pero no puedo hacer que funcione correctamente. Este es mi código:

const uint8_t JVC_MUTE = 0x71;
const uint8_t JVC_ADDRESS = 0xF1;

void setupPWM () {
//enables fast pwm, non inverting,TOP=OCR0A, prescaler 8
TCCR0A = (1<<WGM01)| (1<<WGM00)|(1<<COM0B1);
TCCR0B = (1<<WGM02)|( 1<<CS01);
}

void stopPWM () {
TCCR0A = 0;
}

/*emits a long preamble pulse
*/
void preamble(){
//enables fast pwm, non inverting, prescaler 64
TCCR0A = (1<<WGM01)| (1<<WGM00)|(1<<COM0B1);
TCCR0B = (1<<WGM02)|( 1<<CS01)|(1<<CS00);
TCNT0=0;
OCR0A=255;
OCR0B=80;
do ; while ((TIFR & 1<<OCF0B) == 0);
TIFR = 1<<OCF0B;
TCCR0A = 0;
}

/*emits 16 bit of data using fast PWM
code:16 bit data value to be send (address + command)
*/
void sendCode (uint16_t code) {
TCNT0=0;

    //padding instructions 1
OCR0A=0;
OCR0B=0;
do ; while ((TIFR & 1<<OCF0B) == 0);
TIFR = 1<<OCF0B;
    //padding instructions 2
OCR0A=0;
OCR0B=0;
    //waits while polling the OCF0B bit signaling a compare match with OCR0B
do ; while ((TIFR & 1<<OCF0B) == 0);
TIFR = 1<<OCF0B;

            //loops through each bit in the 'code' variable
            //and emits a long or short pulse depending on value
    for (uint16_t Bit=0x8000;Bit;Bit=Bit>>1){
            //if 1
        if (code & Bit) {
        OCR0A=255;
        OCR0B=80;
    }
            //if 0
    else {
        OCR0A=130;
        OCR0B=80;
    };
    do ; while ((TIFR & 1<<OCF0B) == 0);
    TIFR = 1<<OCF0B;
}
//emits a short pulse signaling the end of the transmission
OCR0A=130;
OCR0B=80;
do ; while ((TIFR & 1<<OCF0B) == 0);
TIFR = 1<<OCF0B;

}

/*
*emits a transmission (preamble pulse, 16 bit of data + end pulse)
*/
void transmit(uint8_t address,uint8_t code){
preamble();
setupPWM();//PWM settings in TCCR0A and TCCR0B
sendCode((JVC_ADDRESS<<8)+JVC_MUTE);
stopPWM();//disables PWM (TCCR0A=0)
}

Hay dos problemas:

  1. Este código generará el pulso del preámbulo la primera vez, seguido de por datos erróneos, y luego solo los datos erróneos cuando se llama
    consecutivamente.
  2. Necesita las instrucciones de relleno que agregué en sendCode (), de lo contrario, los 2 primeros bits de la transmisión siempre se cortan.

editar: la parte de datos real (partes naranja y amarilla), así como el pulso de parada al final, funcionan bien cuando se comenta la llamada a preámbulo (). El único problema es con la parte de preámbulo ().

Apreciaría cualquier ayuda, especialmente con el punto 1.

    
pregunta Polyphil

1 respuesta

0

Borre la cuenta en el prescaler cada vez que cambie la configuración del prescaler. Para el prescaler 0, el bit de restablecimiento es el bit bajo de GTCCR. Establezca, luego borre el bit de reinicio del prescaler con:

GTCCR = GTCCR | 1; GTCCR = GTCCR & 0xfe;

    
respondido por el Entrepreneur

Lea otras preguntas en las etiquetas