LPCXpresso と USB シリアル変換モジュール マイコンからデータを送信する~後編~

 NXPセミコンダクタ社LPCXpresso 基板と PC の端末エミュレータを使って,マイコンからデータを送るためのプロジェクトを作成しました.いよいよ,プログラムを作成します.

データを送信するプログラム

 ここで作成されるアプリケーションは,すべて main.c ファイルの中に記述されます.

main.cファイルを開く

 まずは, main.c ファイルをエディタで開きます.プロジェクト・エクスプローラで,プロジェクト proj03a にあるソースファイル src/main.c をダブルクリックします.

 そして開いたテキスト・エディタに,以下のプログラムを入力します.

/*
===============================================================================
 Name        : main.c
 Author      : noritan
 Version     : 1.0
 Copyright   : Copyright (C) 2010 noritan.org
 Description : main definition
===============================================================================
*/

#ifdef __USE_CMSIS
#include "LPC11xx.h"
#endif

// Flag mask for UART_LSR register.
const uint32_t		LSR_THRE = 0x20;

// Initialize UART module with specified baud-rate
void uart_init(uint32_t baudrate) {
    // Divisor ratio
    uint32_t                    Fdiv;

    // Configure P1[7] as TXD output.
    LPC_IOCON->PIO1_7 &= ~0x07;         // FUNC=000 (GPIO)
    LPC_IOCON->PIO1_7 |= 0x01;          // FUNC=001 (TXD)

    // Enable UART clock
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);   // UART=1

    // Enable UART peripheral clock
    LPC_SYSCON->UARTCLKDIV = 0x01;      // DIV=1

    // Calculate baud rate divisor
    Fdiv = (
            SystemCoreClock             // System clock frequency
          * LPC_SYSCON->SYSAHBCLKDIV    // AHB clock divider
        ) / (
            LPC_SYSCON->UARTCLKDIV      // UART clock divider
          * 16 * baudrate               // baud rate clock
        );

    // Set the baud rate divisor value
    LPC_UART->LCR |= 0x80;
    LPC_UART->DLM = Fdiv / 256;
    LPC_UART->DLL = Fdiv % 256;
    LPC_UART->LCR &= ~0x80;

    // Configure UART module as
    //   8 bit, 1 stop bit, no parity
    //   Enable and reset TX and RX FIFO.
    LPC_UART->LCR = 0x03;
    LPC_UART->FCR = 0x07;
}

// send a character via TXD
void uart_putc(const char c) {
    // Wait for TX buffer empty
    while (!(LPC_UART->LSR & LSR_THRE));
    // Put a character
    LPC_UART->THR = c;
}

// send a string via TXD
int uart_puts(const char *s) {
    int n;
    for (n = 0; *s; s++, n++) {
        uart_putc(*s);
    }
    return n;
}

// Main loop
int main(void) {
    uart_init(9600);
    uart_puts("HELLO WORLD\r\n");

    // Enter an infinite loop, just incrementing a counter
    volatile static int i = 0 ;
    while(1) {
        i++ ;
    }
    return 0 ;
}

 少々長いので,部分ごとに解説していきます.

UARTの初期設定

 uart_init() 関数は, UART を初期設定するための関数です.このプロジェクトでは, UART の送信機能だけを初期設定しています.初期設定は,以下の順序で進められます.

  • ポート機能の設定

    LPC11xx の各端子は,リセット直後は General Purpose I/O(GPIO:汎用入出力端子)として設定されています.そのため, UART の TXD 出力端子を使用するときには,端子の設定を行わなくてはなりません.

    LPC11xx では,UART の TXD 機能は,端子 P1[7] に割り当てることができます.この端子への機能割り当てを行うレジスタが, LPC_IOCON->PIO1_7 です.このレジスタの LSB 3ビットに 001 を設定すると, P1[7] 端子が TXD 出力として使用されます.

    TXD 機能を割り当てることで,端子 P1[7] は,自動的に出力に設定されます.そのため,端子の入出力方向をさらに指定する必要はありません.

  • UARTモジュールにクロックを供給する

    LPC11xx は,消費電力を抑制するために,リセット直後はほとんどのペリフェラルのクロックを停止しています. UART モジュールも例外ではなく,そのままでは使用することができません.

    UART モジュールへのクロック供給を制御しているのが LPC_SYSCON->SYSAHBCLKCTRL レジスタです.この32ビットレジスタのそれぞれのビットが個別ペリフェラルへのクロックの供給・停止を制御しています. UART モジュールへのクロックを制御しているのは,このレジスタのビット12です.

  • ボーレート・ジェネレータにクロックを供給する

    UART モジュールには,モジュールへ供給するクロック以外にもうひとつクロックを供給する必要があります.これは,ペリフェラル・クロックと呼ばれています.

    ペリフェラル・クロックは, UART の通信速度を決めるために使用されるクロックで,独立した8ビットの可変分周器から出力されます.

    この分周器の分周比は, LPC_SYSCON->UARTCLKDIV レジスタで決定されます.このプログラムでは,レジスタに "1" を書き込むことにより,分周比 "1" でペリフェラル・クロックを生成しています.

  • ボーレートを決定する

    UART の通信速度を最終的に決定するのが,ボーレート・クロックです.ボーレート・クロックには,通信速度(ボーレート)の16倍のクロックを与えます.

    ボーレートは,ペリフェラル・クロックを分周して作りますが,分周比は,それぞれ8ビットのレジスタ LPC_UART->DLMLPC_UART->DLL によって,決定されます.分周比の計算方法は,次の節で説明します.

  • UARTを起動する

    最後に, UART モジュールを起動します.起動する際には, LPC_UART->LCR レジスタを使用する転送フォーマットに従い設定します.また, LPC_UART->FCR レジスタを設定して,入出力バッファの初期化を行います.

ボーレートの設定の仕組み

 UART の初期設定で手間取るのが,ボーレートの設定です.ローエンド・マイコンの場合,ボーレートの計算に必要とされる比較的高精度な割り算を行うほどの計算能力を持っていないので,コンパイル時に計算してハード・コーディングすることが多いかと思います.このプロジェクトでは,32ビットのプロセッサを使用している LPC11xx の特性を活かし,実行時に計算させる方式を採用しています.

ボーレート・クロックの生成

 この図は,ボーレート・クロックを生成する分周器の模式図です.LPC11xx 内部で生成された 48MHz main_clock は,システム・クロック分周器を経て, system_clock というクロックとなり, UART を含む各周辺回路に供給されます.

 一方, main_clock は,ボーレート・クロックを生成するためにも使用され,こちらは,ペリフェラル・クロック分周器とボーレート分周器の二つの分周器で分周されます.

 system_clock の周波数は,スタートアップ時に SystemCoreClock という変数に格納されます.この値と必要な通信速度からボーレート分周器の分周比を求めるには,以下の計算を行います.

分周比の計算

 main_clock の周波数は,最大でも100MHz程度なので,十分に32ビットで計算することができます.

1文字送信関数

 uart_putc() 関数は, UART から1バイトのデータを送信します. LPC_UART->THR レジスタにデータを書き込むだけでデータを送信することができますが,この時にUARTが送信すべきデータを受け取る準備ができているかを確認する必要があります.準備が完了したことを示すのが,LPC_UART->LSRレジスタのTHREフラグです.

// send a string via TXD
int uart_puts(const char *s) {
    int n;
    for (n = 0; *s; s++, n++) {
        uart_putc(*s);
    }
    return n;
}

 この関数では,THREフラグがクリアされるまでwhile文で待ち,送信するデータをLPC_UART->THRレジスタに書き込んでいます.

 この1文字送信関数を使って,文字列送信関数uart_puts()も用意されています.

メイン関数

 メイン関数での主要な仕事は,UARTの初期化を行って,文字列を送信するだけの簡単なものです.

    uart_init(9600);
    uart_puts("HELLO WORLD\r\n");

 ボーレートに9600ボーを指定して,あいさつ文を送信します.あいさつ文を送信した後は,無限ループに入るため,プログラムは停止することなく走り続けます.

デバッガを起動する

 プログラムの準備ができたら,マイコンに書き込みます.まずは,プロジェクトをビルドします.

プロジェクトをビルドする

 「クイック・スタート・ビュー」のStart hereタブにあるBuild 'proj03a' [Debug]メニューアイテムをクリックして,プロジェクトのビルドを行います.

ビルド完了

 ビルドが完了したら,コンソール・ビューにバイナリ・ファイルの情報が表示されます.プログラムは,1912バイトになりました.

デバッガを起動する

 次は,プログラムの書き込みからデバッガの起動まで進めます.

 USBシリアル変換モジュールのUSBケーブルとLPC-LinkモジュールのUSBケーブルをPCに接続します.そして,「クイック・スタート・ビュー」のStart hereタブにあるDebug 'proj03a' [Debug]メニューアイテムをクリックします.これで,プログラムの実行待ち状態までたどり着きました.

デバッガを起動すると,LPCXpresso開発環境は,USBに接続されたLPC-Linkを探しにいきます.このとき,複数のLPC-Linkが接続されていた場合,LPCXpresso開発環境には,どのLPC-Linkに接続すればいいのか,判断できません.


接続するLPC-Linkを指定する

そこで,このようなダイアログを表示して,接続すべきLPC-Linkをユーザに選択させます.

今回の場合,USBに接続されたLPC-Linkは,一つだけです.にも関わらず,このダイアログが表示されてしまいます.これは,USBシリアル変換モジュールがLPC-Linkと紛らわしい動作をするため,LPCXpresso開発環境が,誤って検出してしまったものと思われます.

このような場合でも,リストの中からLPC-Linkを探し出して,OKボタンをクリックすれば,デバッガを起動することができます.あわてず,さわがず,対処しましょう.


プログラムを実行する

 プログラムの実行準備ができたら,端末エミュレータソフトを起動します.ボーレートなどの設定は,今までと同じです.

実行継続ボタン

 そして,デバッグ・ビューの実行継続ボタンをクリックして,プログラムを実行させます.

あいさつ文表示

 すると,端末エミュレータには,あいさつ文が表示されます.これで,このプロジェクトは,完成です.お好みのあいさつ文を入れて,動作を確認してみてください.

実行終了ボタン

 プログラムは,無限ループで構成されているので,そのままでは停止しません.プログラムを停止させるためには,実行終了ボタンをクリックします.

田中範明(noritan.org)


| | トラックバック(0)

トラックバック(0)

このブログ記事を参照しているブログ一覧: LPCXpresso で UART シリアル通信 (7)

このブログ記事に対するトラックバックURL: http://www.eleki-jack.com/mt/mt-tb.cgi/4830





カテゴリ


Copyright (C) 2006-2015 CQ Publishing Co.,Ltd. All Rights Reserved.