У меня довольно странная проблема с 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 Compiler 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 $<
Любая помощь, чтобы получить эту работу будет очень цениться.
unsigned char
,char
,const unsigned char
иconst char
.byteTx
вместо этого? Я обеспокоен тем, чтоbyte
может быть определено в другом месте как тип данных. (Похоже, это сгенерирует диагностику компилятора, но здесь явно происходит что-то странное.) И как еще один тест, ведетputch(0x61)
себя так же, как иputch('a')
? Мне интересно, читает ли инструкция чтения таблицы 8-битные или 16-битные данные. PIC W регистр только 8 бит, правда?Ответы:
Ваша программа в порядке, это ошибка на PIC18F27K40.
См. Http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf
Используйте компилятор XC8 V1.41 и mplabx IDE, выберите XC8 Global options / XC8 linker и выберите «Дополнительные параметры», затем добавьте
+nvmreg
в поле «Ошибки», и все будет хорошо.Выдержка из связанного документа, ключевые слова выделены жирным шрифтом:
источник
константные символы хранятся в памяти программы (flash), и похоже, что компилятор видит, что вы не используете его как переменную (поскольку он никогда не изменяется), и оптимизирует его в памяти программы независимо от того, используете ли вы const или нет.
Попробуйте объявить это как
volatile char c= 'a';
. Это заставит его храниться в памяти SRAM, а не во флэш-памяти.Почему это важно?
На PIC18, использование директивы db (размер данных для хранения байта в памяти программы) с нечетным числом байтов (как в вашем случае) автоматически заполняет его нулями. Это поведение отличается от PIC16, поэтому, вероятно, оно работает на одном, а не на другом. По этой причине строки или символы, хранящиеся во флэш-памяти, также не будут работать ни с одной из стандартных строковых функций, таких как strcpy или printf. Хранение чего-либо в памяти программы не является безопасным типом автоматически.
Судя по сборке, довольно ясно, что загружаются не те 8 байтов. Это 0x00, поэтому он правильно отправляет 0x00 (как вы полностью подтвердили, что он делает).
Может быть трудно предсказать, что вы получите с безумным количеством оптимизации компилятора в наши дни, поэтому я не уверен, сработает ли это. изменчивый трюк должен работать, но если вы действительно хотите, чтобы он хранился во флэш-памяти, попробуйте это:
TXREG = data & 0xff;
или возможно
TXREG = data & 0x0ff;
Я знаю, что в теории это не должно делать ничего. Но мы пытаемся изменить вывод сборки компилятора так, чтобы он делал то, что мы хотим, а не в некотором роде, но не совсем то, что мы хотим.
Из руководства пользователя MPASM:
Я также рекомендую проверить это самостоятельно , как и code_pack, в PDF. Страница 65.
источник