Imprimir caracteres variables en UART no funciona, las constantes funcionan bien

9

Tengo un problema bastante extraño con XC8 en un microcontrolador PIC18F27K40. En un PIC16F1778 funciona . He definido:

void uart_putch(unsigned char byte) {
    while (!PIR3bits.TX1IF);
    TX1REG = byte;
}

Cuando, en mi bucle main , llamo a uart_putch('a'); , esto funciona bien. Sin embargo, cuando defino const char c = 'a'; y llamo a uart_putch(c); , no funciona. Imprime algo, aunque no es un a . Creo que son 0x00 caracteres, que recibo de hexdump -x /dev/ttyUSB0 . Esto no es un problema con el puerto serie en mi computadora; Miré con un alcance y la señal es diferente (izquierda funciona, derecha no):

Elcódigoessimple:

voidmain(void){init();//SetsupportsandUARTcontrolregisterswhile(1){uart_putch('a');//orc}}

Loquetampocofuncionaesusarcualquieradelasfuncionesdecadena(puts,printf,etc.),quecreoqueestárelacionada,porloqueenestapreguntahiceunejemplodetrabajomínimoconcaracteres.

Elensambladogeneradocuandousounavariablectiene:

_c: db low(061h) global __end_of_c _main: ; ... movlw low((_c)) movwf tblptrl if 1 ;There is more than 1 active tblptr byte movlw high((_c)) movwf tblptrh endif if 1 ;There are 3 active tblptr bytes movlw low highword((_c)) movwf tblptru endif tblrd * movf tablat,w call _putch

Y con una constante que tiene en el bloque _main :

    movlw   (061h)&0ffh 
    call    _putch

Estoy usando MPLAB XC8 C Compiler V1.41 (24 de enero de 2017), con soporte de pieza versión 1.41.

Las partes relevantes de mi Makefile:

CC:=xc8
CFLAGS:=-I. --chip=18F27K40 -Q -Wall

SRC:=main.c uart.c
DEP:=uart.h
PRS:=$(subst .c,.p1,$(SRC))
OBJ:=main.hex

all: $(OBJ)

$(OBJ): $(PRS)
    $(CC) $(CFLAGS) $^

$(PRS): %.p1: %.c $(DEP)
    $(CC) $(CFLAGS) -o$@ --pass1 $<

Cualquier ayuda para hacer que esto funcione sería muy apreciada.

    
pregunta Keelan

2 respuestas

3

Su programa está bien, es un error en el PIC18F27K40.

Consulte enlace

Use XC8 compilier V1.41 y mplabx IDE, seleccione XC8 Global options / XC8 linker y seleccione "Opciones adicionales", luego agregue +nvmreg en el cuadro Errata y todo estará bien.

Extracto del documento vinculado, palabras clave marcadas en negrita:

  

TBLRD requiere que el valor NVMREG apunte a   memoria apropiada

     

Las revisiones de silicona afectadas de los dispositivos PIC18FXXK40 requieren incorrectamente los bits NVMREG<1:0> en el registro NVMCON para configurarse para el acceso TBLRD de las distintas regiones de memoria. El problema es más evidente en los programas de C compilados cuando el usuario define un tipo de const. y el compilador utiliza TBLRD instrucciones para recuperar los datos de la memoria Flash del programa (PFM). El problema también es evidente cuando el usuario define una matriz en la RAM para la cual el compilador crea un código de inicio, ejecutado antes de main() , que usa las instrucciones de TBLRD para inicializar la RAM desde PFM.

    
respondido por el Ian Munro
3

los caracteres const se almacenan en la memoria del programa (flash), y parece que el compilador ve que no lo está utilizando como una variable (ya que nunca cambia) y lo está optimizando en la memoria del programa, independientemente de si usa const o no.

Intenta declararlo como volatile char c= 'a'; . Esto obligará a que se almacene en SRAM en lugar de flash.

¿Por qué esto importa?

En PIC18s, usar la directiva db (databyte para almacenar un byte en la memoria del programa) con un número impar de bytes (como en su caso) lo rellenará automáticamente con ceros. Este comportamiento difiere del de PIC16, que es probablemente el motivo por el que funciona en uno pero no en el otro. Debido a esta razón, las cadenas o caracteres almacenados en la memoria flash tampoco funcionarán con ninguna de las funciones de cadena estándar, como strcpy o printf. Guardar algo en la memoria del programa no es automáticamente seguro.

Según el ensamblaje, es bastante claro que está cargando los 8 bytes incorrectos. Lo que es 0x00, por lo que envía correctamente 0x00 (como lo confirmó a fondo).

Puede ser difícil predecir qué obtendrás con la loca cantidad de optimización del compilador en estos días, así que no estoy seguro de si esto funcionará. El truco volátil debería funcionar, pero si realmente desea que se almacene en flash, intente esto:

TXREG = data & 0xff;

o posiblemente

TXREG = data & 0x0ff;

Sé que en teoría, esto no debería hacer nada. Pero estamos tratando de cambiar la salida de ensamblaje del compilador para hacer lo que queremos, y no la clase pero realmente no lo que queremos.

De la Guía del usuario de MPASM:

Tambiénrecomiendo revisándolo usted mismo , así como code_pack, en el PDF. Página 65.

    
respondido por el metacollin

Lea otras preguntas en las etiquetas