stm32f405rgtでspi通信(L3GD20)を使ってみる

早速進めていきたいと思います。

 

使用するもの

L3GD20

STM32F405RGT

 

使用するソフト

visual studio code

cmd( makefile , arm-none-eabi-gcc )

 

まずはstm32cubemxでSPI通信の設定をします。

今回はSPI2を Full-Duplex Masterに設定して、どこか一つのポートをGPIO_OUTPUTに設定します。

f:id:sora_siro:20180224155344p:plain

その後、SPIの設定を変更します。

f:id:sora_siro:20180224160233p:plain

SPIの通信速度によってプリスケーラの値は適宜変更してください。

ここで、L3GD20は10Mhzで通信を行えるので10Mhzで設定しました。

あとはGPIO_PIN_OUTPUTのラベルを付けておくと後でソフトを書くときに楽になるのでつけておくことをお勧めします。

 

ここまで設定をしたらコードを作成してもらいましょう。

これで、cubemxでの作業はおしまいです。

 

そしたらvisual studio codeでソフトを書いていこうと思います。(開発環境については)stm32のローカル環境構築のメモ1,stm32のローカル環境構築のメモ2を参照して頂ければ幸いです。

main.c( spi.c)内に記述していきます。

追加で記述したコードです。

// ジャイロ関連
#define WHO_AM_I 0x0F
#define CTRL_REG1 0x20
#define CTRL_REG4 0x23
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D

#define Certain 0xD4
#define POWER_ON 0x0F
#define L3GD20_500dps 0x10
#define L3GD20_2000dps 0x20

#define SETTING 0x80

 

///////////////////////////////////////////////////////////////////////
// spi read 1 byte upper bit ( signed )
// [argument] Register
// [Substitutiong] nothing
// [return] 1byte upper bit data
///////////////////////////////////////////////////////////////////////
int16_t readShiftByte( uint8_t reg )
{
uint8_t address,val;
int16_t ret;
HAL_GPIO_WritePin( gyro_cs_GPIO_Port, gyro_cs_Pin, RESET );
address =( reg|SETTING );
HAL_SPI_Transmit( &hspi2, &address,1,100 );
HAL_SPI_Receive( &hspi2,&val,1,100 );
ret = (int16_t)(val<< 8);
HAL_GPIO_WritePin( gyro_cs_GPIO_Port,gyro_cs_Pin, SET );
return ret;
}

///////////////////////////////////////////////////////////////////////
// spi write 1 byte
// [argument] Register
// [Substitutiong] write data
// [return] nothong
///////////////////////////////////////////////////////////////////////
void writeByte( uint8_t reg, uint8_t val )
{
HAL_GPIO_WritePin( gyro_cs_GPIO_Port, gyro_cs_Pin, RESET );
HAL_SPI_Transmit( &hspi2, &reg,1,100 ); // 書き込みアドレス??��?��???��?��?
HAL_SPI_Transmit( &hspi2, &val,1,100 ); // 書き込み
HAL_GPIO_WritePin( gyro_cs_GPIO_Port,gyro_cs_Pin, SET );
}

///////////////////////////////////////////////////////////////////////
// l3gd20 set up ( spi )
// [argument] nothing
// [Substitutiong] nothing
// [return] nothig
///////////////////////////////////////////////////////////////////////
void setL3GD20( void )
{
uint8_t ret;
ret = readByte( WHO_AM_I );
printf("who am i = 0x%x",ret);
writeByte( CTRL_REG1, POWER_ON );
writeByte( CTRL_REG4,L3GD20_2000dps );
}

///////////////////////////////////////////////////////////////////////
// spi read 1 byte
// [argument] nothing
// [Substitutiong] nothing
// [return] 2000 deg/sec int data
///////////////////////////////////////////////////////////////////////
int getGyroZ( void )
{
int ret;
// *0.070 because you read l3gd20 manual
ret = ( readShiftByte(OUT_Z_H) | readByte(OUT_Z_L) ) * 0.070;
return ret;
}

(インデントが崩れているのは目をつぶっていただきたいです。

やばいインデント警察に捕まってしまう・・・)

そしたら、関数のプロトタイプ宣言などをして、

int main(void)
{

/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM4_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_SPI2_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_ADC3_Init();

/* USER CODE BEGIN 2 */
setbuf(stdout, NULL);
setL3GD20();
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
printf( "gyro z axis %04d\r",getGyroZ() );
} //switch end
} // while end
/* USER CODE END 3 */

}

 とすることでジャイロセンサーの値を2000deg/secでtera termなどで表示することができると思います。この開発環境でprintfを実装する方法は後々このブログに書いていこうと思います。

詳しくはマニュアルやリファレンスマニュアルなどを参考にしてください。

 

最後に

つたない文章を最後まで読んでいただきありがとうございます。

知見のある方でここをこうしたほうがいいとのことがあれば教えていただきたいです。