UART通信をする場合、受信時を割り込みをコールバックしてうんぬんかんぬんが正攻法ですが、ポーリングを使うと処理の無駄は発生しますが簡単に実装できるのでここではその楽な方を紹介します。
Screen1にはボタン一つとテキストエリア二つを設置
ボタンで起動するインタラクションを設定。
trigger:Button is clicked
Choose clicked source:button1
Action:Call new virtual function
Function Name:sendHelloWorld
Interaction Name:sendHelloWorld
テキストエリアはtextArea1とtextArea2とする。Typographyには「Default,20px」を使う
wildcard1を追加して、ID の欄の「+」をクリックして以下の通り設定する。
Initial Value:123456789012345678901234567890
Use wildcard buffer:チェックする
Buffer size:30
※Initial Valueに最初に文字を埋めておかないと、後から書き換えできない。Buffer size30に設定していてもIntial Valueが4文字だと後から書き換えるときに4文字までしか書けない。なぜ。
テキストエリアのワイルドカードに使用するTypograpiesの設定をしないと、文字が表示できない。
Texts>Typographies>Default>Wildcard Rangesに「0x20-0x7E」と入力。
STM32CubeIDEでプロジェクトを開いて、STM32U59J-DK2.iocからUARTに割り付けるピンを設定。
「PA2」を「USART2_TX」
「PA3」を「USART2_RX」
に設定する。PA2、PA3はArduinoコンパチソケットの「TX/D1」と「RX/D0」に相当します。
続いて左の「Connectivity」からUARTの設定をおこないます。
ConnectivityからUSART2を選んで「mode」を「Asynchrounous」にします。
/* USER CODE BEGIN Includes */
extern UART_HandleTypeDef huart2;
/* USER CODE END Includes */
#ifndef SCREEN1VIEW_HPP
#define SCREEN1VIEW_HPP
#include <gui_generated/screen1_screen/Screen1ViewBase.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
class Screen1View : public Screen1ViewBase
{
public:
Screen1View();
virtual ~Screen1View() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void sendHelloWorld();
protected:
char sendMsg[50];
};
#endif // SCREEN1VIEW_HPP
#include <gui/screen1_screen/Screen1View.hpp>
#include "stm32u5xx_hal.h"
#include "main.h"
#include <cstring>
Screen1View::Screen1View()
{
strcpy(sendMsg, "Hello World from STM32\r\n");
}
void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();
}
void Screen1View::tearDownScreen()
{
Screen1ViewBase::tearDownScreen();
}
void Screen1View::sendHelloWorld()
{
HAL_UART_Transmit(&huart2,(uint8_t *)sendMsg,strlen(sendMsg),3000);
HAL_Delay(1000);
}
UARTを送信するのにくらべ、受信はデータがいつ入るのか判らないため、少し込み入った処理が必要です。
コールバック関数を使って、受信したら割り込み処理を書ける方法と、ポーリングで定期的に入力データを監視し、データが入ったら処理を行うという方法があります。
今回の実装方法は仕組みが簡単なポーリングを使う方法です。Screnn1View.cpp上のhandleTickEventという関数で定期的にUARTの受信データを監視しています。
/* USER CODE BEGIN Includes */
extern UART_HandleTypeDef huart2;
/* USER CODE END Includes */
#ifndef SCREEN1VIEW_HPP
#define SCREEN1VIEW_HPP
#include <gui_generated/screen1_screen/Screen1ViewBase.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
class Screen1View : public Screen1ViewBase
{
public:
Screen1View();
virtual ~Screen1View() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void handleTickEvent();
virtual void sendHelloWorld();
protected:
char sendMsg[30];
uint8_t rev; // 受信データ
char buffer[100]; // 受信バッファ
uint8_t bufferIndex;
};
#endif // SCREEN1VIEW_HPP
#include <gui/screen1_screen/Screen1View.hpp>
#include "stm32u5xx_hal.h"
#include "main.h"
#include <cstring>
#include <touchgfx/Unicode.hpp>
Screen1View::Screen1View()
: bufferIndex(0)
{
strcpy(sendMsg, "Hello World from STM32\r\n");
}
void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();
}
void Screen1View::tearDownScreen()
{
Screen1ViewBase::tearDownScreen();
}
//UARTの受信用関数
void Screen1View::handleTickEvent()
{
while (HAL_UART_Receive(&huart2, &rev, 1, 100) == HAL_OK) // タイムアウトを短くしてループ
{
buffer[bufferIndex++] = rev;
buffer[bufferIndex] = '\0'; // 終端文字を追加
// 改行が来たら表示
if (rev == '\n' || bufferIndex >= sizeof(buffer) - 1)
{
Unicode::strncpy(textArea1Buffer, buffer, TEXTAREA1_SIZE - 1);
textArea1Buffer[TEXTAREA1_SIZE - 1] = '\0';
textArea1.invalidate();
bufferIndex = 0; // バッファをリセット
break; // 改行またはバッファが満杯になったらループを抜ける
}
}
}
//UARTにメッセージを送る
void Screen1View::sendHelloWorld()
{
HAL_UART_Transmit(&huart2, (uint8_t *)sendMsg, strlen(sendMsg), 3000);
Unicode::strncpy(textArea2Buffer, sendMsg, TEXTAREA2_SIZE - 1);
textArea2Buffer[TEXTAREA2_SIZE - 1] = '\0';
textArea2.invalidate();
HAL_Delay(200);
}
使用ボード:STM32U5G9J-DK2