In các ký tự biến thành UART không hoạt động, hằng số hoạt động tốt


9

Tôi có một vấn đề khá lạ với XC8 trên vi điều khiển PIC18F27K40. Trên PIC16F1778, nó hoạt động . Tôi đã xác định:

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

Khi, trong mainvòng lặp của tôi , tôi gọi uart_putch('a');, điều này hoạt động tốt. Tuy nhiên, khi tôi xác định const char c = 'a';và gọi uart_putch(c);, nó không hoạt động. Nó in một cái gì đó, mặc dù không phải là a- tôi nghĩ chúng là những 0x00nhân vật mà tôi có được hexdump -x /dev/ttyUSB0. Đây không phải là vấn đề với cổng nối tiếp trên máy tính của tôi; Tôi đã xem xét một phạm vi và tín hiệu là khác nhau (hoạt động bên trái, bên phải không):

nhập mô tả hình ảnh ở đây

Mã rất đơn giản:

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

Những gì không hoạt động hoặc là sử dụng bất kỳ hàm chuỗi nào ( puts, printfv.v.), mà tôi nghĩ là có liên quan - vì vậy trong câu hỏi này tôi đã làm một ví dụ làm việc tối thiểu với các ký tự.

Tập hợp được tạo khi tôi sử dụng một biến ccó:

_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

Và với một hằng số, nó có trong _mainkhối:

    movlw   (061h)&0ffh 
    call    _putch

Tôi đang sử dụng MPLAB XC8 C Compiler v1.41 (ngày 24 tháng 1 năm 2017), với phiên bản hỗ trợ một phần 1.41.

Các phần có liên quan trong Makefile của tôi:

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

Bất kỳ trợ giúp để có được công việc này sẽ được rất nhiều đánh giá cao.


1
Xác định uart_putch của bạn là "uart_putch (const char & c)". Điều này được gọi là "đi qua tham chiếu".
Rohat Kılıç

1
@ RohatKılıç Đó là C ++
TisteAndii

1
@tcrosley Ý tôi là bao gồm điều đó, xin lỗi. Nó không tạo ra sự khác biệt (vẫn không hoạt động). Tôi đã thử tất cả unsigned char, char, const unsigned charconst char.

1
Trong định nghĩa của bạn về putch (), điều gì xảy ra nếu bạn đổi tên đối số byteTxthay thế? Tôi lo ngại rằng bytecó thể được định nghĩa ở nơi khác là một loại dữ liệu. (Có vẻ như điều đó sẽ tạo ra chẩn đoán trình biên dịch, nhưng rõ ràng có điều gì đó kỳ lạ đang diễn ra ở đây.) Và như một thử nghiệm khác, liệu có putch(0x61)hoạt động sai giống như putch('a')vậy không? Tôi đang tự hỏi liệu hướng dẫn đọc bảng đang đọc dữ liệu 8 bit hay 16 bit. Đăng ký PIC W chỉ có 8 bit, phải không?
MarkU

2
@MarkU vì vậy tôi đã thử trên PIC16F1778 và điều tương tự cũng hoạt động tốt. (điều này làm cho nó trở thành một vấn đề tồi tệ hơn nhiều đối với tôi vì tôi vẫn ổn với một trong hai con chip, nhưng tôi vẫn quan tâm để biết làm thế nào để 18F27K40 hoạt động ..)

Câu trả lời:


3

Chương trình của bạn vẫn ổn, Đó là một lỗi trên PIC18F27K40.

Xem http://ww1.microchip.com/doads/en/DeviceDoc/80000713A.pdf

Sử dụng trình biên dịch XC8 v1.41 và mplabx IDE, chọn XC8 Global Tùy chọn / trình liên kết XC8 và chọn "Tùy chọn bổ sung", sau đó thêm +nvmregvào hộp Errata và tất cả sẽ ổn.

Trích từ tài liệu được liên kết, từ khóa được đánh dấu đậm:

TBLRD yêu cầu giá trị NVMREG để trỏ đến bộ nhớ phù hợp

Các phiên bản silicon bị ảnh hưởng của các thiết bị PIC18FXXK40 yêu cầu không đúng các NVMREG<1:0>bit trong thanh NVMCONghi được đặt để TBLRDtruy cập vào các vùng nhớ khác nhau. Vấn đề rõ ràng nhất trong các chương trình C được biên dịch khi người dùng xác định loại const và trình biên dịch sử dụng các TBLRDhướng dẫn để lấy dữ liệu từ bộ nhớ Flash chương trình (PFM). Vấn đề cũng rõ ràng khi người dùng xác định một mảng trong RAM mà trình biên dịch tạo mã khởi động, được thực thi trước đó main(), sử dụng các TBLRDhướng dẫn để khởi tạo RAM từ PFM.


2

const chars được lưu trữ trong bộ nhớ chương trình (flash) và có vẻ như trình biên dịch đang thấy rằng bạn không sử dụng nó như một biến (vì nó không bao giờ thay đổi) và tối ưu hóa nó vào bộ nhớ chương trình bất kể bạn có sử dụng const hay không.

Hãy thử khai báo nó là volatile char c= 'a';. Điều này sẽ buộc nó được lưu trữ trong SRAM chứ không phải flash.

Vì sao vấn đề này?

Trên PIC18, sử dụng chỉ thị db (databyte để lưu trữ một byte trong bộ nhớ chương trình) với số byte lẻ (như trong trường hợp của bạn) sẽ tự động đệm nó bằng số không. Hành vi này khác với hành vi của PIC16, có lẽ là lý do tại sao nó hoạt động trên một nhưng không phải là khác. Vì lý do này, các chuỗi hoặc ký tự được lưu trữ trong bộ nhớ flash cũng sẽ không hoạt động với bất kỳ chức năng chuỗi tiêu chuẩn nào, chẳng hạn như strcpy hoặc printf. Lưu trữ một cái gì đó trong bộ nhớ chương trình không tự động gõ an toàn.

Dựa trên sự lắp ráp, khá rõ ràng là đang tải sai 8 byte. Đó là 0x00, vì vậy nó gửi chính xác 0x00 (như bạn đã xác nhận hoàn toàn nó đang làm).

Có thể khó dự đoán những gì bạn sẽ nhận được với số lượng tối ưu hóa trình biên dịch điên rồ hiện nay, vì vậy tôi không chắc liệu điều này có hoạt động không. Thủ thuật dễ bay hơi sẽ hoạt động, nhưng nếu bạn thực sự muốn nó được lưu trữ trong flash, hãy thử điều này:

TXREG = data & 0xff;

hoặc có thể

TXREG = data & 0x0ff;

Tôi biết rằng trên lý thuyết, điều này sẽ không làm gì cả. Nhưng chúng tôi đang cố gắng thay đổi đầu ra lắp ráp của trình biên dịch để làm những gì chúng tôi muốn, và không sắp xếp nhưng không thực sự những gì chúng tôi muốn.

Từ Hướng dẫn sử dụng MPASM:

nhập mô tả hình ảnh ở đây

Tôi cũng khuyên bạn nên tự kiểm tra , cũng như code_pack, trong PDF. Trang 65.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.