Değişken karakterleri UART'a yazdırmak işe yaramıyor, sabitler iyi çalışıyor


9

Bir PIC18F27K40 mikrodenetleyici üzerinde XC8 ile oldukça garip bir sorun var. Bir PIC16F1778 üzerinde çalışır . Ben tanımladım:

void uart_putch(unsigned char byte) {
    while (!PIR3bits.TX1IF);
    TX1REG = byte;
}

Ne zaman, benim de maindöngü, arayacağım uart_putch('a');, bu cezayı çalışır. Ancak, tanımlayıp const char c = 'a';aradığımda uart_putch(c);işe yaramıyor. Bir şey yazdırmasa da, bir şey değil a- sanırım onlar 0x00karakterlerden oluşuyor hexdump -x /dev/ttyUSB0. Bu, bilgisayarımdaki seri bağlantı noktasıyla ilgili bir sorun değil; Bir kapsam ile baktım ve sinyal farklı (sol işler, sağ değil):

resim açıklamasını buraya girin

Kod basit:

void main(void) {
    init(); // Sets up ports and UART control registers
    while (1) {
        uart_putch('a'); // or c
    }
}

Ne işe yaramıyor ilişkili olduğunu düşünüyorum dize işlevleri ( puts, printfvb.), Herhangi birini kullanmak - bu yüzden bu soruda karakterlerle minimal bir çalışma örneği yaptı.

Bir değişken kullandığımda oluşturulan derleme cvardır:

_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

Ve bir sabitle _mainblokta var:

    movlw   (061h)&0ffh 
    call    _putch

Parça desteği sürüm 1.41 ile MPLAB XC8 C Derleyici V1.41 (24 Ocak 2017) kullanıyorum.

Makefile'mın ilgili kısımları:

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 $<

Bu çalışmayı sağlamak için herhangi bir yardım çok takdir edilecektir.


1
Uart_putch öğenizi "uart_putch (const char & c)" olarak tanımlayın. Buna "referans ile geçme" denir.
Rohat Kılıç

1
@ RohatKılıç Bu C ++
SoreDakeNoKoto

1
@tcrosley Bunu eklemek istedim, üzgünüm. Bir fark yaratmıyor (hala çalışmıyor). Ben hepsini denedim unsigned char, char, const unsigned charve const char.

1
Putch () tanımınızda, byteTxbunun yerine argümanı yeniden adlandırırsanız ne olur ? byteBaşka bir yerde bir veri türü olarak tanımlanmış olabilir endişeliyim . (Bu bir derleyici tanılama üretecek gibi görünüyor, ama açıkça burada garip bir şey oluyor.) Ve başka bir test olarak, putch(0x61)yanlış davranış aynı şekilde putch('a')mi? Tablo okuma talimatının 8 bit mi yoksa 16 bit veri mi okuduğunu merak ediyorum. PIC W kaydı sadece 8 bit, değil mi?
MarkU

2
@MarkU bir PIC16F1778 üzerinde denedim ve aynı şey iyi çalışıyor. (bu da her iki çip ile de iyi olduğum için benim için çok daha az kötü bir sorun haline getiriyor, ancak yine de 18F27K40'ın nasıl çalışacağını bilmek isterim ..)

Yanıtlar:


3

Programınız iyi, PIC18F27K40 üzerinde bir hata.

Bkz. Http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf

XC8 compilier V1.41 ve mplabx IDE'yi kullanın, XC8 Global options / XC8 linker'ı seçin ve "Ek seçenekler" i seçin, ardından +nvmregErrata kutusuna ekleyin ve hepsi iyi olacaktır.

Bağlantılı dokümandan alıntı, kalın olarak işaretlenmiş anahtar kelimeler:

TBLRD, NVMREG değerinin uygun belleği göstermesini gerektirir

PIC18FXXK40 cihazlarının etkilenen silikon revizyonları , çeşitli bellek bölgelerine erişim için kayıttaki NVMREG<1:0>bitlerin yanlış NVMCONayarlanmasını gerektirir TBLRD. Sorun en çok kullanıcı bir const türü tanımladığında ve derleyici verileri program Flash belleğinden (PFM) almak için TBLRDyönergeler kullandığında derlenmiş C programlarında belirgindir . Sorun, kullanıcı RAM'de, daha önce çalıştırılan ve PFM'den RAM başlatmak main()için TBLRDyönergeler kullanan başlatma kodunu oluşturduğu bir dizi tanımladığında da belirgindir .


2

const karakterleri program belleğinde (flash) saklanır ve derleyici bunu değişken olarak kullanmadığınızı (hiç değişmediği için) görüyor ve const kullansanız da kullanmasanız da program belleğine optimize ediyor gibi görünüyor.

Olarak bildirmeyi deneyin volatile char c= 'a';. Bu, flaş yerine SRAM'da saklanmasını zorlayacaktır.

Bu neden önemli?

PIC18'lerde, tek bir baytla (durumunuzda olduğu gibi) db yönergesini (bir baytı program belleğine depolamak için veri baytı) kullanmak otomatik olarak sıfırlarla doldurur. Bu davranış PIC16'dan farklıdır, bu yüzden muhtemelen birinde çalışır, ancak diğerinde çalışmaz. Bu nedenle, flash bellekte saklanan dizeler ya da karakterler de strcpy ya da printf gibi standart dizgi işlevleriyle çalışmaz. Program belleğinde bir şey saklamak otomatik olarak güvenli değildir.

Derlemeye bağlı olarak, yanlış 8 bayt yüklediği oldukça açıktır. Hangi 0x00, bu yüzden doğru bir şekilde 0x00 gönderiyor (yaptığınızı iyice doğruladığınız gibi).

Bu gün derleyici optimizasyonu deli miktarı ile ne alacağınızı tahmin etmek zor olabilir, bu yüzden bu işe yarayacak emin değilim. uçucu hile çalışmalıdır, ancak gerçekten flaşta saklanmasını istiyorsanız, şunu deneyin:

TXREG = data & 0xff;

veya muhtemelen

TXREG = data & 0x0ff;

Teoride, bunun hiçbir şey yapmaması gerektiğini biliyorum. Ancak derleyicinin montaj çıktısını istediğimizi yapmak için değiştirmeye çalışıyoruz, gerçekten istediğimiz gibi değil.

MPASM Kullanıcı Kılavuzu'ndan:

resim açıklamasını buraya girin

PDF'de kendiniz ve kod_paketi'ni de kontrol etmenizi öneririz . Sayfa 65.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.