Juan Luis Juan Luis - 1 month ago 8
C Question

Microchip PIC led flash OR operation rare behaviour

I am new with Microchip PIC uC. I have some experience with AVR's but some weeks ago I decided to learn about PICs.

Well, the problem is the following. I am trying to do my first program with 2 flashing leds, it is very simply. RA1 and RA2 flash.

When I type the code 1 and code 2, the program works perfectly.
Code 1: Works ok.

//Code 1. OK.

main(){

while(1){
__delay_ms(1000); //wait 1 second
PORTA |= 0b00000110; //RA1 & RA2 on
__delay_ms(1000); //wait 1 second
PORTA &= 0b00000000; //RA1 & RA2 off
}
}


Code 2: Works ok.

//Code 2. OK

main(){

while(1){
__delay_ms(1000); //wait 1 second
PORTA |= (1 << 1) | (1 << 2); //RA1 & RA2 on
__delay_ms(1000); //wait 1 second
PORTA &= ~(1 << 1) & ~(1 << 2); //RA1 & RA2 off
}
}


Code 3: This code doesn't work. Only 1 led flash. I use this with AVR and the code works perfectly. What is the problem? OR operation should not affect the RA1 operation.

//Code 3. Don't work. Only RA2 flash.

main(){

while(1){
__delay_ms(1000); //wait 1 second
PORTA |= (1 << 1); //RA1 on
PORTA |= (1 << 2); //RA2 on

__delay_ms(1000); //wait 1 second
PORTA &= ~(1 << 1); //RA1 off
PORTA &= ~(1 << 2); //RA2 off
}
}


Thank you very much for your help.

Best regards

Answer

PIC I/O registers use read-modify-write. In some cases this may cause it to re-read voltage from the pins instead of the logical value you expected in your program. This is especially true if the output pin has some capacitance that cause it to change value slower than what the sequence of instructions is telling it to do to the pin.

In your case the third case is trying to modify the pins on PORTA very quickly in succession. This may cause the second value to latch the actual voltage on the output instead of what you intended with your code.

In such cases you need to use a variable to shadow the PORTA register:

main(){

unsigned char output = 0;

while(1){
  __delay_ms(1000); //wait 1 second
  output |= (1 << 1); //RA1 on 
  PORTA = output;
  output |= (1 << 2); //RA2 on 
  PORTA = output;

  __delay_ms(1000); //wait 1 second
  output &= ~(1 << 1); //RA1 off
  PORTA = output;
  output &= ~(1 << 2); //RA2 off
  PORTA = output;
}
}
Comments