Search code examples
cpic

using a port as a variable in pic microcontroller


I using PIC18f45k22 and I am trying to make a thermocouple library. This library requires LATCH to be assigned as a parameter variable. This is the created code.

#define B4_LATCH LATB4
unsigned short Thermo1;

unsigned short thermal (unsigned char* Latch) {
unsigned short thermocouple;
    Latch = 0;
    thermocouple  = spiRead(0)<<8; //Read first byte
    thermocouple |= spiRead(0); //add second byte with first one
    thermocouple  = (thermocouple>>4)*0.5;
    Latch = 1;
return thermocouple;
}

void main (){
 while (1){
thermo1 = thermal (B4_LATCH);
printf ("%u" , thermo1);
}

However, I have used the same code without using it in a function and it worked.


Solution

  • You can achieve it by using indirection. If you take a look at the PIC18 headers or any PIC header in MPLAB, you will see that each register is assigned with a memory address and also they are defined with volatile qualifier like this: volatile unsigned char LATB __at(0xF8A) So the ports are accessible by using pointers while the bit fields cannot be accessed using pointers because of the nature of C lang. So one handy way to make a general modification access to a port's bits is to use macros. So let's define bit set and bit clear macros first:

    #define mBitClear(var, n) var &= ~(1 << n)
    #define mBitSet(var, n) var |= 1 << n
    

    Now that we have our generilized C style bit manipulating macros, we can pass any port and bit number as a variable, as long as the port does exist and the bit number does not exceed 7 since the ports are 8 bit wide. But note that some ports may have least bits. Now lets apply these macros to your function:

    #define B4_LATCH 4 // Define the bit number
    unsigned short Thermo1;
    
    unsigned short thermal (volatile unsigned char* Port, const unsigned char Latch) {
    unsigned short thermocouple;
        mBitClear(*Port, Latch); // Clear the bit
        thermocouple  = spiRead(0)<<8; //Read first byte
        thermocouple |= spiRead(0); //add second byte with first one
        thermocouple  = (thermocouple>>4)*0.5;
        mBitSet(*Port, Latch); // Set the bit
        return thermocouple;
    }
    
    void main (){
    
        while (1){
            thermo1 = thermal (&LATB, B4_LATCH); //< Note the indirection symbol (&) it is important
            printf ("%u" , thermo1);
        }
    }
    

    You can pass any valid port or even variable with a valid bit number by using this method. Ask me if you see something unclear.