nRF UART

 ちゃんとした評価ボードを触ってきた事もあり、手元にこれまでなかったFT232RLを購入。nRFでUARTを学ぶためにFT232RLをアマゾンでポチリと。”FT232RLチップは本物ではありません”と書いてあるのがたくましい中国製。レビューを見る限りは問題なさそうなので購入。


 安いからいいやと購入したが手にしてわかったのがMini-USBだった事。おいおい・・・ケーブルあったか?とガサガサと、Arduinoで使っていたものが出てきて一安心。

何も考えずに、USBでPCに接続してやる。



デバイスマネージャーで確認するとCOMポートがちゃんと見えている。

【回路の構成】

シルク印刷が見にくいので拡大。3.3V側にジャンパーを設定。上の写真は5Vになっているので写真とは逆。
左から(Data Terminal Ready Control Output / Handshake Signal)、RX,TX,VCC,CTS,
CTS (Clear To Send Control Input / Handshake Signal)GNDになっている。

XAIOのピンマップにはTXはP1.11にRXはP1.12にアサインされている絵を見るがこれはArduinoで利用する場合で、実はどのピンでも対応できる。

あえていうなら、データシートを眺めてみると、

https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf

データシートの7 Hardware and layoutに、”Standard drive, low frequency I/O only”とピンによっては記載されている。じゃあこれらのピンは動かないのか?というとそうではなくて、無線に近いピンので、無線機の動作中に標準駆動または低周波以外の使用に設定すると、無線機に干渉する可能性があるためこのタグが付ついている。動かないって訳ではなく、動作が不安定になる事があるらしい・・・。

がシルク印刷もある事だし、本質的ではないので、TXはP1.11にRXはP1.12を使う事にする。

FT232RLとの接続方法だが、GND-GNDに、RXはTX,TXはRXに接続する。

(この点、TXはTX、RXはRXという解説もあるのでシルク印刷がすべての基板の場合は、試すしかない所あり)


【コード記載基本】

.....SDK\nRF5_SDK_17.1.0_ddde560\examples\peripheral\uart

のフォルダーをmyprojects(自身の作業スペース)にコピーをとる。

\examples\myprojects\6_uart\pca10056\blank\ses

の下のuart_pca10056.emProjectをダブルクリックし開く。

なんどもよっているが、同じフォルダーのflash_placement.xmlをSESにドラックして開きsize="0x4"を2か所削除して保存する。

main.cを編集する。

whileの中身を決して、whileの上もバッサリと。#includeもnrf_uart.fを残すがifとかその周辺も削除してシンプルにしてしまう。(勉強にならないから・・)



unknown type name '__printf_tag_ptr'

でエラーが出たら、retarget.cを削除してしまう。

他に出るエラーとしては、以下のようなもの。


Projectを右クリックして、Option
Commonを選択hして、LibraryでライブラリIOの部分をRTTを選択して
”OK”を押して、さらに”OK”を押すと回避できる。


ここまでは、サンプルコードのエラー対処。ここからUARTの基本的な使い方。

ヘッダーファイルを読み込む。

#include "nrf_uart.h"   

UARTを使う限り必要。nrf_uarte.hを使う事を推奨すると書いてあるが・・

まずUARTの設定をする。

mainの中でwhileより上の部分に

    app_uart_comm_params_t const comm_params =

    {

        .rx_pin_no    = 11+32,

        .tx_pin_no    = 12+32,

        .rts_pin_no   = 0,

        .cts_pin_no   = 0,

        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,

        .use_parity   = false,

        .baud_rate    = NRF_UART_BAUDRATE_115200

    };

app_uart_comm_params_tという構造体で、comm_params という名前をつける。

comm_params は任意なんでなんでもよい。7個のパラメータを設定する

上から

RXピン:ピン番号をいれる。

TXピン:ピン番号をいれる。→P0.5なら5を入れるが、P1.5なら?32を足して37を入れるというルール。

RTSピン:リセットピンを使う場合は指定する。TXとRXだけでよいので、"0"としておいてもよい。

CTSピン:これも使わない。”0”としてもよい。

flow_control :APP_UART_FLOW_CONTROL_DISABLED

APIの中で定義されている

 .use_parity   = false, ここはパリティを使うか?で大抵の場合false。

最後に、baud_rate   :ボーレートの設定。NRF_UART_BAUDRATE_115200の数字の部分をかえればよい事はわかる。(後でこんなん出てくるか!)という点は述べる)

直ぐ下に、APP_UART_FIFO_INITという命令を置く。これは上で定義したパラメータをUARTに反映させると思ってよくINITとあるように初期化をする。

    APP_UART_FIFO_INIT(&comm_params,

                       128, 

                       128,

                       uart_event_handle,

                       APP_IRQ_PRIORITY_LOWEST,

                       err_code

                       );

第一引数 RXのバッファーサイズ

第二引数 TXのバッファーサイズ

第3引数 UARTのイベントが起きた際のハンドラー

第四引数 優先度の設定

第5引数 エラーコードの格納

ここで、イベントがおきた時のハンドラーとエラーコードを空でもよいので入れてあげる必要があるので、定義をする。

まずincludeとmainの間で

void uart_event_handle(app_uart_evt_t * p_event)

{

}

と中身がなくてよいので、uart_event_handleを定義する。
そしてmainが始まったすぐの所に、
   uint32_t                     err_code;
と32ビットのアンサインイントでerr_codeを定義。
最後にAPP_UART_FIFO_INITの下mainの最後部に足す。
    while(1)
    {
       app_uart_put('A');
       nrf_delay_ms(1000);
    }

app_uart_putの命令で8ビットの文字1つを送り込んでやる。


コード全体は、

****************************************************
#include <stdint.h>
#include <string.h>
#include "app_uart.h"
#include "nrf_delay.h"

#include "nrf_uart.h"    

void uart_event_handle(app_uart_evt_t * p_event)
{
}

int main(void)
{
    uint32_t                     err_code;
    app_uart_comm_params_t const comm_params =
    {
        .rx_pin_no    = 11+32,
        .tx_pin_no    = 12+32,
        .rts_pin_no   = 0,
        .cts_pin_no   = 0,
        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
        .use_parity   = false,
        .baud_rate    = NRF_UART_BAUDRATE_115200
    };
    APP_UART_FIFO_INIT(&comm_params,
                       128,
                       128,
                       uart_event_handle,
                       APP_IRQ_PRIORITY_LOWEST,
                       err_code
                       );

    while(1)
    {
       app_uart_put('A');
       nrf_delay_ms(1000);
    }
}
****************************************************


最小構成のUARTの動作が確認できた。

動作を確認できた所で、元にもどって、

 .flow_control = APP_UART_FLOW_CONTROL_DISABLED,

などパラメータを指定しているがそんなAPP_UART_FLOW_CONTROL_DISABLEDなんか出てくるか!!という方、ご心配なく。sdk_configを開いて、Ctrl+Fでuartを検索。

そこにパラメータが入っている。例えば、NRFX_UARTE_DEFAULT_CONFIG_HWFC 0をdefine

NRFX_UARTE_DEFAULT_CONFIG_HWFC 0
とゼロに設定されている。ハードウェアのフローコントロールの意味でHWFC。

.flow_control = APP_UART_FLOW_CONTROL_DISABLED,

.flow_control =NRFX_UARTE_DEFAULT_CONFIG_HWFC

とsdk_configの中で設定できるように,sdk_config内の定義にあわせて名前を入れておく。

とボーレートも同じようにできる。
        .rx_pin_no    = 11+32,
        .tx_pin_no    = 12+32,
        .rts_pin_no   = 0,
        .cts_pin_no   = 0,
        .flow_control = NRFX_UARTE_DEFAULT_CONFIG_HWFC ,
        .use_parity   = false,
        .baud_rate    = NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE

ってな感じ。RXとTXのピンの数字の所、ここは、ボードがpac10056を想定しているので直接叩いているがボードをカスタムでちゃんと指定すればよい。

左のProject Itemの欄でProjectを右クリック、Optionを開いて、Commonをプルダウンで選択。Preprocesserを選択してPreprosessor Definitions をダブルクリック(または右の・・・をクリック)

ボード名を”BOARD_CUSTOM”に変更する。

SDKのフォルダの下にある\components\boardsを開いて、

boards.hを開いて、BOARD_CUSTOMの下にある名前がカスタムボードのピン定義のヘッダーファイルになっているかを確認。

#elif defined(BOARD_CUSTOM)

  #include "xiaonRF52840.h"

#else

xiaonRF52840.hの中を開いて、UARTで用いる定義のピン割り当てを目的のものに変更する。

RX_PIN_NUMBER, TX_PIN_NUMBERを使うピンアサインにあわせて変更する。

またCTS,RTSについては定義不要だがゼロとしておく。HWFCはfaulseとする。

#include "boards.h"をインクルードしてなければして、これらのカスタムボードのピン定義を使う。またバッファーのサイズもメインの上、#includeの下あたりで定義するため

#define UART_RX_BUF_SIZE 128   /**< UART RX buffer size. */

#define UART_TX_BUF_SIZE 128 /**< UART TX buffer size. */

を置いてやる。

#include <stdint.h>
#include <string.h>
#include "app_uart.h"
#include "nrf_delay.h"
#include "boards.h"
#include "nrf_uart.h"    

#define UART_RX_BUF_SIZE 128   /**< UART RX buffer size. */
#define UART_TX_BUF_SIZE 128/**< UART TX buffer size. */

void uart_event_handle(app_uart_evt_t * p_event)
{
}

void uart_init()
{
    uint32_t                     err_code;
    app_uart_comm_params_t const comm_params =
    {
        .rx_pin_no    = RX_PIN_NUMBER,
        .tx_pin_no    = TX_PIN_NUMBER,
        .rts_pin_no   = RTS_PIN_NUMBER,
        .cts_pin_no   = CTS_PIN_NUMBER,
        .flow_control = NRFX_UARTE_DEFAULT_CONFIG_HWFC,
        .use_parity   = NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY,
        .baud_rate    = NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE
    };
    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_event_handle,
                       APP_IRQ_PRIORITY_LOWEST,
                       err_code
                       );
}

int main(void)
{
    uart_init();
    while(1)
    {
       app_uart_put('A');
       nrf_delay_ms(1000);
    }
}


【Uart multi bytes 複数のバイトのやりとり】

app_uart_putは1バイトしか送れない。文字1つだけ。実際はいろいろ送るので複数バイトを送り込みたい。

マイコンからPCへ送る場合は簡単で、文字の数だけforで回せばよい。

static void uart_print(uint8_t data_string[])

{

  static uint8_t str_array[256];

  memcpy(str_array,data_string,strlen(data_string));  

  for (uint32_t i = 0; i < strlen(str_array); i++)

  {

      while (app_uart_put(str_array[i]) != NRF_SUCCESS);

  }

  memset(&str_array,0x00,UART_RX_BUF_SIZE);//clear str_array

}

main()の中をいくつかの変数を定義してやって書き換え、uart_printを呼び出してやる。

 /*test variable*/

    uint8_t unsigned_integer;

    unsigned_integer=5;

    float pi;

    pi=3.141592;


    while(1)

    {

      printf("LED turned on.\n\r");

      sprintf(UART_TX_Buffer,"This is a UART test.\n\r");

      uart_print(UART_TX_Buffer);

  

      sprintf(UART_TX_Buffer,"2+3=%d\n\r",unsigned_integer);

      uart_print(UART_TX_Buffer); 

      sprintf(UART_TX_Buffer,"pi=%.6f\n\r",pi);

      uart_print(UART_TX_Buffer);

      nrf_delay_ms(500);

    }


受け取る側はまたの機会にしたいと思う。









コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

CH9329で日本語キーボード109で正しく表示する方法