Arduinoとの通信(lib)

Keil StudioのSerialCtrlのようなライブラリの使用方法

  1. UART_Arduinoライブラリの最新バージョンをダウンロード。

    teams等にある場合が多い。

  2. ダウンロードしたヘッダファイルプロジェクト-Core-Incに、ソースファイルプロジェクト-Core-Srcに移動。

  3. 使用したいソースファイル内等でヘッダファイルをIncludeする。

  4. 使用するUSART.iocファイルで設定しコードを生成。

    [プロジェクト名].ioc-Pinout & Configuration-Connectivity-USART1-ModeAsynchronousConfiguration-Parameter Settings-Basic Parameters-Baud Rate38400に設定。今回はUSART1を使用した。

  5. 使用する関数を記述。

中にはprintfを使用する関数も含まれているため、printfUART通信で使用できるようにしておく。'参考'

使用例1
main.c

// 略
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "USART_Arduino.h"
/* USER CODE END Includes */
// 中略
    /* USER CODE BEGIN 1 */
    setbuf(stdout,NULL);
    /* USER CODE END 1 */
// 中略
    /* USER CODE BEGIN 2 */
    getdata DATA;
    /* USER CODE END 2 */
// 中略
    /* USER CODE BEGIN WHILE */
    while (1)
    {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
        if(getData(&huart1,&DATA) == 0){
            AllShowP(DATA);
        }
    }
    /* USER CODE END 3 */
// 中略
    /* USER CODE BEGIN 4 */
    int _write(int file,char *ptr,int len){
        HAL_UART_Transmit(&huart2, (uint8_t *)ptr, len, 10);
        return len;
    }
    /* USER CODE END 4 */
// 略

上記の使用例では、printfUSART2で使用できるようにし、ArduinoとのUART通信USART1を使用している。また、getdata型のDATAという名前の構造体変数を宣言し、getData関数に引数としてDATAのアドレスを渡している。

使用例2
main.c

// 略
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "USART_Arduino.h"
#include "STprintf.h"
#include "manydef.h"
/* USER CODE END Includes */
// 略
    /* USER CODE BEGIN 2 */
    STprintf(&huart2);
    unsigned int FAFcount = 0;
    /* USER CODE END 2 */
// 略
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        HAL_TIM_PWM_Start(&htim3,TIMCH_3);
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        getDataIT(&huart1);
        printf("%d %d \r\n",FAF,FAFcount);
        if(FAF == 1){
            FAFcount = 0;
            AllShow(data);
            __HAL_TIM_SET_COMPARE(&htim3,TIMCH_3,data.LY);
            HAL_GPIO_WritePin(GPIOxA, GPIO_Pin_0, 0);
        }else{
            FAFcount++;
            if(FAFcount >= TIMEOUT_MAX * 10){
                __HAL_TIM_SET_COMPARE(&htim3,TIMCH_3,0);
                HAL_GPIO_WritePin(GPIOxA, GPIO_Pin_0, 0);
                FAFcount = 0;
                printf("main timeout ");
                HAL_Delay(500);
            }
        }
    }
    /* USER CODE END 3 */
// 略

上記の使用例では、printfUSART2で使用できるようにし、ArduinoとのUART通信USART1を使用している。あらかじめライブラリ内で宣言されている構造体dataLYの値に合わせてLEDが点灯する。FAFとはデータを受信したかどうか記録するフラグ(変数)であり、フラグに合わせてタイムアウトの処理を行っている。タイムアウトの時間や回数などは他の処理の量によって変更した。

各関数に関して

  • getData関数
    • 引数にUART_HandleTypeDef*getdata*をもつ。使用するUSARTの構造体変数のポインタUART_HandleTypeDef*と受信したデータを入れる構造体変数のポインタgetdata*を渡す。
    • getData(&huart1,DATA);
    • 戻り値は、先頭データが0xafであり、構造体に受信データが代入された場合は0、先頭データが0xafでない場合は-1が返される。
    • 受信にはポーリング方式を使用し、データを受信する関数。
  • getDataIT関数
    • 引数にUART_HandleTypeDef*をもつ。使用するUSARTの構造体変数のポインタUART_HandleTypeDef*を渡す。
    • getDataIT(&huart1);
    • 使用にはConfiguration-NVIC Setting-USART1 global interruptEnableに設定する必要がある。
    • 戻り値はなく、受信には割り込み使用し、データを受信する関数。
  • AllShow関数
    • 引数にgetdataをもつ。構造体変数getdataを渡す。
    • AllShow(data);
    • 戻り値はなく、構造体の中身を表示する関数。表示形式はアナログ値をもつスティックなどは整数3桁(空白埋め)で、ディジタル値をもつボタンなどは0/1で表示する。
    • printf関数を使用するため、printfを使用するためのコードが必要になる。'参考'
  • AllShowP関数
    • 引数や戻り値はAllShow関数と同じである。
    • 表示形式はスティックなどはAllShow関数と同じだが、ボタンなどはAllShow関数と異なり、押されているボタンを名前で表示する。送信側のArduinoのシリアルモニタと同じように表示される。

内部で使用される各関数に関して

  • RevAF関数
    • 引数にUART_HandleTypeDef*をもつ。使用するUSARTの構造体変数のポインタUART_HandleTypeDef*を渡す。
    • RevAF(huart);
    • 戻り値は、受信したデータが先頭データ0xafの場合は0xaf、そうでない場合は0x00を、そもそも受信していない場合は0xffを返す。
    • ポーリング方式の際に使用される関数。
  • AddArray関数
    • 引数にUART_HandleTypeDef*uint8_t*をもつ。使用するUSARTの構造体変数のポインタUART_HandleTypeDef*と受信したデータを入れる配列のポインタuint8_t*を渡す。
    • AddArray(huart,Rdata);
    • 戻り値はなく、受信データの総数になるまで受信したデータを配列に順番に代入する。
    • ポーリング方式の際に使用される関数。
  • HAL_UART_RxCpltCallback関数
    • 引数にUART_HandleTypeDef*をもつ。この関数は受信割り込みでデータを受信した時に自動的に実行される。
    • 戻り値はなく、FAFを揚げデータを受信したことを表す。また、getData関数の内部処理のようなことを行う。
    • 割り込みを使用した際に使用される関数。
  • ChSUM関数
    • 引数にuint8_t*をもつ。受信したデータが入った配列のポインタuint8_t*を渡す。
    • 配列の最後のデータが終端データ0xedであるか確認し、終端データである場合、チェックサムを行う。
    • チェックサムとは、各スティックと各ボタンのデータの総和が送信側で計算された総和と一致しているか確認すること。送信側の計算結果も受信データに含まれている。
    • 戻り値は、総和が一致している場合は0xed、そうでない場合は0x00、配列の最後のデータが正しくない場合は0xffを返す。
    • ポーリング方式と割り込みを使用した際のどちらでも使用される関数。
  • AddStruct関数
    • 引数にgetdata*uint8_t*をもち、データを格納する構造体変数のポインタgetdata*と受信データが入ってる配列のポインタuint8_t*を渡す。
    • AddStruct(&data,AIdata);
    • 配列の値から構造体の各要素にデータを代入する。
    • 戻り値はなく、ポーリング方式と割り込みを使用した際のどちらでも使用される関数。
  • StructInit関数
    • 引数にgetdata*をもつ。データを格納する構造体変数のポインタgetdata*を渡す。
    • StructInit(&data);
    • 構造体の各要素を初期化する。LX,LY,RX,RYスティックは0x80に、L2,R2スティックは0x00に、各ボタンは0に初期化される。
    • 戻り値はなく、ポーリング方式と割り込みを使用した際のどちらでも使用される関数。