9bit serial for LPC11U24

【本記事は、誤りが含まれている可能性がありますので、100%信用するとケガをする可能性があります。】

LPC11U24での9bit目のデータは、パリティエラービットを確認することで取得することができました。

LPC11U24で9bitシリアルを使用する場合、いくつかの注意点があります。 LPC11U24は、シリアルの9bit目を格納するレジスタは用意されていないため、パリティビットレジスタに9bit目のデータを格納します。 しかし、このパリティビットレジスタに直接アクセスする方法はありません。(分かりませんでした。)

以下の手順で9bitシリアルを実現しました。

  • mbedライブラリを用いて、まずは8bitシリアルを構成する
  • パリティ設定で Force0 を指定する。これで9bitシリアル時にパリティエラービットに出てきます。 Force1では無理でした。
  • mbedライブラリには用意されていないので、直接レジスタ設定して9bitモードを有効にする。
  • 割り込み受信などを用いてシリアルデータを受信、このときにパリティエラービットの状態も確認して9bit目を取得

ヘッダーファイルで準備するもの

/*========================================================================

for mbed LPC11U24

      | LPC11U24    | mbed 11U24 
-----------------------------------
RXD   | PIO1.26     | p10
TXD   | PIO1.27     | p9
DE    | PIO0.2      | p8

RS485 rs(p9, p10, p8, 625000);//TX, RX, DE, baud

========================================================================*/

#define RS485ADRMATCH (*((volatile unsigned int *) 0x40008050))       /* RS485ADRMATCH register */
#define RS485CTRL     (*((volatile unsigned int *) 0x4000804C))       /* RS485CTRL register */
#define RS485DLY      (*((volatile unsigned int *) 0x40008054))       /* RS485DLY register */
#define LCR           (*((volatile unsigned int *) 0x4000800C))       /* USART Line Control Register */
#define RBR           (*((volatile unsigned int *) 0x40008000))       /* USART Receiver Buffer Register */
#define LSR           (*((volatile unsigned int *) 0x40008014))       /* USART Line Status Register Read only */
#define FCR           (*((volatile unsigned int *) 0x40008008))       /* USART FIFO Control Register Write only */

プログラムコードで準備するもの(例)

//---------------------------------------------------------------------------------------------------------
RS485::RS485(PinName tx, PinName rx, PinName de, uint32_t baud) : _serial(tx, rx), _de(de)
{
    if(rx == p10)
    {
        _uart = LPC_USART;
        NVIC_SetPriority(UART_IRQn, 1);
    }
    _de = 0;//DE port

    _serial.baud(baud);
//    _serial.format(8, Serial::Forced0 ,1);
    _serial.attach(this, &RS485::int_rx, Serial::RxIrq);

    //USART Line Control Register
//    LCR = 0x0000002B;//Parity force1, Parity generator, stop1bit, 8bit data
    LCR = 0x0000003B;//Parity force0, Parity generator, stop1bit, 8bit data
    FCR = 0;

    //RS485 register settings
    RS485CTRL |= 0x00000001;//9-bit mode on
//    RS485CTRL |= 0x00000003;//9-bit mode on, address mode
    
    rx_count = 0;
    rx_point = 0;
}
//---------------------------------------------------------------------------------------------------------
void RS485::int_rx()
{
    uint32_t flg, dat;

    flg = LSR;
    dat = RBR;

    if((flg & 0x0000000B) == 0x00000001)// FE PARI OVER BUF
    {
        if(rx_count < BUF_SIZE)
        {
            rx_flg[ (rx_point+rx_count) % BUF_SIZE ] = (unsigned char)flg;
            rx_buf[ (rx_point+rx_count) % BUF_SIZE ] = (unsigned char)dat;
            rx_nine[ (rx_point+rx_count) % BUF_SIZE ] = (unsigned char)((flg>>2) & 0x01);// RS-485 ADDR : PARIErr = 1, DATA : PARIErr = 0
            rx_count++;
        }
    }
}

自分のプログラムからの抜粋のため、不要なコメントやここでは利用しない変数などが含まれています。

  • LCR = 0x0000003B;Parity force0, Parity generator, stop1bit, 8bit data

ここで、パリティForce0とします。

  • RS485CTRL |= 0x00000001;9-bit mode on

9bit mode を有効にします。

  • rx_nine[ (rx_point+rx_count) % BUF_SIZE ] = (unsigned char)((flg>>2) & 0x01); RS-485 ADDR : PARIErr = 1, DATA : PARIErr = 0

ここで、9bit目のデータを取得しています。 LSRレジスタの3bit目が、パリティエラービットです。

シリアル通信での9bit目は、RS485通信におけるアドレス/データ認識に利用されることが通例のようです。 そのため、LPC11U24にはこの9bit目が0/1であるか、つまりアドレス/データであるかを自動で判断する機能があります。 その機能を利用すると、アドレス/データ判定のフィルタリングが有効になり、受信した8bitの情報をシリアルバッファに 格納するか否かを自動で処理できるようになります。 これらの機能に関連したレジスタは、RS485ADRMATCHやRS485CTRLです。 詳しいことはデータシート(User Manual)に書いてありますので、横道になることもあり割愛します。


Please log in to post comments.