Author Topic: PIC18, XC8 and returning pointers to registers ?  (Read 1684 times)

0 Members and 1 Guest are viewing this topic.

Offline smoothVTerTopic starter

  • Regular Contributor
  • *
  • Posts: 151
  • Country: us
PIC18, XC8 and returning pointers to registers ?
« on: November 02, 2016, 08:04:19 pm »
I am a level 4 out of 100 in C programming, so please bear with me, this may be an XY problem.    I'm using a PIC18F25  with MPLAB X and the free version of XC8 compiler.

Goal:   Sequentially turn on/off   16  LEDs   attached to various arbitrarily assigned PORTA/B/C  pins.

In my main.h I've defined the following to achieve the LED-Pin mapping:
Code: [Select]
#define LED_0      LATCbits.LC7 //RC7
#define LED_1               LATCbits.LC5 //RC5
#define LED_2               LATAbits.LA3 //RA3
#define LED_3               LATCbits.LC3 //RC3
#define LED_4               LATBbits.LB7 //RB7           
#define LED_5               LATAbits.LA0 //RA0
#define LED_6               LATCbits.LC6 //RC6
#define LED_7               LATCbits.LC4 //RC4
#define LED_8               LATBbits.LB5 //RB5
#define LED_9               LATAbits.LA2 //RA2
#define LED_10              LATBbits.LB6 //RB6
#define LED_11              LATAbits.LA1 //RA1
#define LED_12              LATCbits.LC2 //RC2
#define LED_13              LATCbits.LC1 //RC1
#define LED_14              LATBbits.LB4 //RB4
#define LED_15              LATCbits.LC0 //RC0

So now in main.c I can turn on/off each mapped LED using the  LED_x  macros easily:

Code: [Select]
LED_0 = 1;
delay_s(0.25);
LED_0 = 0;
LED_1 = 1;
delay_s(0.25);
LED_1=0;
LED_2=1;
 // etc.
 // etc.

I don't want to explicitly use LED_0, LED_1, LED_x  every single time in my main.c;  I want something more elegant that I can loop through and modify in arbitrary fashion.    I thought of writing a function which takes a char as a parameter ( with values 0-15 ) and returns a pointer to the appropriate port/pin, by using the 'friendly name' of that port/pin.    These friendly names are in the PIC18f25xxx.h header file, and the LATxbits are defined as volatile unsigned chars:

Code: [Select]
// This is from inside PIC18F25xxx.h:
// Register: LATA
extern volatile unsigned char           LATA                @ 0xF89;
#ifndef _LIB_BUILD
asm("LATA equ 0F89h");
#endif
// bitfield definitions
typedef union {
    struct {
        unsigned LATA0                  :1;
        unsigned LATA1                  :1;
        unsigned LATA2                  :1;
        unsigned LATA3                  :1;
        unsigned                        :1;
        unsigned LATA5                  :1;
    };
    struct {
        unsigned LA0                    :1;
    };
    struct {
        unsigned                        :1;
        unsigned LA1                    :1;
    };
    struct {
        unsigned                        :2;
        unsigned LA2                    :1;
    };
    struct {
        unsigned                        :3;
        unsigned LA3                    :1;
    };
    struct {
        unsigned                        :5;
        unsigned LA5                    :1;
    };
} LATAbits_t;
extern volatile LATAbits_t LATAbits @ 0xF89;

So I wrote my function with the same return type:

Code: [Select]
volatile unsigned char * getLATptr( unsigned char ledIdx ){

    switch( ledIdx ){
        case 0: return &LATCbits.LC7;
        case 1: return &LATCbits.LC5;
        case 2: return &LATAbits.LA3;
        case 3: return &LATCbits.LC3;
        case 4: return &LATBbits.LB7;
        case 5: return &LATAbits.LA0;
        case 6: return &LATCbits.LC6;
        case 7: return &LATCbits.LC4;
        case 8: return &LATBbits.LB5;
        case 9: return &LATAbits.LA2;
        case 10: return &LATBbits.LB6;
        case 11: return &LATAbits.LA1;
        case 12: return &LATCbits.LC2;
        case 13: return &LATCbits.LC1;
        case 14: return &LATBbits.LB4;
        case 15: return &LATCbits.LC0;                         
    }//switch   
    return;
}

The point being that I simply give an index value ( 0 -15 ) and this function returns a pointer to the friendly-named register.   Then in main.c I attempt to call this function to turn on LED_9:

Code: [Select]
*(getLATptr(9)) = 1;

I'm getting the compiler error:    main.c:81: error:  (712) can't generate code for this expression

So:   Can anybody enlighten me as to why the compiler cannot generate this code? 
Is there something fundamentally wrong with my understanding of C here?   Is it an XC8 compiler specific issue?
Or am I approaching the problem from an inherently over-complicated way  ( this is my guess! )

Thanks for reading, cheers     :popcorn:

 

Online edavid

  • Super Contributor
  • ***
  • Posts: 3418
  • Country: us
Re: PIC18, XC8 and returning pointers to registers ?
« Reply #1 on: November 02, 2016, 08:14:27 pm »
Bitfields don't have addresses, so you can't use the address operator on them.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf