What’s correct way to toggle a single bit and a whole register in microchip C programming

microchipmicrocontroller

I'm trying to write a code where when a push button is pressed, a whole PORT is toggled.

So I got a push button at PORT E in pin 0, and 8 leds on PORTD, I also got a debugging led on PORT E pin 1.

void main() {

     // Interrupt flags, enable global and external interrupt
     INTCON = 0x90;
     TRISE.F0 = 1;
     TRISE.F1 = 0;
     TRISD= 0x00;

     do {
        if (PORTE.F0 == 1) {
           Delay_ms(100);
           if (PORTE.F0 == 1) {
              LATD ^= 1;
              Delay_ms(1000);
             }
          }
          PORTE.F1 ^= 1;
          Delay_ms(1000);
     } while(1);

}

The problem is that neither thing happens, on push button press is not toggling port D and pin 1 on PORT E isn't blinking as it should.

Just in case I got a 18F4550 microcontroller with 20 Mhz oscillator, coding in C with mikroC IDE's compiler, I let the IDE set up all configuration bits. What have I got wrong?

Simple test.

void main() { 
  TRISD=0; 
  LATD = 0xFF;
  while(1){
    LATD=~LATD;
    Delay_ms(1000)
  } 
}

this makes the leds blink each second.

Update.

I changed the LATD toggling statement to LATD ^= 0xFF; as one answer suggests. But this made it not working. So I'm thinking that definitely the issue about the button push detection statements.

This is how setup bits are set:

enter image description here

Best Answer

I see many issues with your code that would likely cause you grief.

Firstly (I dont think this is your main issue), you enable interrupts but have no function to catch them. If an interrupt were to occur, your PIC would likely reset (undefined behavior).

Secondly, when you try to toggle your LATD, you are in fact togling just the lowest bit. When you enter the literal 1, the compiler interprets it as 0x01. If you want to toggle the whole byte, you should xor with 0xFF (255) instead.

Thirdly, you dont seem to set your configuration bits anywhere nor do you configure your oscillator. Without setting these values, you may have a chip running at a very low speed and your Delay might be longer than you expect (you have not provided their definition ether so I cant confirm or deny this hypothesis).

EDIT: I looked into this more and i believe I have found your main issue. If you look at the pinout in the specification sheet for this PIC, you will find that pin RE0 shares a physical pin with an analog input. The default state in PIC micro-controllers is for the analog input to override the digital input. You have to disable the analog input through the ADCON1 register to be able to get digital input (see test code below).

As you seem to have determined that your oscillator is running, I suggest next testing if you can read the button correctly :

void main(){
    TRISD=0;
    ADCON1 = 0x0F;
    LATD =0;
    while(1) LATD = (PORTE & 0x01) ? 0xff : 0x00;
}

You should see your LEDs follow the logic level of your switch.