I'm working on a 433MHz RF reciver code for a PIC16F628A using a cheap 433MHz receiver. The catch here is that I'm only able to use RA4 for the RX, and because of that i had to use timer2 (because the other timers are already i use). I'm almost done with having it completely functional, but there is something that is breaking all my code, and I cant figure out why. The issue is on the ISR:
typedef union {
uint8_t REG;
struct {
unsigned RX : 1; // Bit de estado de pin Rx
unsigned RXp : 1; // Bit de estado previo de pin Rx
unsigned DONE : 1; // Bit de fin de recepcion
unsigned MTCH : 1; // Bit de control conocido
unsigned CH1 : 1; // Bit de canal 1
unsigned CH2 : 1; // Bit de canal 2
unsigned GRB : 1;
} REGbits;
} customRFREG;
volatile customRFREG RFREGu; // Registro de modulo RF 433MHz
#define RFREG RFREGu.REG
#define RFREGbits RFREGu.REGbits
int8_t RXc = 0; // Cuenta de pulsos
uint32_t rcvd_key = 0; // Registro de recepcion
uint32_t key_db[10] = {0b10010110100101101010, 0b10011000010110001000, 0x0AEAEA, 0x0AEAEA, 0x0AEAEA, 0x0AEAEA, 0x0AEAEA, 0x0AEAEA, 0x0AEAEA, 0x0AEAEA};
void main(void) {
TRISA = 0x10;
TRISB = 0x00;
PORTA = 0x00;
PORTB = 0x00;
RFREG = 0x00;
INTCON = 0xC0;
PIE1 = 0x02;
T2CON = 0x00;
PR2 = 111;
while (1) {
if (PORTAbits.RA4 && !T2CONbits.TMR2ON && !RFREGbits.MTCH) {
T2CONbits.TMR2ON = 1;
}
if (RFREGbits.DONE) {
RFREGbits.RX = RXc = 0;
RFREGbits.DONE = T2CONbits.TMR2ON = 0;
RFREGbits.RXp = 0;
for (int i = 0; i < 10; i++){
if(key_db[i] == (rcvd_key >> 8)){
rcvd_key = (rcvd_key - (key_db[i] << 8)) >> 4;
RFREGbits.MTCH = 1;
break;
}
}
if (!RFREGbits.MTCH){
rcvd_key = 0;
}
}
if (RFREGbits.MTCH){
switch (rcvd_key){
case 13:
RFREGbits.CH1 = !RFREGbits.CH1;
break;
case 14:
RFREGbits.CH2 = !RFREGbits.CH2;
break;
}
PORTAbits.RA1 = RFREGbits.CH1;
PORTAbits.RA2 = RFREGbits.CH2;
RFREGbits.MTCH = rcvd_key = 0;
__delay_ms(1000);
}
}
return;
}
void __interrupt() isr() {
if (PIR1bits.TMR2IF) {
RFREGbits.RX = PORTAbits.RA4;
if (!RFREGbits.RX) {
if (RFREGbits.RXp) {
rcvd_key <<= 1;
if (RXc > 0) {
rcvd_key |= 1;
PORTBbits.RB4 = 1;
} else {
PORTBbits.RB4 = 0;
RXc = 0;
}
RXc--;
PORTBbits.RB3 = 0;
} else {
RXc++;
PORTBbits.RB3 = 1;
}
if (RXc < -20){
RFREGbits.DONE = 1;
T2CONbits.TMR2ON = 0;
}
RFREGbits.RXp = RFREGbits.RX;
PORTBbits.RB5 = !PORTBbits.RB5;
//RFREGbits.GRB = !RFREGbits.GRB;
PIR1bits.TMR2IF = 0;
}
}
As is, the code works perfec (except for the PORTAbits.RA1 = RFREGbits.CH1;, it turns on for a split second and then gets turned off). The thing is that I need RB3, RB4 and RB5 for other things. Removing RB3 and RB4 produces no changes on the functionality of the code, and it still works perfectly fine, but when I remove RB5, everything stops working.
Here is a graph of the outputs with RB5:
And here is one without RB5:
As you can see, the decodification when ther is no RB5 is ok up until it stops (on the wrong place).
I have found no explanation on why this happens. I've tried to replace the PORTBbits.RB5 = !PORTBbits.RB5; with RFREGbits.GRB = !RFREGbits.GRB;, but still, the decodification was totally off. I've also tried to take a look at the (of what I think is) generated assembly code to see if I might be able to find a bug (with no knoweldge on assembly):
983 ;newmain.c: 126: PORTBbits.RB5 = !PORTBbits.RB5;
984 019E 1003 clrc
985 019F 1283 bcf 3,5 ;RP0=0, select bank0
986 01A0 1303 bcf 3,6 ;RP1=0, select bank0
987 01A1 1E86 btfss 6,5 ;volatile
988 01A2 1403 setc
989 01A3 1803 btfsc 3,0
990 01A4 29A6 goto u33_21
991 01A5 29AA goto u33_20
992 01A6 u33_21:
993 01A6 1283 bcf 3,5 ;RP0=0, select bank0
994 01A7 1303 bcf 3,6 ;RP1=0, select bank0
995 01A8 1686 bsf 6,5 ;volatile
996 01A9 29AD goto u34_24
997 01AA u33_20:
998 01AA 1283 bcf 3,5 ;RP0=0, select bank0
999 01AB 1303 bcf 3,6 ;RP1=0, select bank0
1000 01AC 1286 bcf 6,5 ;volatile
1001 01AD u34_24:
982 ;newmain.c: 126: RFREGu.REGbits.GRB = !RFREGu.REGbits.GRB;
983 019E 1003 clrc
984 019F 1F75 btfss _RFREGu,6 ;volatile
985 01A0 1403 setc
986 01A1 1803 btfsc 3,0
987 01A2 29A4 goto u33_21
988 01A3 29A6 goto u33_20
989 01A4 u33_21:
990 01A4 1775 bsf _RFREGu,6 ;volatile
991 01A5 29A7 goto u34_24
992 01A6 u33_20:
993 01A6 1375 bcf _RFREGu,6 ;volatile
994 01A7 u34_24:
995 01A7 i1l757:
As you can see, the only difference (appart from the variables) are those extra bcf 3,5 and bcf 3,6, wich I think they select the PORTB register and do something???
One of the weird things is that the PORTBbits.RB5 = !PORTBbits.RB5; shouldn't affect anything related to time or the ISR execution itself. Another thing, that i just did for testing, is replace the RB5 with another pin. I even changed port, but even that broke the code. What didnt broke the code was changing where the pin state is altered. I tried inside the ISR and in the while(1), and that did not affect the functionality of the code. I'm starting to think that it could be some kind of bug with the uC itself, but I don't really know
PIR1bits.TMR2IF = 0;higher in the interrupt (perhaps as the first thing afterif (PIR1bits.TMR2IF). – Ben Voigt Jul 25 '23 at 19:44