Saya memiliki masalah yang agak aneh dengan XC8 pada mikrokontroler PIC18F27K40. Pada PIC16F1778 berfungsi . Saya telah mendefinisikan:
void uart_putch(unsigned char byte) {
while (!PIR3bits.TX1IF);
TX1REG = byte;
}
Ketika, dalam main
lingkaran saya , saya sebut uart_putch('a');
, ini berfungsi dengan baik. Namun, ketika saya mendefinisikan const char c = 'a';
dan menelepon uart_putch(c);
, itu tidak berfungsi. Ini mencetak sesuatu, meskipun bukan a
- saya pikir mereka adalah 0x00
karakter, yang saya dapatkan dari hexdump -x /dev/ttyUSB0
. Ini bukan masalah dengan port serial di komputer saya; Saya melihat dengan cakupan dan sinyalnya berbeda (kiri berfungsi, kanan tidak):
Kode ini sederhana:
void main(void) {
init(); // Sets up ports and UART control registers
while (1) {
uart_putch('a'); // or c
}
}
Apa yang tidak berfungsi adalah menggunakan salah satu fungsi string ( puts
,, printf
dll.), Yang saya pikir terkait - jadi dalam pertanyaan ini saya membuat contoh kerja minimal dengan karakter.
Rakitan yang dihasilkan saat saya menggunakan variabel c
memiliki:
_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
Dan dengan konstanta yang ada di _main
blok:
movlw (061h)&0ffh
call _putch
Saya menggunakan MPLAB XC8 C Compiler V1.41 (24 Januari 2017), dengan bagian dukungan versi 1.41.
Bagian yang relevan dari Makefile saya:
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 $<
Setiap bantuan untuk mendapatkan pekerjaan ini akan sangat dihargai.
unsigned char
,char
,const unsigned char
danconst char
.byteTx
? Saya khawatir yangbyte
mungkin didefinisikan di tempat lain sebagai tipe data. (Sepertinya itu akan menghasilkan diagnostik kompiler, tetapi jelas sesuatu yang aneh sedang terjadi di sini.) Dan sebagai tes lain, apakahputch(0x61)
berperilaku salah dengan cara yang samaputch('a')
? Saya bertanya-tanya apakah instruksi membaca tabel membaca data 8-bit atau 16-bit. Register PIC W hanya 8 bit, kan?Jawaban:
Program Anda baik-baik saja, Ini adalah bug pada PIC18F27K40.
Lihat http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf
Gunakan XC8 compilier V1.41 dan mplabx IDE, pilih XC8 Global options / XC8 linker dan pilih "Opsi tambahan", kemudian tambahkan
+nvmreg
dalam kotak Errata dan semua akan baik-baik saja.Kutipan dari dokumen tertaut, kata kunci bertanda tebal:
sumber
const chars disimpan dalam memori program (flash), dan sepertinya kompiler melihat bahwa Anda tidak menggunakannya sebagai variabel (karena tidak pernah berubah) dan mengoptimalkannya ke dalam memori program terlepas dari apakah Anda menggunakan const atau tidak.
Coba nyatakan sebagai
volatile char c= 'a';
. Ini akan memaksanya untuk disimpan dalam SRAM daripada flash.Mengapa ini penting?
Pada PIC18s, menggunakan direktif db (databyte untuk menyimpan byte dalam memori program) dengan jumlah byte yang ganjil (seperti dalam kasus Anda) akan secara otomatis mengisinya dengan nol. Perilaku ini berbeda dari PIC16, yang mungkin mengapa ia bekerja pada satu tetapi tidak yang lain. Karena alasan ini, string atau karakter yang disimpan dalam memori flash juga tidak akan berfungsi dengan fungsi string standar apa pun, seperti strcpy atau printf. Menyimpan sesuatu dalam memori program tidak secara otomatis mengetik aman.
Berdasarkan perakitan, cukup jelas bahwa memuat 8 byte yang salah. Yaitu 0x00, jadi benar mengirim 0x00 (karena Anda telah benar-benar mengkonfirmasi sedang melakukan).
Mungkin sulit untuk memprediksi apa yang akan Anda dapatkan dengan optimisasi kompiler yang gila hari ini, jadi saya tidak yakin apakah ini akan berhasil. trik volatile akan berfungsi, tetapi jika Anda benar-benar ingin itu disimpan dalam flash, coba ini:
TXREG = data & 0xff;
atau mungkin
TXREG = data & 0x0ff;
Saya tahu secara teori, ini seharusnya tidak melakukan apa-apa. Tetapi kami mencoba untuk mengubah output perakitan dari compiler untuk melakukan apa yang kita inginkan, dan tidak mengurutkan tetapi tidak benar-benar apa yang kita inginkan.
Dari Panduan Pengguna MPASM:
Saya juga merekomendasikan memeriksanya sendiri , serta code_pack, dalam PDF. Halaman 65.
sumber