STM32 ゼロから始めるローパワーマイコン SPIで温度センサーとつなぐ

STM32 ゼロから始めるローパワーマイコン SPIで温度センサーとつなぐ

皆さま こんにちは。

今回はSPIによる温度センサモジュールとつないでみます。

投稿時の開発環境を記しておきます。

PC:Windows10 OS
IDE: STM32CubeIDE Version1.3.0
Configurator: STM32CubeMX Version5.6.0
マイコン: STM32L010F4P6
Board: 自作のボード

回路図

回路図は以下の通りです。
ADCを使ってスイッチを読み分ける の回路に温度センサーモジュールを追加した回路になっています。

温度センサーモジュールは秋月で売っている こちら を使ってみました。

回路図はICそのものをつないだ図になっていますがICの端子名とモジュール基板の端子名が同じなので確認して接続してください。

マイコン側との接続を表にしましたので参考にしてください。

使用するプロジェクト

UARTに出力するので STM32 ゼロから始めるローパワーマイコン ADCを使ってスイッチを読み分ける でつくったプロジェクトを改造して使っていきます。

iocファイルをダブルクリックして開き、Pinout & Configuration でマイコンの11,12,13番ピンをSPIの端子に設定します。

PA5を右クリックして選択し、SPI1_SCK を選択します。
PA6を右クリックして選択し、SPI1_MISO を選択します。
PA7を右クリックして選択し、SPI1_MOSI を選択します。

下記の画像を参考にしてください。

そして Pinout & Configuration – Categories – Connectivity – SPI1 を選択し、
SPI1 Mode and Configuration – Mode のリストから Full Duplex Master を選択します。

送受信の線があるので全2重通信を選択するわけです。

Hardware NSS Signal は Disable のままにしておきます。

これは CS(チップセレクト)信号をソフトウェアで行うようにしています。
通信の前後で GPIO を制御します。

このセンサーの仕様におけるSPIのパラメーターは以下の通りに設定します。

Project Explorer で F401SPiHAL を選択し、Project – Build Project でビルドします。

main.cに MX_SPI1_Init()が生成されてエラーがないことを確認します。

コードを編集・追加する

TIM2の割り込み処理

region `FLASH’ overflowed by xxx bytes というエラーが出てしまいました。

今回は使わないのでstm32l0xx_it.cにあるTIM2_IRQHandler()内の処理はコメントアウトしてください。

初期化処理もコメントアウトする

使わないので以下の部分もコメントアウトしておきます。

// init(&qd); // queue initialize
// HAL_TIM_Base_Start_IT(&htim2);

whileループまわり

#include <string.h>

  HAL_StatusTypeDef s;
  uint8_t sbuf[16], rbuf[16];
  uint8_t sbuf2[16];
  uint32_t temp;

  sbuf[0] = 0x54;
  sbuf[1] = 0x00;

  rbuf[0] = rbuf[1] = 0x00;

  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  s = HAL_SPI_TransmitReceive(&hspi1, sbuf, rbuf, 1, 1000);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

  HAL_Delay(1000);

  while (1)
  {
    sbuf[0] = 0x00;

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    s = HAL_SPI_TransmitReceive(&hspi1, sbuf, rbuf, 2, 1000);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

    if (HAL_OK == s)
    {
      temp = rbuf[0] << 8 | rbuf[1];
      temp >>= 3;
    }
    int dt;
    int sign;

    if (temp & 0x1000)
    {
      temp ^= 0xfff;
      temp += 1;
      sign = 1;
    }
    else
    {
      sign = 0;
    }
    dt = temp >> 4; // *0.0625 = 1/16

    int c10, c01;

    c10 = dt / 10;
    c01 = dt % 10;

    strcpy(sbuf2, "Temperature=");

    sign ? (sbuf2[11] = '-') : (sbuf2[11] = '+');
    sbuf2[12] = c10 | '0';
    sbuf2[13] = c01 | '0';
    sbuf2[14] = '\r';
    sbuf2[15] = '\n';

    HAL_UART_Transmit(&huart2, (uint8_t*)sbuf2, 16, 10);
    HAL_Delay(1000);
  }

コード概要

SPIの場合、SPIの仕様の他にデバイス固有の仕様を理解する必要があります。

ADT7310の場合、最初に1バイト 0x54 を書き込むと、後は何か2バイト送るとそのクロックを使って2バイトの温度データを受け取ることができます。

while()ループ内で送っている sbufの中は何でも良く、rbufに2バイトのデータを受けとるために必要です。

rbufに受信した2バイトのデータの内、下3ビットは温度データではないので、3回右シフトして捨てています。

残りの13ビットのうちのMSBが符号で、このビットが1なら負数として扱い2の補数をとります。

1ビットは 0.0625℃ということなので、1/16するために更に4回右シフトしています。

そして文字列にして UART で送信しています。

適度なインターバルがないと、うまく変換できなかったりするようです。。

詳しくは ADT7310 からデータシートをご覧になってください。

いかがでしたか?

うまく通信できたでしょうか?

お疲れさまでした。

LowPowerカテゴリの最新記事