In this example LED rotation is changed, using Queue options when button is pressed.
Code Example:
#include "bsp.h"
#include <math.h>
#define NUMBER_OF_LEDS 8 //Maximum of LEDs
#define NONE_MESSAGES 0 /* Indicate that No messages available */
#define RESET_VALUE 0 /* Default value to Restore a Variable */
#define RIGHT 0 //Rotate LEDs to right
#define LEFT 1 //Rotate LEDs to left
static void Task_LED_Selector( void *parameters ); /* Task to select LED to be control */
static void Task_Read_Buttons( void *parameters ); /* Task to read Buttons to change LED rotation */
static void Task_LED_Control( void *parameters ); /* Task to control LED status */
QueueHandle_t QueueLEDstatus; /* Handler of Queue */
static uint16_t Rotation = RIGHT; /* Option to change QueueSend function */
int main( void )
{
HAL_Init( );
/*enable RTT and system view*/
SEGGER_SYSVIEW_Conf( );
SEGGER_SYSVIEW_Start( );
QueueLEDstatus = xQueueCreate( 8, sizeof(uint16_t) ); /* Create the Queue to store a data of 16 bits */
xTaskCreate( Task_Read_Buttons, "Task_Rotation", 128u, NULL, 3u, NULL ); /* Register a Task */
xTaskCreate( Task_LED_Selector, "Task_Selector", 128u, NULL, 2u, NULL ); /* Register a Task */
xTaskCreate( Task_LED_Control, "Task_Control", 128u, NULL, 1u, NULL ); /* Register a Task */
vTaskStartScheduler( ); /* initilize the kernel */
return 0u;
}
static void Task_LED_Selector( void *parameters )
{
UNUSED( parameters );
uint16_t Led_Pin[NUMBER_OF_LEDS] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7 };
static uint8_t i = 0; /* Iter Value to send different messages */
for( ;; )
{
while( uxQueueSpacesAvailable( QueueLEDstatus ) > NONE_MESSAGES ) /* Check space in Queue to write */
{
if( Rotation == LEFT ) /* Check Flag Value */
{
xQueueSendToBack( QueueLEDstatus, &Led_Pin[i], 0 ); /* Write elements back of Queue buffer */
}
else if( Rotation == RIGHT ) /* Check Flag Value */
{
xQueueSendToFront( QueueLEDstatus, &Led_Pin[i], 0 ); /* Write elements in front of Queue buffer */
}
i++; /* Increment to select another data from Array */
}
i = RESET_VALUE; /* If Queue has no space, Reset the Value */
vTaskDelay(2000 / portTICK_PERIOD_MS); /* wait 2s to send another complete Queue */
}
}
static void Task_Read_Buttons( void *parameters )
{
UNUSED( parameters );
for( ;; )
{
if ( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_RESET ) /* Read Status of button 7 */
{
Rotation = LEFT; /* Change Flag value */
SEGGER_SYSVIEW_PrintfHost( "Button Pressed to Left" );
}
else if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_15) == GPIO_PIN_RESET ) /* Read Status of button 15 */
{
Rotation = RIGHT; /* Change Flag value */
SEGGER_SYSVIEW_PrintfHost( "Button Pressed to Right" );
}
vTaskDelay( 50 / portTICK_PERIOD_MS ); /* Check buttons each 50ms */
}
}
static void Task_LED_Control( void *parameters )
{
UNUSED( parameters );
uint16_t dataRead; /* Variable to store data of Queue */
for( ;; )
{
while ( uxQueueMessagesWaiting( QueueLEDstatus ) > NONE_MESSAGES ) /* Check that there are message to read */
{
xQueueReceive( QueueLEDstatus, &dataRead, 0 ); /* Read the data of the Queue */
HAL_GPIO_TogglePin( GPIOC, dataRead ); /* Change the LED Status */
vTaskDelay(200 / portTICK_PERIOD_MS); /* Wait 200ms to read other msg */
uint32_t res = log2(dataRead);
SEGGER_SYSVIEW_PrintfHost( "LED %d", res );
}
vTaskDelay(200 / portTICK_PERIOD_MS); /* Periodicity of Task */
}
}
Three tasks are created, Task_Read_Buttons()
that Read 2 buttons, each of them executes a different Queue option in Task_LED_Selector()
, for example, if flag Rotation
is equal to RIGHT the function to execute is xQueueSendToFront()
that writes each data in the front of the Queue as a normal function, but if flag Rotation
change to LEFT, the function to execute is xQueueSendToBack()
that send each data to the back of Queue buffer.
Task Task_LED_Control()
isn't affected by the selection of rotation, just processes the data received from QueueLEDstatus
.
There are not difference between function xQueueSendToBack()
and xQueueSend()
, This functions just use a macro to call the same function.
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
SystemView Output:
Terminal output shows that initial rotation of LEDs is to the Right. By default application sends to front elements to the Queue, As a result Terminal shows a count drecrement each time that message is read.
TimeLine:
Task "Task_Read_Buttons" is executed but ignored because the button is not pressed yet.
|
|
When the button to change to Left is pressed a message is send to terminal, and task "Task_LED_Control" wait to read all the elements on Queue to change the LED rotation.
|
|
Timeline Shows when the last message of the Right rotation finish and when the Left rotation start.
|
End of Right Rotation
Start Left Rotation |