Search code examples
cpicmicrochip

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


Solution

  • 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;
    }
    }