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 main
bucle, llamo uart_putch('a');
, esto funciona bien. Sin embargo, cuando defino const char c = 'a';
y llamo uart_putch(c);
, no funciona. Imprime algo, aunque no un a
- Creo que son 0x00
personajes, de los cuales obtengo 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 (la izquierda funciona, la derecha no):
El código es simple:
void main(void) {
init(); // Sets up ports and UART control registers
while (1) {
uart_putch('a'); // or c
}
}
Lo que no funciona bien es el uso de cualquiera de las funciones de cadena ( puts
, printf
, etc.), que creo que está relacionado - por lo que en esta pregunta que hice un ejemplo básico mínimo, con los personajes.
El ensamblado generado cuando uso una variable c
tiene:
_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 _main
bloque:
movlw (061h)&0ffh
call _putch
Estoy usando MPLAB XC8 C Compiler V1.41 (24 de enero de 2017), con la versión de soporte parcial 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 que esto funcione será muy apreciada.
unsigned char
,char
,const unsigned char
yconst char
.byteTx
? Me preocupa quebyte
pueda definirse en otro lugar como un tipo de datos. (Parece que eso generaría un diagnóstico del compilador, pero claramente algo extraño está sucediendo aquí.) Y como otra prueba, ¿seputch(0x61)
comporta mal de la misma manera queputch('a')
? Me pregunto si la instrucción de lectura de tabla está leyendo datos de 8 bits o de 16 bits. El registro PIC W solo tiene 8 bits, ¿verdad?Respuestas:
Su programa está bien, es un error en el PIC18F27K40.
Ver http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf
Utilice el compilador XC8 V1.41 y mplabx IDE, seleccione Opciones globales XC8 / 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:
fuente
los caracteres const se almacenan en la memoria del programa (flash), y parece que el compilador está viendo que no lo está utilizando como una variable (ya que nunca cambia) y optimizándolo 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é importa esto?
En PIC18s, el uso de 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 del PIC16, lo que probablemente sea la razón por la que funciona en uno pero no en el otro. Por 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. Almacenar algo en la memoria del programa no es automáticamente seguro.
Según el ensamblaje, está bastante claro que está cargando los 8 bytes incorrectos. Que es 0x00, por lo que envía correctamente 0x00 (como has confirmado a fondo que lo está haciendo).
Puede ser difícil predecir lo que obtendrá con la increíble cantidad de optimización del compilador en estos días, por lo que no estoy seguro de si esto funcionará. el truco volátil debería funcionar, pero si realmente quieres que esté almacenado en flash, prueba 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 del ensamblador del compilador para hacer lo que queremos, y no lo que realmente queremos.
De la Guía del usuario de MPASM:
También recomiendo revisarlo usted mismo , así como code_pack, en el PDF. Página 65.
fuente