Skip to main content

STM32 Pushbutton Example: Part 3. Pushbutton State Check

In this post, actual pushbutton checking algorithm is explained. As discussed previously, it utilizes the software timer (UsrTimer) to address the chattering issue and to implement a multi-function input button. The main timer routine is registered by calling:
Source file
  103     // initialize the pushbutton handler with mask byte.
  104     PushButton_Init(0x01);
where the mask byte (0x01) indicates the location of the state bits of active buttons in the 8bit button state byte. Here we have only one button that is located at the first bit location. This call starts a timer routine that runs indefinitely at a predefined interval, PUSHBTN_TMR_PERIOD whose value is set to 80 msec at the moment.

This period can be tuned to serve particular hardware better. However you have to remember that other parameters such as the duration values that determine short click and long click have reference to this value. For example PUSHBTN_TO_SHORT value is set to 3, which means that the algorithm wait for 3 * 80 = 240 msec after a click is detected then posts a single click event. If subsequent click is detected during this period, it does not post any event but keeps track the state of the button.

Actual algorithm is implemented in the main routine, PushButton_Routine(). However this routine needs to read the current state of the button(s) by calling PushButton_Read() function:
Source file
   63 /** Main routine
   64  */
   65 void PushButton_Routine()
   66 {
   67     int i;
   68     uint8_t diff_state;
   69     uint8_t event[EVT_QWIDTH];
   70     static bool flag = false;
   71 
   72     pp.new_state = PushButton_Read();
   73 
   74     // difference in the button state
   75     diff_state = pp.old_state ^ pp.new_state;
where the function is defined as weak:
Source file
   81 /// Read all pushbutton state and return them in a uint8_t form
   82 uint8_t PushButton_Read(void) __attribute__((weak));
Thus you have to write your own version of the function somewhere in your code:
Source file
  298 /** This function returns the state (click/release) of the pushbuttons
  299  * in a uint8_t variable, each bit of which corresponds to a button.
  300  * Note that 1 implies the button is clicked (pressed) and 0 implies the
  301  * button is released.
  302  *
  303  * \return  pushbutton state packed in a uint8_t.
  304  */
  305 uint8_t PushButton_Read()
  306 {
  307     // button released
  308     if(HAL_GPIO_ReadPin(TEST_BTN_GPIO_Port, TEST_BTN_Pin))
  309     {
  310         return 0x00;
  311     }
  312     // button pressed
  313     else
  314     {
  315         return 0x01;
  316     }
  317 }
Note that the return value of the function should match with the mask bit, in this case the first bit of the 8bit data.
As the PushButton_Routine() automatically posts events according to the state of the button, you need to implement event handling function inside the main() loop as shown in the previous post. In the sample code, it will print out the result via UART port.


It is rather easy to modify the code to have two modes. In addition to the method described above, i.e., algorithm detects the change of the buttons state, it can detects just up or down state of the buttons, so that it will continuously generate event when the button is pressed, while silent when it is released.



<<source code>>

Comments

Popular posts from this blog

A Simple STM32 Example Project

Most of the embedded projects share certain initial steps. You need to confirm the clock settings before doing anything, then you want to have debug connection via a UART channel since it is cheap  but still it can provide useful information for debugging. Let us start with CubeMX. You select a device/board of your choice, set up the pinouts for one GPIO output and one UART port. Configure the clock if necessary then create a project. Clock Checking using SysTick The sanity of the clock setting can be done by checking the SysTick interval. All Cortex-M series core have SysTick timer by default, which should fire at 1msec interval while the MCU is active. In the STM32Cube, the SysTick is initialized by HAL_Init() call, which in turn calls SysTick_Config() in CMSIS. Once the SysTick is initialized, it generates 1 msec interrupt and this interrupt is handled by SysTick_Handler() according to the Cube framework. Source file 1 /** 2 * @brief This function handles

STM32 USB MSC Device with FLASH memory

USB Mass Storage Class framework implements bulk-only-transfer (BOT) with SCSI protocol. USB packets from the host eventually converted SCSI transport commands by the middleware, in which data is exchanged (read / write) in the unit of logical block, typically 512 bytes. This SCSI commands works well with SD card system where a dedicated controller does the job of managing the actual memory elements. If you want to use a FLASH chip as a memory unit instead, you need to handle read / write operation directly. Fortunately, most of flash memory support 4KB block erase. This makes the 4096 bytes as a natural choice for the size of the logical block in the file usbd_storage_if.c. In this case, 8Mbit Flash memory was used. During initial enumeration, this information is registered to the host. The middleware maintains one logical block size of buffer and handles USB transaction where each payload is only 64 bytes. It then calls SCSI requests to store / retrieve data to / from physical

STM32 USB MSD with SD Card

Build a low level driver for SD card, then the glue logic for FatFs and USB MSD is pretty much the same as Flash memory case posed before. In case of SD card, sector size is 512 in most of the cases. Thus the memory requirement is much relaxed. You can even allocate a file buffer that is bigger than the sector size. FatFs site has a  dedicated page for MMC/SDC, on which you can find fairly detailed explanation about how to interface MMC/SDC via SPI bus. Implementation should be straightforward until you encounter with cheap SD cards that do not behave very well. In such cases, you either have to protect your code with redundancy or just stick with quality devices. If you choose SanDisk or Kingston brand, you will be safe. ADATA on the other hand, frequently generates timeout error at first try. Most of the SD card sockets have a pin to detect the presence of the card. This pin is usually connected to GND pin or some other pin. You can use this to generate interrupt whenever a ca