UARTへの可変文字の印刷が機能せず、定数が正常に機能する


9

PIC18F27K40マイクロコントローラーのXC8でかなり奇妙な問題があります。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
    }
}

どちらも機能しないのは、関連があると思われる文字列関数(putsprintfなど)のいずれかを使用しているため、この質問では、文字を使用して最小限の作業例を作成しました。

変数を使用したときに生成されるアセンブリには、次のものが含まれます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(2017年1月24日)を使用しており、パーツサポートバージョン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)」として定義します。これは「参照渡し」と呼ばれます。
RohatKılıç2017

1
@RohatKılıçC ++です
TisteAndii 2017年

1
@tcrosleyすみません、それを含めるつもりでした。違いはありません(まだ機能しません)。私はすべてを試してみましたunsigned charcharconst unsigned charconst char

1
putch()の定義で、byteTx代わりに引数の名前を変更するとどうなりますか?byte他の場所でデータ型として定義されているのではないかと心配しています。(コンパイラの診断を生成するように見えますが、明らかに何か奇妙なことがここで起こっています。)そして、別のテストとして、putch(0x61)誤動作はputch('a')?テーブル読み取り命令が8ビットまたは16ビットのどちらのデータを読み取るのかと思います。PIC Wレジスタはたった8ビットですよね?
MarkU 2017年

2
@MarkUなので、PIC16F1778を試しましたが、同じことがうまくいきます。(どちらのチップでも問題ないので、問題はずっと少なくなりますが、18F27K40を機能させる方法を知りたいと思っています。)

回答:


3

プログラムは問題ありません。PIC18F27K40のバグです。

http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdfを参照してください

XC8コンパイラV1.41とmplabx IDEを使用し、XC8グローバルオプション/ XC8リンカーを選択し、[追加オプション]を選択+nvmregして、エラータボックスに追加すると、すべて正常に動作します。

リンクされたドキュメントからの抜粋、太字でマークされたキーワード:

TBLRDは、適切なメモリを指すためにNVMREG値を必要とします

影響を受けるPIC18FXXK40デバイスのシリコンリビジョンでは、さまざまなメモリ領域にアクセスするためにレジスタのNVMREG<1:0>ビットを正しく設定する必要があります。この問題は、ユーザーがconst型を定義し、コンパイラーが命令を使用してプログラムのフラッシュメモリー(PFM)からデータを取得する場合に、コンパイルされたCプログラムで最も顕著です。この問題は、コンパイラーが、前に実行され、PFMからRAMを初期化するための命令を使用する起動コードを作成する配列をRAMに定義した場合にも明らかです。NVMCONTBLRDTBLRDmain()TBLRD


2

const charsはプログラムメモリ(フラッシュ)に格納されており、コンパイラが変数として使用していないことを確認し(変更されないため)、constを使用するかどうかに関係なく、プログラムメモリに最適化しているようです。

として宣言してみてくださいvolatile char c= 'a';。これにより、フラッシュではなくSRAMに保存されます。

なぜこれが問題なのですか?

PIC18sでは、dbディレクティブ(プログラムメモリにバイトを格納するためのデータバイト)を奇数バイトで(あなたの場合のように)使用すると、自動的にゼロが埋め込まれます。この動作はPIC16の動作とは異なります。PIC16の動作は、おそらく一方では機能するが、もう一方では機能しない理由です。このため、フラッシュメモリに保存されている文字列や文字も、strcpyやprintfなどの標準の文字列関数では機能しません。プログラムメモリに何かを保存することは、自動的にタイプセーフではありません。

アセンブリに基づいて、間違った8バイトをロードしていることは明らかです。これは0x00なので、0x00を正しく送信します(十分に確認されているため)。

最近の途方もない量のコンパイラ最適化で何が得られるかを予測するのは難しいので、これが機能するかどうかはわかりません。volatileトリックは機能するはずですが、本当にフラッシュに保存したい場合は、これを試してください:

TXREG = data & 0xff;

または多分

TXREG = data & 0x0ff;

理論的には、これは何もしないはずです。しかし、コンパイラーのアセンブリー出力を変更して、私たちが望むことを実行しようとしています。

MPASMユーザーガイドから:

ここに画像の説明を入力してください

また、PDFのcode_packだけでなく、自分確認することもお勧めします。65ページ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.