EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: PerranOak on October 07, 2020, 04:38:10 pm

Title: C nibble problem
Post by: PerranOak on October 07, 2020, 04:38:10 pm
I am running this simple programme on a PIC12F683:

Code: [Select]
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000

#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

void main(void)
{
    TRISIO = 0;                   
   
    int count = 0;
    int temp = 0;
   
    while(count < 16)
    {
        GPIO = count;
        temp = count;
        GPIObits.GP4 = temp >> 3 & 1;        //because GP3 is input only
                 
        __delay_ms(500);
        count++;
    }
 
}

I have LEDs attached to the GPIO pins 4 and 2-0 because GPIO3 is input only. So, I write "count" to the GPIO register then right-shift it three times (via "temp") then "AND" it with b00000001 to get the digit that should be in position 3 and write it to GPIO4 where the final LED is connected.

I doesn't work. It looks like the lower 3 LEDs count and light very quickly (almost invisible) then GPIO4 lights normally for 500ms and the process repeats. It's as if it is ignoring the "delay" command when displaying the lower three.

If I comment out the "GPIObits, etc." line then it works perfectly with the LEDs lighting for the 500ms and counting as expected, of course GPIO4 doesn't light.

What can I be doing wrong?

Cheers.
Title: Re: C nibble problem
Post by: KrudyZ on October 07, 2020, 05:08:01 pm
I would assemble the word in one go.

GPIO = (count & 0x07) | ((count << 1) & 0x10);

There are more parentheses than are strictly needed, but better be clear than getting bitten by operator precedence.
Title: Re: C nibble problem
Post by: oPossum on October 07, 2020, 05:53:22 pm
Turn off all analog features. They can interfere with RMW (read-modify-write) operations.

Code: [Select]
GPIObits.GP4 = temp >> 3 & 1;   // This does RMW

Code: [Select]
// Turn off analog stuff
CMCON0 = 7;
ANSEL = 0;


Title: Re: C nibble problem
Post by: PerranOak on October 08, 2020, 10:19:37 am
Thank you oPossum this solved it. I am ashamed that I didn't remember ANSEL but I would never have thought of turning off the comparator.

KrudyZ: cheers - my code is a lot slicker now.