Ich habe ein ziemlich seltsames Problem mit XC8 auf einem PIC18F27K40-Mikrocontroller. Auf einem PIC16F1778 funktioniert es . Ich habe definiert:
void uart_putch(unsigned char byte) {
while (!PIR3bits.TX1IF);
TX1REG = byte;
}
Wenn ich in meiner main
Schleife anrufe uart_putch('a');
, funktioniert dies einwandfrei. Wenn ich jedoch definiere const char c = 'a';
und aufrufe uart_putch(c);
, funktioniert es nicht. Es druckt etwas, wenn auch nicht a
- ich denke, es sind 0x00
Charaktere, von denen ich komme hexdump -x /dev/ttyUSB0
. Dies ist kein Problem mit der seriellen Schnittstelle meines Computers. Ich habe mit einem Zielfernrohr gesucht und das Signal ist anders (links funktioniert, rechts nicht):
Der Code ist einfach:
void main(void) {
init(); // Sets up ports and UART control registers
while (1) {
uart_putch('a'); // or c
}
}
Was entweder nicht funktioniert ist eine der String - Funktionen verwenden ( puts
, printf
usw.), die ich denke , ist in Verbindung stehend - so in dieser Frage habe ich ein minimales Arbeits Beispiel mit Zeichen.
Die generierte Assembly, wenn ich eine Variable verwende, c
hat:
_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
Und mit einer Konstante hat es im _main
Block:
movlw (061h)&0ffh
call _putch
Ich verwende MPLAB XC8 C Compiler V1.41 (24. Januar 2017) mit Teilunterstützungsversion 1.41.
Die relevanten Teile meines Makefiles:
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 $<
Jede Hilfe, um dies zum Laufen zu bringen, wäre sehr dankbar.
unsigned char
,char
,const unsigned char
undconst char
.byteTx
stattdessen das Argument umbenennen ? Ich mache mir Sorgen, dassbyte
dies an anderer Stelle als Datentyp definiert werden könnte. (Scheint so, als würde dies eine Compiler-Diagnose generieren, aber hier passiert eindeutig etwas Seltsames.) Und verhält sich ein anderer Testputch(0x61)
genauso schlecht wieputch('a')
? Ich frage mich, ob der Tabellenlesebefehl 8-Bit- oder 16-Bit-Daten liest. Das PIC W-Register ist allerdings nur 8 Bit, oder?Antworten:
Ihr Programm ist in Ordnung. Es ist ein Fehler auf dem PIC18F27K40.
Siehe http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf
Verwenden Sie den XC8-Compiler V1.41 und die mplabx-IDE, wählen Sie XC8 Global Options / XC8 Linker und wählen Sie "Additional options". Fügen Sie dann
+nvmreg
das Feld Errata hinzu, und alles wird in Ordnung sein.Auszug aus dem verknüpften Dokument, fett markierte Schlüsselwörter:
quelle
const-Zeichen werden im Programmspeicher (Flash) gespeichert, und es sieht so aus, als würde der Compiler feststellen, dass Sie sie nicht als Variable verwenden (da sie sich nie ändert) und sie im Programmspeicher optimieren, unabhängig davon, ob Sie const verwenden oder nicht.
Versuchen Sie es als zu deklarieren
volatile char c= 'a';
. Dadurch wird erzwungen, dass er im SRAM und nicht im Flash gespeichert wird.Warum ist das wichtig?
Bei PIC18s wird die Verwendung der db-Direktive (Databyte zum Speichern eines Bytes im Programmspeicher) mit einer ungeraden Anzahl von Bytes (wie in Ihrem Fall) automatisch mit Nullen aufgefüllt. Dieses Verhalten unterscheidet sich von dem des PIC16, weshalb es wahrscheinlich auf dem einen, aber nicht auf dem anderen funktioniert. Aus diesem Grund funktionieren im Flash-Speicher gespeicherte Zeichenfolgen oder Zeichen auch nicht mit den Standardfunktionen für Zeichenfolgen wie strcpy oder printf. Das Speichern von etwas im Programmspeicher ist nicht automatisch typsicher.
Basierend auf der Assembly ist es ziemlich klar, dass die falschen 8 Bytes geladen werden. Welches ist 0x00, also sendet es korrekt 0x00 (wie Sie gründlich bestätigt haben, dass es funktioniert).
Es kann schwierig sein, vorherzusagen, was Sie heutzutage mit der wahnsinnigen Menge an Compiler-Optimierung erreichen werden, daher bin ich mir nicht sicher, ob dies funktionieren wird. Der flüchtige Trick sollte funktionieren, aber wenn Sie wirklich möchten, dass er in Flash gespeichert wird, versuchen Sie Folgendes:
TXREG = data & 0xff;
oder möglicherweise
TXREG = data & 0x0ff;
Ich weiß, dass dies theoretisch nichts bewirken sollte. Wir versuchen jedoch, die Assembly-Ausgabe des Compilers so zu ändern, dass sie das tut, was wir wollen, und nicht irgendwie, aber nicht wirklich das, was wir wollen.
Aus dem MPASM-Benutzerhandbuch:
Ich empfehle auch , es selbst sowie code_pack im PDF zu überprüfen. Seite 65.
quelle