Functions to operate a 7 Segment display on a PIC Controller

Thread Starter

Travm

Joined Aug 16, 2016
363
About 3 years ago i was working on a project that needed a 7 segment display. At that time i was just learning PIC 8-bit mcu's, MPLABX, XC8 and C in general. A lot at once. I put a Mock up of what I wanted together and wrote some code. Took me a few weeks but I had it working.
I used MCC, and the code was generated across 4-5 files. Below I'll try to pull all the related code out of each file so that I'm not uploading 20 pages of code for what could have been much simpler.

At the time I thought the 7 segment code could be portable.
The mock up used a PIC16F1564, and the hardware was entirely my own design on a protoboard. It mostly worked as expected.

Fast forward to today, I'm trying to make a small timer for my Son who is making a board game. I thought I would try a PIC16F54, mainly because it was cheap, and also i'd never used an external crystal in a project, so more to learn, perfect.

I've built the hardware, and the hardware works. I can display any number I want, and the multiplexing works perfectly.
I dont have a schematic to show, because I drew up the schematic in KICAD, then printed it, and by the time I was finished building and testing the hardware, it changed a little. I could change the KICAD files and I will if someone here thinks they need to see my schematic. But i'm pretty sure this is a programming issue.
I've taken my functional code and pasted it into my new program. It wont compile.

Code from Working Board (PIC16F1564)

C:
//snippet from pin_manager.h

#define SEG7A_SetHigh()            do { LATCbits.LATC1 = 1; } while(0)
#define SEG7A_SetLow()             do { LATCbits.LATC1 = 0; } while(0)
#define SEG7G_SetHigh()            do { LATCbits.LATC0 = 1; } while(0)
#define SEG7G_SetLow()             do { LATCbits.LATC0 = 0; } while(0)
#define SEG7F_SetHigh()            do { LATAbits.LATA2 = 1; } while(0)
#define SEG7F_SetLow()             do { LATAbits.LATA2 = 0; } while(0)
#define SEG7D_SetHigh()            do { LATAbits.LATA1 = 1; } while(0)
#define SEG7D_SetLow()             do { LATAbits.LATA1 = 0; } while(0)
#define SEG7E_SetHigh()            do { LATAbits.LATA0 = 1; } while(0)
#define SEG7E_SetLow()             do { LATAbits.LATA0 = 0; } while(0)
#define SEG7B_SetHigh()            do { LATCbits.LATC4 = 1; } while(0)
#define SEG7B_SetLow()             do { LATCbits.LATC4 = 0; } while(0)
#define SEG7C_SetHigh()            do { LATCbits.LATC2 = 1; } while(0)
#define SEG7C_SetLow()             do { LATCbits.LATC2 = 0; } while(0)

void seg7set0(); // following 11 functions are prototypes for each 7-seg setting called in pin_manager.c
void seg7set1();
void seg7set2();
void seg7set3();
void seg7set4();
void seg7set5();
void seg7set6();
void seg7set7();
void seg7set8();
void seg7set9();
void seg7setclear();



//snippet from pin_manager.c
void seg7set0()
{   
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetLow();
    SEG7F_SetLow();
    SEG7G_SetHigh();
  }
void seg7set3() // establish function for activating #3 on 7-seg
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetHigh();
    SEG7F_SetHigh();
    SEG7G_SetLow();
    
}
void seg7set1()     // establish function for activating #1 on 7-seg
{
    SEG7A_SetHigh();
       SEG7B_SetLow();
       SEG7C_SetLow();
       SEG7D_SetHigh();
       SEG7E_SetHigh();
       SEG7F_SetHigh();
       SEG7G_SetHigh();
}

void seg7set2()      // function for activating #2 on 7-seg
{
    SEG7A_SetLow();
       SEG7B_SetLow();
       SEG7C_SetHigh();
       SEG7D_SetLow();
       SEG7E_SetLow();
       SEG7F_SetHigh();
       SEG7G_SetLow();
}
void seg7set4()
{
    SEG7A_SetHigh();
       SEG7B_SetLow();
       SEG7C_SetLow();
       SEG7D_SetHigh();
       SEG7E_SetHigh();
       SEG7F_SetLow();
       SEG7G_SetLow();
}
void seg7set5()
{
       SEG7A_SetLow();
       SEG7B_SetHigh();
       SEG7C_SetLow();
       SEG7D_SetLow();
       SEG7E_SetHigh();
       SEG7F_SetLow();
       SEG7G_SetLow();
}
void seg7set6()
{
    SEG7A_SetLow();
    SEG7B_SetHigh();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetLow();
    SEG7F_SetLow();
    SEG7G_SetLow();
}
void seg7set7()
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetHigh();
    SEG7E_SetHigh();
    SEG7F_SetHigh();
    SEG7G_SetHigh();
}
void seg7set8()
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetLow();
    SEG7F_SetLow();
    SEG7G_SetLow();
}
void seg7set9()
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetHigh();
    SEG7F_SetLow();
    SEG7G_SetLow();
}
void seg7setclear()
{
    SEG7A_SetHigh();
    SEG7B_SetHigh();
    SEG7C_SetHigh();
    SEG7D_SetHigh();
    SEG7E_SetHigh();
    SEG7F_SetHigh();
    SEG7G_SetHigh();
}


//main.c  I've put the entire main.c code here, just in case the reasoning for "why i did something" one way or the other is present.

void main(void)
{
    // initialize the device
    SYSTEM_Initialize();

    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();

  
   void (*seg7set[11])(); // array to hold pointers for each 7 segment vaule
   seg7set[0] = seg7set0;
   seg7set[1] = seg7set1; // calling the functions defined in pin_manager.h for each 7 segment value
   seg7set[2] = seg7set2;
   seg7set[3] = seg7set3;
   seg7set[4] = seg7set4;
   seg7set[5] = seg7set5;
   seg7set[6] = seg7set6;
   seg7set[7] = seg7set7;
   seg7set[8] = seg7set8;
   seg7set[9] = seg7set9;
   seg7set[10]= seg7setclear;
   unsigned int DutyCycle;  // duty cycle of power circuit
   int p;  // p will be the 7-segment value
   unsigned int PrevResult; // previous result of power current reading
   char ADCsel=2;  // flip flop for selection of ADC channel
   unsigned int current; // current power of circuit
   char ADCsw; // flip flop for determining if ADC channel should be switched
   int displaysw; // flip flop for switching digit display
    
   while (1)
    {
       // Add your application code
        if (ADCclk>520) // number here sets the sample rate, consider reducing the number to account for the time
        {
             ADCON0bits.GO = 1;
           // PrevResult = ((ADRESH << 8) + ADRESL); 
            if (ConversionComplete==1) // read the pot which is the setting, this variable declared in ADC1.c
               {
                    if (ADCsel==1) // set to read DutyCycle
                        {
                            DutyCycle = ((ADRESH << 8) + ADRESL);  // get the value from the ADC and set it to DutyCycle
                            ADCsw=1; // Toggle the ADC switch
                            
                            ADCON0bits.CHS = channel_AN7; // Set ADC channel to read Pot
                            ConversionComplete = 0;
                            ADCclk=0; // reset ConversionComplete and ADCclk
                        }
                        if (ADCsel==2)  // sets ADC channel to read current feedback circuit
                        {               
                        current = ((ADRESH << 8) + ADRESL); // get the value from the ADC and set it to current.
                        ADCsw=1;
                         // toggle ADC selector to read current
                        ADCON0bits.CHS = channel_AN3; // Set ADC channel to read Current
                        ConversionComplete = 0;
                        ADCclk=0;   
                        }
                    if(ADCsw==1)
                    {
                        if(ADCsel==1) // if ADCsel is set to read pot, switch to read current and toggle the switch
                        {
                            ADCsel=2;
                            ADCsw=0;     
                        }
                    }
                    if(ADCsw==1)
                    {
                        if(ADCsel==2) // if ADCsel is set to read current, switch to read pot and toggle the switch
                        {
                            ADCsel=1;
                            ADCsw=0;
                        }
                    }
            }
        }
    if (digitsel>1)
   {
       seg7set[10](); // clear 7 segment display to prevent ghosting
       if (IO_RA5_PORT==1)
      {
          IO_RA5_SetLow();
          p=(current*10 / 1024);  //get tens value from adc reading
          seg7set[p]();
      }
      else if (IO_RA5_PORT==0)
      {
              IO_RA5_SetHigh();
              p=((current*25 / 256)%10); //get ones value from adc reading
              seg7set[p]();
      }
       digitsel=0;
   }
        
    PWM1DCL = DutyCycle;
    PWM1DCH = (DutyCycle >> 8);
    PWM1LDCON = 0x80;
   // p = (current*10 / 1024); //Multiplying current by 10, so that integer math works, and gives an integer value between 0 and 9.  Needs adjustment yet for proper rounding (add one half of a point)
      //p is the value to display on 7 segment display
    //seg7set[p](); // calling the 7 segment value specified by p

  

   }
  
}


Entire Program from Timer. This wont compile, only since I've added the code relating to the 7 segment. It specifically chokes on the function pointer array. I've highlighted it below.

Code:
/*
 * File:   Main1.c
 * Author: Travis
 *
 * Created on May 18, 2020, 1:30 PM
 */
// CONFIG
#pragma config OSC = XT         // Oscillator selection bits (RC oscillator)
#pragma config WDT = OFF         // Watchdog timer enable bit (WDT enabled)
#pragma config CP = OFF         // Code protection bit (Code protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#define _XTAL_ 4000000
#include <xc.h>

#define SEG7A_SetLow()          RB0=0
#define SEG7A_SetHigh()         RB0=1
#define SEG7B_SetLow()          RB1=0
#define SEG7B_SetHigh()         RB1=1
#define SEG7C_SetLow()          RB2=0
#define SEG7C_SetHigh()         RB2=1
#define SEG7D_SetLow()          RB3=0
#define SEG7D_SetHigh()         RB3=1
#define SEG7E_SetLow()          RB4=0
#define SEG7E_SetHigh()         RB4=1
#define SEG7F_SetLow()          RB5=0
#define SEG7F_SetHigh()         RB5=1
#define SEG7G_SetLow()          RB6=0
#define SEG7G_SetHigh()         RB6=1

void seg7set0(); // following 11 functions are prototypes for each 7-seg setting called in pin_manager.c
void seg7set1();
void seg7set2();
void seg7set3();
void seg7set4();
void seg7set5();
void seg7set6();
void seg7set7();
void seg7set8();
void seg7set9();
void seg7setclear(); 

void seg7set0()
{   
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetLow();
    SEG7F_SetLow();
    SEG7G_SetHigh();
  }
void seg7set3() // establish function for activating #3 on 7-seg
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetHigh();
    SEG7F_SetHigh();
    SEG7G_SetLow();
    
}
void seg7set1()     // establish function for activating #1 on 7-seg
{
    SEG7A_SetHigh();
       SEG7B_SetLow();
       SEG7C_SetLow();
       SEG7D_SetHigh();
       SEG7E_SetHigh();
       SEG7F_SetHigh();
       SEG7G_SetHigh();
}

void seg7set2()      // function for activating #2 on 7-seg
{
    SEG7A_SetLow();
       SEG7B_SetLow();
       SEG7C_SetHigh();
       SEG7D_SetLow();
       SEG7E_SetLow();
       SEG7F_SetHigh();
       SEG7G_SetLow();
}
void seg7set4()
{
    SEG7A_SetHigh();
       SEG7B_SetLow();
       SEG7C_SetLow();
       SEG7D_SetHigh();
       SEG7E_SetHigh();
       SEG7F_SetLow();
       SEG7G_SetLow();
}
void seg7set5()
{
       SEG7A_SetLow();
       SEG7B_SetHigh();
       SEG7C_SetLow();
       SEG7D_SetLow();
       SEG7E_SetHigh();
       SEG7F_SetLow();
       SEG7G_SetLow();
}
void seg7set6()
{
    SEG7A_SetLow();
    SEG7B_SetHigh();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetLow();
    SEG7F_SetLow();
    SEG7G_SetLow();
}
void seg7set7()
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetHigh();
    SEG7E_SetHigh();
    SEG7F_SetHigh();
    SEG7G_SetHigh();
}
void seg7set8()
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetLow();
    SEG7F_SetLow();
    SEG7G_SetLow();
}
void seg7set9()
{
    SEG7A_SetLow();
    SEG7B_SetLow();
    SEG7C_SetLow();
    SEG7D_SetLow();
    SEG7E_SetHigh();
    SEG7F_SetLow();
    SEG7G_SetLow();
}
void seg7setclear()
{
    SEG7A_SetHigh();
    SEG7B_SetHigh();
    SEG7C_SetHigh();
    SEG7D_SetHigh();
    SEG7E_SetHigh();
    SEG7F_SetHigh();
    SEG7G_SetHigh();
}

Void (*seg7set[11])(); // array to hold pointers for each 7 segment vaule
seg7set[0] = seg7set0;
seg7set[1] = seg7set1; // calling the functions defined in pin_manager.h for each 7 segment value
seg7set[2] = seg7set2;
seg7set[3] = seg7set3;
seg7set[4] = seg7set4;
   seg7set[5] = seg7set5;
   seg7set[6] = seg7set6;
   seg7set[7] = seg7set7;
   seg7set[8] = seg7set8;
   seg7set[9] = seg7set9;
   seg7set[10]= seg7setclear;
 

void main(void) {
    TRISA = 0b1010; //RA3 gets tri-stated to turn off AN1 and AN2,
                    //RA1 must be high imp. its connected straight to ground
    TRISB = 0b00000000; //All PortB Pins are I/O
    OPTION = 000111;  //Options - Prescaler set at 1:256
    char currentclk = 0;
    char previousclk = 0;
    int dotflash = 0;
    int ansel = 0;
   // char charsel = 1;
    RA3=1; //Anode 1 and 2 - tristate this pin to turn off
    RB7=1; //Anode 3 start on Anode 3, or the if statement flow doesnt work


 
    while(1) {
        
        previousclk = currentclk;   // clock
        currentclk = TMR0;
        
        if (previousclk > currentclk) //advance item clocks here
        {
            dotflash++;
            ansel++;
        }
        
        if (dotflash==4000)  //4000 cycles is approx 1s
        {
            if (RA0==1) RA0=0;
            else if (RA0==0) RA0=1;
            dotflash=0;           
        }
        if (ansel>15)
        {
            if (RB7==1)
            {
                RB7=0;
                TRISA = 0b0010;
                RA3=1;
            }
            else if (RA3==1)
            {
                RA3=0;
            }
            else if (RA3==0)
            {
                TRISA = 0b1010;
                RB7=1;
            }

           ansel=0;
        }
        // TRISA = 0b1010;
        //RA0=1; //Dot Anode

        
        RB0=0;
        RB1=0;
        RB2=0;
        RB3=1;
        RB4=0;
        RB5=0;
        RB6=0;
        
        
        
        
    }
    return;
}
The compiler output is here. The line #'s it is referencing in the errors relate to the correct numbers in the code above.

Code:
CLEAN SUCCESSFUL (total time: 4ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/Travis/MPLABXProjects/BensTimer.X'
make  -f nbproject/Makefile-default.mk dist/default/production/BensTimer.X.production.hex
make[2]: Entering directory 'C:/Users/Travis/MPLABXProjects/BensTimer.X'
"C:\Program Files (x86)\Microchip\xc8\v2.05\bin\xc8-cc.exe"  -mcpu=16F54 -c  -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -DXPRJ_default=default  -msummary=-psect,-class,+mem,-hex,-file  -ginhx032 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall   -std=c99 -gdwarf-3 -mstack=compiled:auto     -o build/default/production/Main1.p1 Main1.c 
::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries
Main1.c:158:8: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
Void (*seg7set[11])(); // array to hold pointers for each 7 segment vaule
       ^
Main1.c:158:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
Void (*seg7set[11])(); // array to hold pointers for each 7 segment vaule
^
Main1.c:158:6: error: function cannot return function type 'int ()'
Void (*seg7set[11])(); // array to hold pointers for each 7 segment vaule
     ^
Main1.c:159:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
seg7set[0] = seg7set0;
^
Main1.c:159:1: error: array initializer must be an initializer list
Main1.c:160:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
seg7set[1] = seg7set1; // calling the functions defined in pin_manager.h for each 7 segment value
^
Main1.c:160:1: error: array initializer must be an initializer list
Main1.c:161:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
seg7set[2] = seg7set2;
^
Main1.c:161:1: error: array initializer must be an initializer list
Main1.c:162:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
seg7set[3] = seg7set3;
^
Main1.c:162:1: error: array initializer must be an initializer list
Main1.c:163:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
seg7set[4] = seg7set4;
^
Main1.c:163:1: error: array initializer must be an initializer list
Main1.c:164:4: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
   seg7set[5] = seg7set5;
   ^
Main1.c:164:4: error: array initializer must be an initializer list
Main1.c:165:4: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
   seg7set[6] = seg7set6;
   ^
Main1.c:165:4: error: array initializer must be an initializer list
Main1.c:166:4: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
   seg7set[7] = seg7set7;
   ^
Main1.c:166:4: error: array initializer must be an initializer list
Main1.c:167:4: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
   seg7set[8] = seg7set8;
   ^
Main1.c:167:4: error: array initializer must be an initializer list
Main1.c:168:4: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
   seg7set[9] = seg7set9;
   ^
Main1.c:168:4: error: array initializer must be an initializer list
Main1.c:169:4: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
   seg7set[10]= seg7setclear;
   ^
Main1.c:169:4: error: array initializer must be an initializer list
13 warnings and 12 errors generated.
(908) exit status = 1
nbproject/Makefile-default.mk:106: recipe for target 'build/default/production/Main1.p1' failed
make[2]: Leaving directory 'C:/Users/Travis/MPLABXProjects/BensTimer.X'
nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/Travis/MPLABXProjects/BensTimer.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make[2]: *** [build/default/production/Main1.p1] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 961ms)

Any thoughts or ideas on how to overcome this?

Appreciation to anyone who took the time to even look at all this :D
 

Thread Starter

Travm

Joined Aug 16, 2016
363
The basic idea of what I want to do, is have a function or a variable that returns or is a number, and then I want to use that number to directly call the function that holds all the IO settings to set a digit on the 7 segment. I'm stuck here only because the code works on the 16F1564, and does not compile for the 16F54, using the same software and compiler.
 

Papabravo

Joined Feb 24, 2006
21,159
The basic idea of what I want to do, is have a function or a variable that returns or is a number, and then I want to use that number to directly call the function that holds all the IO settings to set a digit on the 7 segment. I'm stuck here only because the code works on the 16F1564, and does not compile for the 16F54, using the same software and compiler.
Is it possible that the 16F1564 has features that are not supported in the 16F54?
Can you elaborate on "does not compile"?
What messages is the compiler producing?
Why didn't you include the content of those messages?
How did you expect we would be able to help with the limited amount of information you provided?
 

Thread Starter

Travm

Joined Aug 16, 2016
363
Is it possible that the 16F1564 has features that are not supported in the 16F54?
Can you elaborate on "does not compile"?
What messages is the compiler producing?
Why didn't you include the content of those messages?
How did you expect we would be able to help with the limited amount of information you provided?
Reread the post maybe?
It's all there.

Yes the 1564 chip has lots of features the 54 does not. This however appears to be a compiler or C issue.
 

Beau Schwabe

Joined Nov 7, 2019
155
From an Assembly language perspective the 16F54 does not have the ADDLW and SUBLW command ... The reason I point this out is that I have seen some compilers that are not aware of the missing commands. There are workarounds in code for a functionally equivalent solution.
 

Papabravo

Joined Feb 24, 2006
21,159
Reread the post maybe?
It's all there.

Yes the 1564 chip has lots of features the 54 does not. This however appears to be a compiler or C issue.
I can't tell you what the root cause of the problem is but the advisory about C99 libraries not being available seems like it might be significant.
You have pointers to functions returning void when the compiler is defaulting the type to int. You and the compiler might need to become better acquainted. Function prototype in the correct position may or may not help with this one.
It was not clear from the visible window fragments that you had included the relevant information. Would it have killed you to mention the error in your text?
 

Thread Starter

Travm

Joined Aug 16, 2016
363
I can't tell you what the root cause of the problem is but the advisory about C99 libraries not being available seems like it might be significant.
You have pointers to functions returning void when the compiler is defaulting the type to int. You and the compiler might need to become better acquainted. Function prototype in the correct position may or may not help with this one.
It was not clear from the visible window fragments that you had included the relevant information. Would it have killed you to mention the error in your text?
The function prototype is in the wrong position?
I'm not sure how to stop the compiler defaulting to int. I don't need those functions to return anything, just execute the code within.
The code is copied from the other project where it compiles and functions as expected.
 

Papabravo

Joined Feb 24, 2006
21,159
The function prototype is in the wrong position?
I'm not sure how to stop the compiler defaulting to int. I don't need those functions to return anything, just execute the code within.
The code is copied from the other project where it compiles and functions as expected.
You stop the compiler from defaulting to int by having a prototype. If you have a function prototype and the compiler can process it before it sees the first invocation of that function, it will know the return type, AND the number and type of the arguments. For example if you have a multiply function that takes two ints and returns a long you put a prototype in a header file that says:

long multiply(int, int) ;

You don't have to give the names of the arguments. The trailing semi-colon (instead of a curly brace) tells the compiler it is a prototype.
 

Thread Starter

Travm

Joined Aug 16, 2016
363
You stop the compiler from defaulting to int by having a prototype. If you have a function prototype and the compiler can process it before it sees the first invocation of that function, it will know the return type, AND the number and type of the arguments. For example if you have a multiply function that takes two ints and returns a long you put a prototype in a header file that says:

long multiply(int, int) ;

You don't have to give the names of the arguments. The trailing semi-colon (instead of a curly brace) tells the compiler it is a prototype.
Ok, I think I have those. Labeled in the comments as such.
 

Papabravo

Joined Feb 24, 2006
21,159
As @Beau Schwabe has already alluded to, there may be no way to generate the assembly language code to do what you want. I'm not specifically familiar with those two parts, but if you could locate the assembly code for the part that works you might be able to see if the code would port to the less capable part.
 

Thread Starter

Travm

Joined Aug 16, 2016
363
That sounds a little beyond my ability today.
I'll see if I can eliminate the c99 library issue, that could be the problem. I discounted it because the code worked up until I added the display functions.
I can't imagine that using a pointer to a function that toggles io ports isn't possible on this part.
 

jpanhalt

Joined Jan 18, 2008
11,087
Those missing instructions in the 12-bit core , 33-instruction devices (e.g., 12F509) are easily substituted:

Consider: addlw

Where did W come from? If something like: movf regA,w (movfw was used then too).
then reverse the sequence to: movlw literal or regX , then addwf regA,w and you are back to the same place. Same process with subtraction. Remember that "movlw RegA" moves the register number, not its contents.
 

Papabravo

Joined Feb 24, 2006
21,159
That sounds a little beyond my ability today.
I'll see if I can eliminate the c99 library issue, that could be the problem. I discounted it because the code worked up until I added the display functions.
I can't imagine that using a pointer to a function that toggles io ports isn't possible on this part.
It may be, we just don't know if the architecture of the more limited part supports that coding structure.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Can you try this...
C:
Void (*seg7set[11])(void) = {
    seg7set0,
    seg7set1,
    seg7set2,
    seg7set3,
    seg7set4,  
    seg7set5,
    seg7set6,
    seg7set7,
    seg7set8,
    seg7set9,
    seg7setclear
};
Was this "working" code from the xc compiler?
 

Thread Starter

Travm

Joined Aug 16, 2016
363
Yes It was/is. I've disassembled the hardware since then so it would be difficult to test.
Regardless that is most likely where my problem is.

Away from my PC at the moment, will test when I get a chance.
 

Ian Rogers

Joined Dec 12, 2012
1,136
The original code was in the main... The second code pasted was outside so will not initialise... If you want to initialise the function pointers outside the main function, try the code above..
 

Thread Starter

Travm

Joined Aug 16, 2016
363
I didn't notice that. I thought the original code was outside the main. Obviously I didn't look closely enough.
Explains the errors I suppose. Two hours and I should be able to test
 

Thread Starter

Travm

Joined Aug 16, 2016
363
Can you try this...
C:
Void (*seg7set[11])(void) = {
    seg7set0,
    seg7set1,
    seg7set2,
    seg7set3,
    seg7set4,
    seg7set5,
    seg7set6,
    seg7set7,
    seg7set8,
    seg7set9,
    seg7setclear
};
Was this "working" code from the xc compiler?
So that code got it to compile.
Looks like XC8 changed a little since I last used it as well. My old code (generated by MCC) wont compile any more, and the automatically generated MCC code is full of errors.

Tomorrow I'll see if i can make this code do something now.

Thanks a ton.

Any suggestions on making that code more compact? Just adding those functions and the pointer array took me from 25% of data memory used to 84%. That might be the next hurdle.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Well I wouldn't do it that way at all... All the digits would be in a array of chars.. Then you don't even have to ty function pointers at all.... Function pointers are advanced C.. What you are doing will work, but my god, there are easier ways do do it..

char sevenSeg[] = {0x40,0x79,0x22,0x30,0x19,0x12,0x02,0x78,0x00,0x1,0x7f}; will do the job

Then use PORTB = sevenSeg[x]; then add in RB7.... no function pointers...
 
Top