การพิมพ์อักขระตัวแปรไปยัง UART ไม่ทำงานค่าคงที่ทำงานได้ดี


9

ฉันมีปัญหาที่ค่อนข้างแปลกด้วย XC8 ในไมโครคอนโทรลเลอร์ PIC18F27K40 ใน PIC16F1778 มันใช้งานได้ ฉันได้กำหนด:

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

เมื่อในของฉันmainห่วงผมเรียกuart_putch('a');นี้ทำงานได้ดี อย่างไรก็ตามเมื่อฉันกำหนดconst char c = 'a';และโทรuart_putch(c);มันไม่ทำงาน มันพิมพ์อะไรบางอย่าง แต่ไม่ได้a- ฉันคิดว่าพวกเขาเป็นตัวละครที่ฉันได้รับจาก0x00 hexdump -x /dev/ttyUSB0นี่ไม่ใช่ปัญหากับพอร์ตอนุกรมในคอมพิวเตอร์ของฉัน ฉันมองด้วยขอบเขตและสัญญาณแตกต่างกัน (ทำงานซ้ายใช่ไหม):

ป้อนคำอธิบายรูปภาพที่นี่

รหัสง่าย ๆ :

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

สิ่งที่ใช้งานไม่ได้ก็คือการใช้ฟังก์ชั่นสตริงใด ๆ ( puts, printfฯลฯ ) ซึ่งฉันคิดว่ามีความเกี่ยวข้อง - ดังนั้นในคำถามนี้ฉันได้ทำตัวอย่างการทำงานกับตัวละครน้อยที่สุด

แอสเซมบลีที่สร้างขึ้นเมื่อฉันใช้ตัวแปรcมี:

_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

และด้วยค่าคงที่มันมีอยู่ใน_mainบล็อก:

    movlw   (061h)&0ffh 
    call    _putch

ฉันใช้ MPLAB XC8 C คอมไพเลอร์ V1.41 (24 มกราคม 2017) พร้อมส่วนสนับสนุนรุ่น 1.41

ส่วนที่เกี่ยวข้องของ 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 $<

ความช่วยเหลือในการทำงานนี้จะได้รับการชื่นชมอย่างมาก


1
กำหนด uart_putch ของคุณเป็น "uart_putch (const char & c)" สิ่งนี้เรียกว่า "การส่งต่อโดยการอ้างอิง"
Rohat Kılıç

1
@ RohatKılıçนั่นคือ C ++
TisteAndii

1
@tcrosley ฉันต้องการรวมไว้ด้วยขอโทษ มันไม่ได้สร้างความแตกต่าง (ยังไม่ทำงาน) ฉันพยายามทั้งหมดunsigned char, char, และconst unsigned char const char

1
ในนิยามของ putch () จะเกิดอะไรขึ้นถ้าคุณเปลี่ยนชื่ออาร์กิวเมนต์byteTxแทน ฉันกังวลว่าbyteอาจถูกกำหนดไว้ที่อื่นเป็นประเภทข้อมูล (ดูเหมือนว่าจะสร้างเรียบเรียงวินิจฉัย แต่อย่างชัดเจนสิ่งที่แปลกเกิดขึ้นที่นี่.) และการทดสอบอีกไม่putch(0x61)เกเรแบบเดียวกับputch('a')? ฉันสงสัยว่าคำสั่งการอ่านตารางกำลังอ่านข้อมูล 8 บิตหรือ 16 บิต แม้ว่า PIC W ลงทะเบียนแล้วเพียง 8 บิตใช่ไหม?
MarkU

2
@ MarkU ดังนั้นฉันจึงลองใน PIC16F1778 และมีสิ่งเดียวกันทำงานได้ดี (ซึ่งทำให้เป็นปัญหาที่เลวร้ายน้อยกว่ามากสำหรับฉันเพราะฉันใช้ได้กับชิปตัวใดตัวหนึ่ง แต่ก็ยังสนใจที่จะทราบวิธีการใช้ 18F27K40 ในการทำงาน .. )

คำตอบ:


3

โปรแกรมของคุณใช้ได้ดีมันเป็นข้อบกพร่องของ PIC18F27K40

ดูhttp://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf

ใช้คอมไพเลอร์ XC8 V1.41 และ mplabx IDE เลือก XC8 Global options / XC8 linker และเลือก "ตัวเลือกเพิ่มเติม" จากนั้นเพิ่ม+nvmregในกล่อง Errata และทุกอย่างจะเรียบร้อย

ตัดตอนมาจากเอกสารที่เชื่อมโยงคำหลักที่ทำเครื่องหมายเป็นตัวหนา:

TBLRD ต้องการค่า NVMREG เพื่อชี้ไปยังหน่วยความจำที่เหมาะสม

การแก้ไขซิลิกอนที่ได้รับผลกระทบของอุปกรณ์ PIC18FXXK40 จำเป็นต้องมีNVMREG<1:0>บิตในNVMCONรีจิสเตอร์อย่างไม่เหมาะสมเพื่อให้สามารถTBLRDเข้าถึงพื้นที่หน่วยความจำที่หลากหลาย ปัญหานี้ปรากฏชัดเจนที่สุดในโปรแกรม C ที่คอมไพล์เมื่อผู้ใช้กำหนดประเภท constและคอมไพเลอร์ใช้TBLRDคำแนะนำเพื่อดึงข้อมูลจากโปรแกรมหน่วยความจำแฟลช (PFM) ปัญหานี้จะปรากฏขึ้นเช่นกันเมื่อผู้ใช้กำหนดอาเรย์ใน RAM ที่ผู้ประกอบการสร้างรหัสเริ่มต้นที่ดำเนินการก่อนหน้าmain()นี้ซึ่งใช้TBLRDคำแนะนำในการเริ่มต้น RAM จาก PFM


2

ตัวอักษร const จะถูกเก็บไว้ในหน่วยความจำของโปรแกรม (แฟลช) และดูเหมือนว่าคอมไพเลอร์กำลังเห็นว่าคุณไม่ได้ใช้มันเป็นตัวแปร (เนื่องจากมันไม่เคยเปลี่ยนแปลง) และปรับให้เป็นหน่วยความจำของโปรแกรม

volatile char c= 'a';ลองประกาศว่ามันเป็น นี่จะเป็นการบังคับให้เก็บไว้ใน SRAM แทนการใช้แฟลช

เหตุใดเรื่องนี้

ใน PIC18s การใช้คำสั่ง db (databyte เพื่อเก็บข้อมูลไบต์ในหน่วยความจำของโปรแกรม) ด้วยจำนวนไบต์คี่ (เช่นในกรณีของคุณ) จะวางด้วยเลขศูนย์ พฤติกรรมนี้แตกต่างจาก PIC16 ซึ่งอาจเป็นเหตุผลว่าทำไมจึงใช้งานได้ แต่ไม่ได้ใช้งาน ด้วยเหตุผลนี้สตริงหรือตัวอักษรที่จัดเก็บในหน่วยความจำแฟลชจะไม่ทำงานกับฟังก์ชั่นสตริงมาตรฐานใด ๆ เช่น strcpy หรือ printf การจัดเก็บบางอย่างในหน่วยความจำของโปรแกรมจะไม่ปลอดภัยโดยอัตโนมัติ

จากแอสเซมบลีมันค่อนข้างชัดเจนว่ากำลังโหลด 8 ไบต์ที่ไม่ถูกต้อง นั่นคือ 0x00 ดังนั้นจะส่งได้อย่างถูกต้อง 0x00 (ตามที่คุณยืนยันอย่างละเอียดว่ากำลังทำอยู่)

มันอาจเป็นเรื่องยากที่จะคาดการณ์ว่าคุณจะได้รับอะไรบ้างกับการเพิ่มประสิทธิภาพของคอมไพเลอร์ในวันนี้ดังนั้นฉันไม่แน่ใจว่ามันจะใช้งานได้หรือไม่ เคล็ดลับการระเหยควรใช้งานได้ แต่ถ้าคุณต้องการให้มันเก็บไว้ในแฟลชลองสิ่งนี้:

TXREG = data & 0xff;

หรืออาจจะเป็น

TXREG = data & 0x0ff;

ฉันรู้ว่าในทางทฤษฎีแล้วสิ่งนี้ไม่ควรทำอะไรเลย แต่เรากำลังพยายามเปลี่ยนเอาต์พุตแอสเซมบลีของคอมไพเลอร์เพื่อทำสิ่งที่เราต้องการและไม่เรียงลำดับ แต่ไม่ใช่สิ่งที่เราต้องการจริงๆ

จากคู่มือผู้ใช้ MPASM:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันยังแนะนำให้ตรวจสอบด้วยตัวคุณเองรวมถึง code_pack ใน PDF หน้า 65

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.