2014年2月2日 星期日

作業系統之前的程式 for stm32f4discovery (8.1) - user button by polling

stm32f4discovery 上頭有好幾顆 button, 其中有一顆名為 user button, 這次的實驗要來偵測這個 button。

右圖 stm32f4discovery 的藍色 button 就是 user button, 電路板也有寫上 user, 應該很好辨識。

有兩種偵測 button 狀態的方法: polling 和中斷, 這次介紹使用 polling 來偵測按鈕有無被按下。

user button 接在 PA0, 是個 GPIO, 所以用設定 gpio 的方式就可以設定相關暫存器。

L140 ~ L147 就是在作這個 button 的設定。所以重點就是在如何設定這個 button 的 gpio。

我沒有說明硬體相關資訊是因為我不懂這些東西, 我把這部份的程式碼簡化成這樣就是為了方便查詢這些資料, 不過現在只需要能搞定 user button 的程式碼即可, 這些等以後要「知道」的時候再查詢。

簡化程式碼, 查詢如何完成這功能就花費我不少時間, 我得留些時間做些休閒活動, 休息和工作是同等重要的, 我很小心取得中間的平衡。

user_button.c
  1 /*
  2  * ref: http://eliaselectronics.com/stm32f4-tutorials/stm32f4-gpio-tutorial/
  3  *   use polling to check user button status (press/release)
  4  */
  5 #include "stm32.h"
  6 
  7 #include "stm32f4xx.h"
  8 #include "stm32f4xx_gpio.h"
  9 
 10 #define USE_STDPERIPH_DRIVER
 11 
 12 /*!< Uncomment the following line if you need to relocate your vector Table in
 13      Internal SRAM. */
 14 /* #define VECT_TAB_SRAM */
 15 #define VECT_TAB_OFFSET  0x0 /*!< Vector Table base offset field.  This value must be a multiple of 0x200. */
 16 
 17 int delay_time = 0x300000;
 18 
 19 void Delay(uint32_t delay )
 20 {
 21   while(delay) delay--;
 22 }
 23 
 24 
 25 void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState)
 26 { 
 27   /* Check the parameters */
 28   //assert_param(IS_RCC_AHB1_CLOCK_PERIPH(RCC_AHB1Periph));
 29   
 30   //assert_param(IS_FUNCTIONAL_STATE(NewState));
 31   if (NewState != DISABLE)
 32   {
 33     RCC->AHB1ENR |= RCC_AHB1Periph;
 34   } 
 35   else
 36   { 
 37     RCC->AHB1ENR &= ~RCC_AHB1Periph;
 38   }
 39 }  
 40 
 41 #define RCC_AHB1Periph_GPIOA             ((uint32_t)0x00000001)
 42 #define RCC_AHB1Periph_GPIOD             ((uint32_t)0x00000008)
 43 
 44 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
 45 {
 46   uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
 47 
 48 #if 0
 49   /* Check the parameters */
 50   assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
 51   assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
 52   assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
 53   assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));
 54 #endif
 55   /* -------------------------Configure the port pins---------------- */
 56   /*-- GPIO Mode Configuration --*/
 57   for (pinpos = 0x00; pinpos < 0x10; pinpos++)
 58   {
 59     pos = ((uint32_t)0x01) << pinpos;
 60     /* Get the port pins position */
 61     currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
 62 
 63     if (currentpin == pos)
 64     {
 65       GPIOx->MODER  &= ~(GPIO_MODER_MODER0 << (pinpos * 2));
 66       GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));
 67 
 68       if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF))
 69       {
 70         /* Check Speed mode parameters */
 71         //assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
 72 
 73         /* Speed mode configuration */
 74         GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));
 75         GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));
 76 
 77         /* Check Output mode parameters */
 78         //assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));
 79 
 80         /* Output mode configuration*/
 81         GPIOx->OTYPER  &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ;
 82         GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));
 83       }
 84 
 85       /* Pull-up Pull down resistor configuration*/
 86       GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));
 87       GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));
 88     }
 89   }
 90 }
 91 
 92 void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
 93 {   
 94   /* Check the parameters */
 95   //assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
 96   //assert_param(IS_GPIO_PIN(GPIO_Pin));
 97     
 98   GPIOx->BSRRL = GPIO_Pin;
 99 } 
100 
101 void GPIO_SetBits_svc(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
102 {   
103   /* Check the parameters */
104   //assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
105   //assert_param(IS_GPIO_PIN(GPIO_Pin));
106     
107   GPIOx->BSRRL = GPIO_Pin;
108   __asm ("svc 0");
109 } 
110 
111 
112 void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
113 {
114   /* Check the parameters */
115   //assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
116   //assert_param(IS_GPIO_PIN(GPIO_Pin));
117 
118   GPIOx->BSRRH = GPIO_Pin;
119 }
120 
121 
122 
123 int init_stm32f4(void)
124 {
125   GPIO_InitTypeDef GPIO_InitStructure;
126     
127   /* GPIOD Periph clock enable */
128   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
129 
130   /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */
131   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
132   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
133   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
134   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
135   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
136   GPIO_Init(GPIOD, &GPIO_InitStructure);
137 
138 
139 
140   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
141 
142   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;            // we want to configure PA0
143   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;         // we want it to be an input
144   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;   // this sets the pin type to push / pull (as opposed to open drain)
145   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//this sets the GPIO modules clock speed
146   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;   // this enables the pulldown resistor --> we want to detect a high level
147   GPIO_Init(GPIOA, &GPIO_InitStructure);   
148 }
149 
150 int main(void)
151 {
152   init_stm32f4();
153   int p;
154 
155   while(1)
156   {
157     int i=0;
158     if(GPIOA->IDR & 0x0001)
159     {
160       i=1;
161     }
162     else
163     {
164       i=2;
165     }
166     p = i;
167 
168   }
169 }

程式執行之後, 按下 user button 會執行 L160。

這樣的方式不算漂亮, 使用中斷是比較合適的作法, 這是為外部中斷的版本熱身用的。

source code: 老地方
git commit 37def95d39fc81b6afa9761a21882816303165da

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。