ArduinoとSTM32マイコンをつないでマイコンシステム開発をしてみる その19 ~検証実験⑪~
マイコンシステム開発の要件定義から総合テストまでの工程をたどってみます。
題材としては、空調管理システムにします。
機材はいま手元にあるArduino1台とSTM32マイコン1台を使います。
実装に入る前に検証実験をおこないます
以下の3点をおこないます。
① STM32で計測した気温データをSPI通信でArduinoに送信。
1)STM32単体で、計測した気温データをUSB経由で端末エミュレータに出力。(完了)
2)SPI通信でSTM32からArduinoにテストデータを送信。(完了)
② Arduinoは気温データを受信し、LCDに表示。
1)LCDに文字を出力するテスト(完了)
2)受信した気温データをLCDに表示(今回行います)
③ ArduinoからSTM32に制御データを送信し、LEDを点灯。
前回はLCDをブレットボードに配線し、文字を出力するテストをおこないました
今回、Arduinoは気温データを受信し、LCDに表示します。
1.プログラムを作成します
① 気温データを送信するSTM32側のプログラム
while (1)
{
/* 温度測定モードを設定 */
i2cbuf[0] = 0x11; // CTRL_REG2 レジスタアドレス
HAL_I2C_Mem_Write(&hi2c1, I2C_ADDR_W, 0x11, I2C_MEMADD_SIZE_8BIT, i2cbuf, 1, 1000);
/* 測定が完了するまで待機 */
while (1) {
i2cbuf[0] = 0;
HAL_I2C_Mem_Read(&hi2c1, I2C_ADDR_R, 0x27, I2C_MEMADD_SIZE_8BIT, i2cbuf, 1, 1000);
if ((i2cbuf[0] & 0x03) == 0x03) {
break; // 測定完了
}
HAL_Delay(10);
}
/* 温度データを取得 */
HAL_I2C_Mem_Read(&hi2c1, I2C_ADDR_R, 0x2B, I2C_MEMADD_SIZE_8BIT, i2cbuf, 2, 1000);
int16_t raw_temp = (int16_t)((i2cbuf[1] << 8) | i2cbuf[0]); // 2の補数形式のデータを取得
/* 温度を°Cに変換 */
float temperature_celsius = raw_temp / 100.0f;
/* 今回は整数部だけを送信 */
data = (uint8_t)temperature_celsius;
/* SSピンをLOWに設定して通信を開始 */
HAL_GPIO_WritePin(SS_PORT, SS_PIN, GPIO_PIN_RESET);
/* SPIデータ送信 */
if (HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY) != HAL_OK) {
/* エラー処理 */
Error_Handler();
}else{
snprintf(msgbuf, sizeof(msgbuf), "temperature=%.1f°C\r\n", temperature_celsius);
CDC_Transmit_FS((uint8_t *)msgbuf, strlen(msgbuf));
}
/* SSピンをHIGHに設定して通信を終了 */
HAL_GPIO_WritePin(SS_PORT, SS_PIN, GPIO_PIN_SET);
/* 1秒待機 */
HAL_Delay(1000);
}
今回は、センサーで検知した気温データの整数部分のみを送信します。
② 気温データを受信するArduino側のプログラム
#include <SPI.h>
#include <LiquidCrystal.h>
volatile byte receivedData;
volatile bool dataAvailable = false;
// LiquidCrystalオブジェクトの作成(ピン指定)
LiquidCrystal lcd(8, 9, 7, 6, 5, 4);
void setup() {
Serial.begin(9600);
Serial.println("SPI Slave Initialized");
// SPIスレーブの初期化
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE); // SPI Enable
SPCR &= ~_BV(MSTR); // スレーブモード
// 割り込みでデータ受信
SPCR |= _BV(SPIE);
lcd.begin(16, 2); // LCDを16x2モードで初期化
}
ISR(SPI_STC_vect) {
receivedData = SPDR; // 受信データを取得
dataAvailable = true;
}
void loop() {
if (dataAvailable) {
// シリアルモニタに出力
Serial.print("Received Data: ");
Serial.println(receivedData);
dataAvailable = false;
// LCDに出力
lcd.clear();
lcd.print(receivedData);
}
}
2.実行
送信も受信も問題ありません。
シリアルモニタに出力されてます。
LCDの表示も問題ありません。