皆さま こんにちは。
今回は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 からデータシートをご覧になってください。
いかがでしたか?
うまく通信できたでしょうか?
お疲れさまでした。
コメントを書く