on 2022-09-06 12:40 AM
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "main.h" #include "tim.h" #include "gpio.h" /* USER CODE END Includes */Create some masks for each event button, it is helpful to manage the event flags. The EV_UNION_MSK it is a union between directional buttons events (up, right, down, and left buttons).
/* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define EV_SELECT_MSK 0b00000001 #define EV_UP_MSK 0b00000010 #define EV_RIGHT_MSK 0b00000100 #define EV_DOWN_MSK 0b00001000 #define EV_LEFT_MSK 0b00010000 #define EV_UNION_MSK (EV_UP_MSK | EV_RIGHT_MSK | EV_DOWN_MSK | EV_LEFT_MSK) #define THREAD_STACK_SIZE 1024 /* USER CODE END PD */Since this demo uses 2 threads to manage the RGB Color LED, we need to create 2 stack buffers, 2 thread pointers and 2 thread prototype functions OneColorThread and RainbowThread. If you need more information about the ThreadX resources, refer: How to create a Thread using AzureRTOS and STM32CubeIDE?
/* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ uint8_t thread_stack1[THREAD_STACK_SIZE]; uint8_t thread_stack2[THREAD_STACK_SIZE]; TX_THREAD threadOneColor_ptr; TX_THREAD threadRainbow_ptr; TX_EVENT_FLAGS_GROUP event_ptr; const uint8_t lookupTABLE[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ VOID RGBColorChange(uint8_t RED_PWM, uint8_t GREEN_PWM, uint8_t BLUE_PWM); VOID OneColorThread(ULONG initial_input); VOID RainbowThread(ULONG initial_input); /* USER CODE END PFP */The RGBColorChange function changes the LED color according to the parameters sent, this updates the PWM duty cycles changing the pulse compare timer registers. It was implemented to avoid repeated code (this function could be placed into user code region 1, i.e., between user code begin/end 1).
VOID RGBColorChange(uint8_t RED_PWM, uint8_t GREEN_PWM, uint8_t BLUE_PWM) { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, RED_PWM); /* RED PWM */ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, GREEN_PWM); /* GREEN PWM */ __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, BLUE_PWM); /* BLUE PWM */ }In App_ThreadX_Init function starts the three PWM channels, create the event flags using tx_event_flags_create function and two threads with tx_thread_create.
UINT App_ThreadX_Init(VOID *memory_ptr) { UINT ret = TX_SUCCESS; TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr; /* USER CODE BEGIN App_ThreadX_MEM_POOL */ (void)byte_pool; /* USER CODE END App_ThreadX_MEM_POOL */ /* USER CODE BEGIN App_ThreadX_Init */ HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); tx_event_flags_create(&event_ptr, "External Interrupt"); tx_thread_create(&threadOneColor_ptr, "Change Color thread", OneColorThread, 0x1234, thread_stack1, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START); tx_thread_create(&threadRainbow_ptr, "Rainbow thread", RainbowThread, 0x1234, thread_stack2, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START); /* USER CODE END App_ThreadX_Init */ return ret; }Redeclare the HAL_GPIO_EXTI_Callback function in the app_threadx file (it could also be placed into user code region 1). In this function, clear the SELECT button event to update the next color that should be shown. Add a switch case to check what button was pressed and set their respective event flag.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { ULONG event; tx_event_flags_get(&event_ptr, EV_SELECT_MSK, TX_OR_CLEAR, &event, TX_NO_WAIT); switch(GPIO_Pin) { case JOYSTICK_SELECT_Pin: tx_event_flags_set(&event_ptr, EV_SELECT_MSK, TX_OR); break; case JOYSTICK_UP_Pin: tx_event_flags_set(&event_ptr, EV_UP_MSK, TX_OR); break; case JOYSTICK_RIGHT_Pin: tx_event_flags_set(&event_ptr, EV_RIGHT_MSK, TX_OR); break; case JOYSTICK_DOWN_Pin: tx_event_flags_set(&event_ptr, EV_DOWN_MSK, TX_OR); break; case JOYSTICK_LEFT_Pin: tx_event_flags_set(&event_ptr, EV_LEFT_MSK, TX_OR); break; } }Now, create the OneColorThread function. This thread should wait for an event fag according to the Event Union Mask. Whenever an event flag is set by a directional button pressing, this thread clears that and check what flag was set. According to this flag, the thread changes the LED color calling the RGBColorChange.
VOID OneColorThread(ULONG initial_input) { ULONG event; while(1) { tx_event_flags_get(&event_ptr, EV_UNION_MSK, TX_OR_CLEAR, &event, TX_WAIT_FOREVER); if(event & EV_LEFT_MSK) /* Turn LED Off */ { RGBColorChange(0, 0, 0); /* RED = 0, GREEN = 0, BLUE = 0 */ } else if(event & EV_UP_MSK) /* Turn LED RED */ { RGBColorChange(10, 0, 0); /* RED = 10, GREEN = 0, BLUE = 0 */ } else if(event & EV_RIGHT_MSK) /* Turn LED GREEN */ { RGBColorChange(0, 10, 0); /* RED = 0, GREEN = 10, BLUE = 0 */ } else if(event & EV_DOWN_MSK) /* Turn LED BLUE */ { RGBColorChange(0, 0, 10); /* RED = 0, GREEN = 0, BLUE = 10 */ } } }The RainbowThread function it’s a thread that manages the colors when the led is set to a rainbow mode. This thread runs while the SELECT event button is set because this flag is not cleared in get function. To change the color, add a counter and use this as index of the lookup table to send the parameters to the RGBColorChange function. Finally, add a logic to give a phase between the led signals as the following code:
VOID RainbowThread(ULONG initial_input) { ULONG event; uint8_t count = 0; while(1) { tx_event_flags_get(&event_ptr, EV_SELECT_MSK, TX_OR, &event, TX_WAIT_FOREVER); if(count < 16) { RGBColorChange(lookupTABLE[count], lookupTABLE[count + 16], lookupTABLE[count + 32]); count++; } else if(count < 32) { RGBColorChange(lookupTABLE[count], lookupTABLE[count + 16], lookupTABLE[count - 16]); count++; } else if(count < 48) { RGBColorChange(lookupTABLE[count], lookupTABLE[count - 32], lookupTABLE[count - 16]); count ++; } else { RGBColorChange(lookupTABLE[count], lookupTABLE[count - 32], lookupTABLE[count - 16]); count = 0; } tx_thread_sleep(15); } }This is all the necessary code. So, press Ctrl + B to build the project and check if no one errors or warnings occurs. Connect the board to the computer and enter in debug mode clicking on the following button.