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:
- 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. - 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.