Project_OKI’s diary

エンジニアの勉強ブログ

STM32マイコン_16(レジスタ操作でスイッチ入力)

 

STM32:レジスタ操作でスイッチ入力

1.本日の内容

 (1) レジスタを読み込みスイッチを入力する。

 (2) レジスタ操作により、スイッチを押すとLEDをONにするプログラムを作成する。

  STM32マイコン(nucleo f401RE)を使用する。

 

・目次

 

2.内容

​​(1) やる内容の詳細​

 ・STM32マイコン(nucleo f401RE)を使用して、スイッチを押した時にLEDを点灯

  1秒後に消灯するプログラムを作成する。

 ・ただLEDを消灯するわけではなく、LEDの点灯を検知し、点灯したら1秒後消灯する。

 

(2) 使用部品​
個数 部品名 型番
1 USBケーブル ​​USBミニBタイプ
1 mbed(マイコンボード) ​​nucleo f401RE

 

(3) STM32CubeMXの設定、プログラムを出力

  CubeMXの設定は下記記事の

 「(3)STM32CubeMXの設定、プログラムを出力」を参照

  →STM32マイコン_5(スイッチ入力とLED点灯、消灯) - Project_OKI’s diary

 

(4) AtricTrueStdioでプログラム作成
 (a) プログラムの作成
/* USER CODE BEGIN 3 */
//スイッチ(PC_13)が押されたとき、動作
if(!(GPIOC -> IDR & 0b0010000000000000)){
	LED1_GPIO_Port->ODR |= GPIO_ODR_OD5;  //PA5プルアップ
	
	if(GPIOA -> IDR & 0b0000000000100000){ //PA5がHighになったら実行
		HAL_Delay(1000);
		LED1_GPIO_Port->ODR = 0b0000000000000000;//プルダウン
	}
}
 /* USER CODE END 3 */
 
(5) プログラム説明

 (a) GPIOC -> IDR & 0b0010000000000000

   ・PC13のHIGH/LOWを確認する。

   ・IDRが入力用レジスタ

   ・PC13の為、GPIOCを指定する。
   ・PC13のため、0b0010000000000000と13bit目をHighにする。

    これにより、そのポートのHigh,Lowを読み出し出来る。

   ・mbedの回路上、GPIOC -> IDR & 0b0010000000000000が0の時スイッチがONということになる。

   ・if(!xxx)で、反転している。

   →参考:C言語基礎知識21(演算子)

 

 ※RM0368の8.4.5を参照

  →ここからダウンロードできる:STM32/STM8 マイクロコントローラ リファレンス マニュアル(日本語)

 

 (b) LED1_GPIO_Port->ODR |= GPIO_ODR_OD5;

  →PA5のLED1をONにする。

  →参照:STM32マイコン_15(レジスタ操作でLED点滅2)

 

 (c) GPIOA -> IDR & 0b0000000000100000

   ・PA5のHIGH/LOWを確認する。

   ・PA5なので、GPIOAを指定

   ・IDRが入力用レジスタ

   ・PA5なので、0b0000000000100000と5bit目を1にしている。

   ・PA5がHIGHになった時、GPIOA -> IDR & 0b0000000000100000は1になる。

 

 (d) CubeMXでKEY1と作成しているため、(b)と同様に

   GPIOC -> IDR & 0b0010000000000000 は

  KEY1_GPIO_Port->IDR & KEY1_Pin

  と書いてもよい。

  STM32f401xe.hで、#defineを用いて、別名に置き換えている。

  CubeMXで作成した場合、自動的にそのファイルがインクルードされる。

  CubeMXにて、KEY1と名前を指定しておくと、ポート位置が変わっても、

  プログラムを変更せずにすむ。

 
(6) プログラム作成(レジスタを用いた入力用関数作成)

 ・スイッチを押すと点灯し1秒後消灯するプログラム

 /* USER CODE BEGIN 0 */
 ///base:GPIOのベース pin:ピンBIT指定 戻り:0/1
 #define InGPIO(port,pin)  ((((port->IDR)&(pin))==0)?0:1)
 #define KEY1       InGPIO(KEY1_GPIO_Port,KEY1_Pin)
 /* USER CODE END 0 */
 
 /* USER CODE BEGIN 3 */
 if(KEY1==0){
    LED1_GPIO_Port->ODR |= GPIO_ODR_OD5;      //PA5プルアップ
    HAL_Delay(1000);			      //1000ms wait
    LED1_GPIO_Port->ODR &= ~GPIO_ODR_OD5      //PA5プルダウン
 }
 /* USER CODE END 3 */

 

(7) プログラムの説明
 (a) ((((port->IDR)&(pin))==0)?0:1) 
  ・*1
   →指定したpinの入力を確認
   →pinがHighの時1、LOWの時0
  ・(((port->IDR)&(pin))==0)が真の時0
  ・*2==0が偽の時1
   を返す。
  参考:C言語基礎知識21(演算子)
  上記 KEY1_GPIO_Port->IDR & KEY1_PinのKEY1_GPIO_PortとKEY1_Pinを
  port、pinとして、汎用的に使用できる。
  #defineで置き換えることにより、
  (4)の入力はInGPIO(KEY1_GPIO_Port,KEY1_Pin)と出来る。
 
 (b)  if(KEY1==0){
  ・#defineで宣言されたKEY1の値を確認
  ・キーが押されたときKEY1 = 0となり{ }を実行する。
 
 (c) InGPIO(KEY1_GPIO_Port,KEY1_Pin)
  ・portをKEY1_GPIO_Portに設定
  ・pinをKEY1_Pinに設定
     (CubeMXでKEY1と指定)
  ・KEY1_GPIO_PortはGPIOCの事(main.hで#defineによって宣言)
  ・KEY1_PinはGPIO_PIN_13の事(main.hで#defineによって宣言)
 

3.関連記事

関連記事一覧:
 
組み込みC言語

 

*1:port->IDR)&(pin

*2:port->IDR)&(pin