MSP432 UARTによるPCとの通信

 


MSP-EXP432P401Rの説明書の回路図を見ると、

ピンP1.2と、P1.3はXDS110-ETとつながっていて、UARTのRXD,TXDになっている。これらのピンとPCとの通信することができる。DriverLibのExampleをインポートして動作を確認してみる。


インポートしたらさすがにエラーはないので、ビルトして書き込みを行う。

PCと接続されているCOMポートの番号をデバイスマネジャーで確認する。上の場合は8番側。シリアルの通信ターミナルを開いてキーボードに何か書いて送付するとエコーバックしてくる。
ArduinoIDEをインストールしているならCOMを8番に設定して、シリアルモニタを代用するでもOK


送信した文字がそのままバックして画面に出てくるってしろもの。
でこれで、ボーレートとか必要ところだけ編集すればまあ動かせる。

const eUSCI_UART_ConfigV1 uartConfig =

{

        EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source

        78,                                     // BRDIV = 78

        2,                                       // UCxBRF = 2

        0,                                       // UCxBRS = 0

        EUSCI_A_UART_NO_PARITY,                  // No Parity

        EUSCI_A_UART_LSB_FIRST,                  // LSB First

        EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit

        EUSCI_A_UART_MODE,                       // UART mode

        EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION,  // Oversampling

        EUSCI_A_UART_8_BIT_LEN                  // 8 bit data length

};

EUSCI_A_UART_CLOCKSOURCE_SMCLK:クロックの指定。SMCLK(サブシステム、マスタークロック)速いHSMCLKってのもあるが、SMCLKを指定している。

SMCLKは、DCO(digitally controlled oscillator)をデフォルトでは元にしている。このDCOは、後の方で、12MHzに変更している。(デフォルトでは3MHz)。BRDIVの設定は、

http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html

で計算しろと書いてあるので、必要事項をいれると、パラメーターを計算してくれて、その通りに設定する。UCxBRF とUCxBRS の部分は、それぞれfirstModRegとsecondModRegに対応して、EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATIONはoverSamplingが1の時に。定義が

#define EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION   0x01

となっているので、0x01を書いても同じ。overSamplngが0なら0x00を記載するか、対に定義されているEUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION。


EUSCI_A_UART_NO_PARITY, EUSCI_A_UART_LSB_FIRST, EUSCI_A_UART_ONE_STOP_BITの部分は通信する相手にあわせて変更する。

【ピンアサイン】
    /* Selecting P1.2 and P1.3 in UART mode */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
            GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
説明は割愛
    /* Setting DCO to 12MHz */
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
CSは、Clock systemのこと。
CS_DCO_FREQUENCY_1_5,
CS_DCO_FREQUENCY_3, 
CS_DCO_FREQUENCY_6, 
CS_DCO_FREQUENCY_12, 
CS_DCO_FREQUENCY_24,
CS_DCO_FREQUENCY_48
から選べる。

    /* Configuring UART Module */
    MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
上で定義したuartConfigの内容を反映させて初期化する。

 /* Enabling interrupts */
    MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_Interrupt_enableMaster();   

MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
何か受信したらインターラプトするように設定して、ISRのルーチンに飛ぶようにするコマンド。
MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
ここから3行はUART自体のインターラプトを許容するようにしている。
MAP_Interrupt_enableSleepOnIsrExit();
はインターラプトに入ったら消費電力削減のためにCPUを眠らせるコマンド。

/* EUSCI A0 UART ISR - Echoes data back to PC host */
void EUSCIA0_IRQHandler(void)
{
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
    {
        MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE));
    }
}

MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE)でインターラプトの状態を確認する状態をstatusに代入して、
status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG
何か受信したら、MAP_UART_transmitDataでデータを送信している。
送信内容が、受信したそのものを送るので、MAP_UART_receiveData(EUSCI_A0_BASE)となっている。
UART_receiveData(EUSCI_A0_BASE)で受け取るのは1バイトのみで、1バイトづつエコーして送信している動作になる。

上の例だと、”test"とPCから送っても、t,e,s,tと4回繰り返しているだけで、文字列としては処理できない。

マルチビット(multi bytes)をUARTでPCから受信する例は以下のようになる

mainより上で変数を定義しておく。一つ前の状態を残しておけるように二つ配列を用意しておく。

/* UART_RX variable */
static char UART_RX_buffer[64];
static char UART_RX_buffer_temp[64];
uint8_t UART_RX_buffer_index=0;

IRQハンドラーを以下のようにする。
void EUSCIA0_IRQHandler(void)
{
    char c;
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
    MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);
    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
    {
        c=MAP_UART_receiveData(EUSCI_A0_BASE);
        MAP_UART_transmitData(EUSCI_A0_BASE, c);

        UART_RX_buffer_temp[UART_RX_buffer_index]=c;
        memcpy(UART_RX_buffer, UART_RX_buffer_temp, sizeof(UART_RX_buffer_temp));
        UART_RX_buffer_index++;
        if (c==0x0a){
            memset(UART_RX_buffer_temp, 0x00, sizeof(UART_RX_buffer_temp));
            UART_RX_buffer_index=0;
            }
        }

    MAP_Interrupt_disableSleepOnIsrExit();
}

UART_RX_bufferとUART_RX_buffer_tempでコピーを取得しているのは、改行したら初期化するという処理をするため。
改行コードを読み取ったら、インデックスをゼロに戻して、配列を初期化したいが
コピーを取らないとせっかく取得した文字列が消えるから、改行を受けっとっても前の状態を保持しておくため。

最後の行の、    MAP_Interrupt_disableSleepOnIsrExit();でインターラプトから元のmainのルーチンに戻ることになり、結果が、UART_RX_bufferに格納される。




コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

Attiny85 FuseRest

HS101 STM32の自作お手軽オシロスコープ