2

My project consists in:

Using a 4 digit 7-segment display to show certain numbers, representing the amount of cash stored in a moneybox. I am using both .c and .S files.

To rotate between the 4 digits I use a 4ms TIMER0 interrupt, whose ISR calls the Assembly function. Apart from that interrupt, I am using Interrupt on Change, but that part works just fine so I removed it from the code I am sharing.

Device: PIC16F18855; MPLABxIDE 5.45; XC8 Compiler.

So, here is the main.c script (please excuse the spanish comments):

#include <xc.h>
 
 
// INICIO DE PRIVATE CODE
// Se incluyen los headers
#include "system.h"
 
 
// Declaración de funciones
void TMR0_ISR_DISPLAY4(void);  // Corrección en los parámetros
extern void DISPLAY4();
void array_digitos4(unsigned int);   // Función para obtener el array de números a mostrar en el display 4 segmentos
 
 
// Declaración de variables globales
volatile unsigned char tecla, compart;
volatile unsigned int TOTAL = 0; // Cantidad total de dinero en la alcancía 
volatile unsigned int X = 0;    // Cantidad en un compartimiento (A, B, C, D)
volatile unsigned int Y = 0; 
volatile unsigned int totales_ar[4] = {0, 0, 0, 0};  // Los totales se acumulan en un array
volatile unsigned char etapa = 0;
volatile unsigned char digito = 0;
volatile unsigned char digitos4[4] = {0, 0, 0, 0};
volatile unsigned char D0, D1, D2, D3;
 
 
int main(void){
    // Inicialización de periféricos
    SYSTEM_Initialize();
    
    // Configuración del handler para TMR0 ISR
    TMR0_OverflowCallbackRegister(TMR0_ISR_DISPLAY4);
 
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;
    INTCONbits.INTEDG = 0;
    
    while(1){
        // Tu bucle principal
        __asm("nop");
        __asm("nop");
        __asm("nop");
    }
}
 
 
// Implementación de la ISR
void TMR0_ISR_DISPLAY4(void){
    // Deshabilito interrupciones
    INTCONbits.GIE = 0;
    
    // Llamada a la función en ensamblador con los parámetros
    switch(etapa){
        case 0:
            array_digitos4(TOTAL);           
            break;
            
        case 1:
            if(digito == 0){
                array_digitos4(X);
            }
            else{
                array_digitos4(Y);
            }
            break;
                  
        case 2:
            array_digitos4(totales_ar[compart]);
            break;  
    }
    DISPLAY4();
    
    // Salir de la ISR
    PIR0bits.TMR0IF = 0;
    INTCONbits.GIE = 1;
}
 
void array_digitos4(unsigned int numero){
    unsigned int dividendo = numero;
    unsigned int divisor = 1000;             // Iniciar con 1000 para el primer dígito
    // Descomponer el número en dígitos
    for (int i = 0; i < 4; i++){
        if(digitos4[i] >= divisor){
            //digitos4[i] = (char)(dividendo/divisor);     // Obtener el dígito correspondiente
            digitos4[i] = (char)(10);
        }
        else{
            digitos4[i] = 0;
        }
        dividendo = dividendo%divisor;       // Reducir el número eliminando el dígito extraído
        divisor = divisor/10;          // Reducir el divisor para el siguiente dígito
    }
    D0 = digitos4[0];
    D1 = digitos4[1];
    D2 = digitos4[2];
    D3 = digitos4[3];
}

Now, the DISPLAY4.S, this is the part of the script that is failing:

#include <xc.inc>
 
 
GLOBAL _DISPLAY4      ; Hacer la función accesible desde C
PSECT text, class = CODE, local, delta = 2
 
 
; Definir variables manualmente en la RAM
extern      _D3
extern      _D2
extern      _D1
extern      _D0
 
_DISPLAY4:
    ; Operación con PORTC para encender el digito correcto
    BANKSEL (PORTC)            ; Seleccionar el banco de PORTC
    movf    _D3, W           ; Leer PORTC en W
    movwf   PORTC

How do I access the variables declared and calculated in the .c file? To, say, move the content from D0, D1, D2, or D3, to PORTC in the .S file? That port controls the display mentioned prevoiusly.

0

2 Answers 2

1

The value is transmitted via the w-register, if you call an assembler subroutine in xc8 code.

    extern void DISPLAY4(unsigned char a); 
    ...  
    DISPLAY4(4);             //the value '4' is loaded into the w 
    register
    ...

the w register is loaded with the value of 4.

In the assembler routine the w register is know already loaded with the value of 4.

GLOBAL _DISPLAY4
...    
_DISPLAY4:
        movwf PORTC        ;pushes the value 4 to port C      
        return

Now you can write this value to the port C.

Sign up to request clarification or add additional context in comments.

2 Comments

Hi Mike, I managed to solve it adding this to all my variables (each in its own line): extrn _D3 extrn _D2 extrn _D1 extrn _D0 Now the .S file recognises the global characters declared in main.c, but still, how can I send all 4 values (D3, D2, D1, D0) being all of them unsigned chars? As parameters to said function, not only one of them at a time. -> DISPLAY4(D0, D1, D2, D3)
The first argument is tranfered via the w-register. I don't know how it works with more arguments. Maybe this link helps: forum.microchip.com/s/topic/a5C3l000000BqlCEAS/t391905. I will try it later.
-1

Have you tried to:

; Definir variables manualmente en la RAM
extern      D3
extern      D2
extern      D1
extern      D0

instead?

Historically, C compilers used _ character in front of an identifier to avoid name clashes with assembler code, but today that's practically dissapeared. Check if your compiler generates symbols with _ prepended, and change the assembler code correspondingly.

4 Comments

The xc8 compiler still works with _.
I don't use xc8, sorry. This is an issue that can be the source of problems. I tried to just point to something that could be wrong.
Aren't you using a I2C or SPI device to control the display. It allows you to support ram memory on the device and the chip generates all the signals to control de led display. try for example HT16K33A (i2c) or TM1638 (SPI) (both chips allow you to control up to eight digit and a 39 keys button matrix for a keyboard)
I can assist you in spanish, have you posted this question in the spanis version of StackOverflow? If so, drop me a reference to the question, and I can assist you there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.