GadgetSeed  0.9.6
gpio_button.c
[詳解]
1 /** @file
2  @brief STM32F411 Nucreo 簡易キードライバ
3 
4  @date 2015.09.22
5  @author Takashi SHUDO
6 
7  @note
8 
9  PC4 KEY3
10  PC5 KEY2
11  PB2 KEY1
12  PB12 KEY0
13 */
14 
15 #include "interrupt.h"
16 #include "device.h"
17 #include "sysevent.h"
18 #include "key.h"
19 #include "tkprintf.h"
20 #include "timer.h"
21 
22 #include "stm32f4xx_hal.h"
23 
24 //#define DEBUGKBITS 0x03
25 #include "dkprintf.h"
26 
27 
28 //#define USE_GPIO_INTERRUPT
29 
30 #define SCANINTTIME 20 //!< スキャン間隔(20ms)
31 
32 #define KEYLINEBITS 4
33 static unsigned short key_stat; // キー状態
34 
35 static const unsigned char key_map[KEYLINEBITS] = {
36  KEY_GB_UP,
37  KEY_GB_ENTER,
38  KEY_GB_DOWN,
39  KEY_GB_ESC,
40 };
41 
42 static void MX_GPIO_Init(void)
43 {
44 
45  GPIO_InitTypeDef GPIO_InitStruct;
46 
47  /* GPIO Ports Clock Enable */
48  __GPIOC_CLK_ENABLE();
49  __GPIOB_CLK_ENABLE();
50 
51  /*Configure GPIO pins : PC4 PC5 */
52  GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
53 #ifdef USE_GPIO_INTERRUPT
54  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
55 #else
56  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
57 #endif
58  GPIO_InitStruct.Pull = GPIO_PULLUP;
59  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
60  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
61 
62  /*Configure GPIO pins : PB2 PB12 */
63  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_12;
64 #ifdef USE_GPIO_INTERRUPT
65  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
66 #else
67  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
68 #endif
69  GPIO_InitStruct.Pull = GPIO_PULLUP;
70  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
71  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
72 
73 // HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
74 #ifdef USE_GPIO_INTERRUPT
75  HAL_NVIC_EnableIRQ(EXTI2_IRQn);
76  HAL_NVIC_EnableIRQ(EXTI4_IRQn);
77  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
78  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
79 #endif
80 }
81 
82 static void init_gpio(void)
83 {
84  MX_GPIO_Init();
85 }
86 
87 static unsigned short scan_gpio(void)
88 {
89  unsigned short rt;
90 
91  /*
92  ポート状態が0ならばOn、1ならばOff
93  関数は1のビットがOn
94  */
95  rt = ~((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2 )<<3) |
96  (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12)<<2) |
97  (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4 )<<1) |
98  (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5 )<<0));
99 
100  DKPRINTF(0x02, "PORT=%04X\n", (int)rt);
101 
102  return rt;
103 }
104 
105 static void scan_key(void *sp)
106 {
107  int i;
108  unsigned short mask;
109  unsigned short bit;
110  struct st_sysevent event;
111  int flg_evt = 0;
112 
113  mask = 0x0001;
114  bit = scan_gpio();
115 
116  for(i=0; i<KEYLINEBITS; i++) {
117  if(bit & mask) {
118  // 押されている
119  if((key_stat & mask) == 0) {
120  // 前は押されていなかった
121  event.what = EVT_KEYDOWN;
122  event.arg = key_map[i];
123  DKPRINTF(0x01, "EVT_KEYDOWN(%d)\n",
124  event.arg);
125  key_stat |= mask;
126  push_event_interrupt(sp, &event);
127  flg_evt = 1;
128  }
129  } else {
130  // いまは押されていなくて
131  if(key_stat & mask) {
132  // 前は押されていた
133  event.what = EVT_KEYUP;
134  event.arg = key_map[i];
135  DKPRINTF(0x01, "EVT_KEYUP(%d)\n",
136  event.arg);
137  key_stat &= ~mask;
138  push_event_interrupt(sp, &event);
139  flg_evt = 1;
140  }
141  }
142  mask <<= 1;
143  }
144 
145  // push したイベント分、カウンタを進める必要がある
146  if(flg_evt) {
148  }
149 }
150 
151 #ifndef USE_GPIO_INTERRUPT
152 static void key_timer(void *sp, unsigned long long stime)
153 {
154  scan_key(sp);
155 }
156 
157 #else
158 static void inthdr_exti2(unsigned long intnum, void *sp)
159 {
160  __HAL_GPIO_EXTI_CLEAR_IT(EXTI_IMR_MR2);
161  DKPRINTF(0x02, "INT %d(%d)\n", (int)intnum, HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2));
162 
163  scan_key(sp);
164 }
165 
166 static void inthdr_exti4(unsigned long intnum, void *sp)
167 {
168  __HAL_GPIO_EXTI_CLEAR_IT(EXTI_IMR_MR4);
169  DKPRINTF(0x02, "INT %d(%d)\n", (int)intnum, HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4));
170 
171  scan_key(sp);
172 }
173 
174 static void inthdr_exti9_5(unsigned long intnum, void *sp)
175 {
176  __HAL_GPIO_EXTI_CLEAR_IT(EXTI_IMR_MR5);
177  DKPRINTF(0x02, "INT %d(%d)\n", (int)intnum, HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5));
178 
179  scan_key(sp);
180 }
181 
182 static void inthdr_exti15_10(unsigned long intnum, void *sp)
183 {
184  __HAL_GPIO_EXTI_CLEAR_IT(EXTI_IMR_MR12);
185  DKPRINTF(0x02, "INT %d(%d)\n", (int)intnum, HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12));
186 
187  scan_key(sp);
188 }
189 #endif
190 
191 static int gpio_button_register(struct st_device *dev, char *param)
192 {
193  key_stat = 0;
194 
195  init_gpio();
196 
197 #ifdef USE_GPIO_INTERRUPT
198  register_interrupt(IRQ2VECT(EXTI2_IRQn), inthdr_exti2);
199  register_interrupt(IRQ2VECT(EXTI4_IRQn), inthdr_exti4);
200  register_interrupt(IRQ2VECT(EXTI9_5_IRQn), inthdr_exti9_5);
201  register_interrupt(IRQ2VECT(EXTI15_10_IRQn), inthdr_exti15_10);
202 #else
203  register_timer_func(key_timer, SCANINTTIME);
204 #endif
205 
206  return 0;
207 }
208 
209 const struct st_device gpio_button_device = {
210  .name = DEF_DEV_NAME_INPUT,
211  .explan = "STM32F4 GPIO Button",
212  .register_dev = gpio_button_register,
213 };
#define EVT_KEYDOWN
キーを押した
Definition: sysevent.h:27
unsigned short arg
イベント引数
Definition: sysevent.h:14
int register_timer_func(timer_func func, unsigned long interval)
周期処理を追加する
Definition: timer.c:274
void set_event_interrupt(void *sp)
割り込みハンドラからシステムイベント待ちタスクを起床する
Definition: sysevent.c:158
カーネルタイマ
#define EVT_KEYUP
キーを離した
Definition: sysevent.h:28
void push_event_interrupt(void *sp, struct st_sysevent *event)
割り込みハンドラからシステムイベントを登録する
Definition: sysevent.c:146
カーネル用機能限定printf
システムイベント
割り込みハンドラ
#define SCANINTTIME
スキャン間隔(20ms)
Definition: gpio_button.c:30
システムイベント
Definition: sysevent.h:12
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
カーネル、ドライバ(非タスク)デバッグ用マクロ
DADG109Aキーコード定義
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26