J'ai un problème assez étrange avec XC8 sur un microcontrôleur PIC18F27K40. Sur un PIC16F1778 cela fonctionne . J'ai défini:
void uart_putch(unsigned char byte) {
while (!PIR3bits.TX1IF);
TX1REG = byte;
}
Lorsque, dans ma main
boucle, j'appelle uart_putch('a');
, cela fonctionne bien. Cependant, lorsque je définis const char c = 'a';
et appelle uart_putch(c);
, cela ne fonctionne pas. Il imprime quelque chose, mais pas un a
- je pense que ce sont des 0x00
personnages dont je tire hexdump -x /dev/ttyUSB0
. Ce n'est pas un problème avec le port série de mon ordinateur; J'ai regardé avec une lunette et le signal est différent (gauche fonctionne, droite non):
Le code est simple:
void main(void) {
init(); // Sets up ports and UART control registers
while (1) {
uart_putch('a'); // or c
}
}
Ce qui ne fonctionne pas non plus est en utilisant l' une des fonctions de chaîne ( puts
, printf
, etc.), qui je pense est lié - donc dans cette question que je fait un exemple de travail minimal avec des caractères.
L'assembly généré lorsque j'utilise une variable c
a:
_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
Et avec une constante, il a dans le _main
bloc:
movlw (061h)&0ffh
call _putch
J'utilise le compilateur MPLAB XC8 C V1.41 (24 janvier 2017), avec la prise en charge partielle de la version 1.41.
Les parties pertinentes de mon 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 $<
Toute aide pour le faire fonctionner serait très appréciée.
unsigned char
,char
,const unsigned char
etconst char
.byteTx
place? Je crains que celabyte
ne soit défini ailleurs comme un type de données. (On dirait que cela générerait un diagnostic du compilateur, mais clairement quelque chose d'étrange se passe ici.) Et comme un autre test, seputch(0x61)
comporte-t-il de la même manière queputch('a')
? Je me demande si l'instruction de lecture de table lit des données 8 bits ou 16 bits. Le registre PIC W n'est que de 8 bits, non?Réponses:
Votre programme va bien, c'est un bug sur le PIC18F27K40.
Voir http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf
Utilisez XC8 compilier V1.41 et mplabx IDE, sélectionnez XC8 Global options / XC8 linker et sélectionnez "Additional options", puis ajoutez
+nvmreg
dans la zone Errata et tout ira bien.Extrait du document lié, mots clés en gras:
la source
les caractères const sont stockés dans la mémoire du programme (flash), et il semble que le compilateur voit que vous ne l'utilisez pas comme variable (car il ne change jamais) et l'optimise dans la mémoire du programme, que vous utilisiez const ou non.
Essayez de le déclarer comme
volatile char c= 'a';
. Cela le forcera à être stocké dans SRAM plutôt que flash.Pourquoi est-ce important?
Sur les PIC18, l'utilisation de la directive db (dataoctet pour stocker un octet dans la mémoire du programme) avec un nombre impair d'octets (comme dans votre cas) le remplira automatiquement avec des zéros. Ce comportement diffère de celui du PIC16, c'est probablement pourquoi il fonctionne sur l'un mais pas sur l'autre. Pour cette raison, les chaînes ou les caractères stockés dans la mémoire flash ne fonctionneront pas non plus avec les fonctions de chaîne standard, telles que strcpy ou printf. Stocker quelque chose dans la mémoire du programme n'est pas automatiquement sécurisé.
Sur la base de l'assemblage, il est assez clair que le chargement des 8 octets est incorrect. Ce qui est 0x00, donc il envoie correctement 0x00 (comme vous l'avez bien confirmé).
Il peut être difficile de prédire ce que vous obtiendrez avec la quantité folle d'optimisation du compilateur de nos jours, donc je ne sais pas si cela fonctionnera. l'astuce volatile devrait fonctionner, mais si vous voulez vraiment le stocker en flash, essayez ceci:
TXREG = data & 0xff;
ou peut-être
TXREG = data & 0x0ff;
Je sais qu'en théorie, cela ne devrait rien faire. Mais nous essayons de changer la sortie d'assembly du compilateur pour faire ce que nous voulons, et non pas en quelque sorte mais pas vraiment ce que nous voulons.
Dans le Guide de l'utilisateur MPASM:
Je recommande également de le vérifier vous - même , ainsi que code_pack, dans le PDF. Page 65.
la source