Mencetak karakter variabel ke UART tidak berfungsi, konstanta berfungsi dengan baik

9

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 mainlingkaran 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 0x00karakter, 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):

masukkan deskripsi gambar di sini

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,, printfdll.), Yang saya pikir terkait - jadi dalam pertanyaan ini saya membuat contoh kerja minimal dengan karakter.

Rakitan yang dihasilkan saat saya menggunakan variabel cmemiliki:

_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 _mainblok:

    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.


sumber
1
Tentukan uart_putch Anda sebagai "uart_putch (const char & c)". Ini disebut "lewat referensi".
Rohat Kılıç
1
@ RohatKılıç Itu adalah C ++
TisteAndii
1
@ tcrosley saya bermaksud memasukkan itu, maaf. Itu tidak membuat perbedaan (masih tidak berfungsi). Saya mencoba semua unsigned char, char, const unsigned chardan const char.
1
Dalam definisi Anda tentang putch (), apa yang terjadi jika Anda mengganti nama argumen byteTx? Saya khawatir yang bytemungkin 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, apakah putch(0x61)berperilaku salah dengan cara yang sama putch('a')? Saya bertanya-tanya apakah instruksi membaca tabel membaca data 8-bit atau 16-bit. Register PIC W hanya 8 bit, kan?
MarkU
2
@ Marku jadi saya mencoba pada PIC16F1778 dan ada hal yang sama berfungsi dengan baik. (yang membuatnya menjadi masalah yang jauh lebih buruk bagi saya karena saya baik-baik saja dengan kedua chip, tapi tetap saya akan tertarik untuk mengetahui cara mendapatkan 18F27K40 untuk bekerja ..)

Jawaban:

3

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 +nvmregdalam kotak Errata dan semua akan baik-baik saja.

Kutipan dari dokumen tertaut, kata kunci bertanda tebal:

TBLRD membutuhkan nilai NVMREG untuk menunjuk ke memori yang sesuai

Revisi silikon yang terpengaruh pada perangkat PIC18FXXK40 secara tidak tepat membutuhkan NVMREG<1:0>bit dalam NVMCONregister yang ditetapkan untuk TBLRDmengakses berbagai wilayah memori. Masalahnya paling jelas dalam program C yang dikompilasi ketika pengguna mendefinisikan tipe const dan kompiler menggunakan TBLRDinstruksi untuk mengambil data dari program Flash memory (PFM). Masalahnya juga jelas ketika pengguna mendefinisikan array dalam RAM yang pembuatnya membuat kode start-up, dieksekusi sebelumnya main(), yang menggunakan TBLRDinstruksi untuk menginisialisasi RAM dari PFM.

Ian Munro
sumber
2

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:

masukkan deskripsi gambar di sini

Saya juga merekomendasikan memeriksanya sendiri , serta code_pack, dalam PDF. Halaman 65.

metacollin
sumber