Follow Us for More UpdatesStar Our Public Account to Not Miss Exciting Content from GitHub
Source | GitHub
When it comes to queues, many might first think of “queues” in RTOS. In fact, similar queue functionality can also be implemented in a bare-metal state. Today, I will share a module for implementing queue functionality in a bare-metal microcontroller environment: QueueForMcu
About QueueForMcu
A queue functionality module implemented based on microcontrollers, primarily used for 8-bit, 16-bit, and 32-bit microcontroller applications that do not run RTOS, compatible with most microcontroller platforms.
Open-source code: https://github.com/xiaoxinpro/QueueForMcu
1. Features
- Dynamic creation of queue objects
- Dynamic setting of queue data buffer
- Static specification of queue element data length
- Value passing method to store queue data
2. Quick Start
#include "queue.h"
#define Q_UART_BUFFER_SIZE 1024
QUEUE_HandleTypeDef qUartTx;
QUEUE_DATA_T BufferUartTx[Q_UART_BUFFER_SIZE];
int main(void)
{
QUEUE_DATA_T temp;
// Initialize queue
Queue_Init(&qUartTx, BufferUartTx, Q_UART_BUFFER_SIZE);
while(1)
{
// Enqueue
Queue_Push(&qUartTx, 'Q');
Queue_Push(&qUartTx, 'u');
Queue_Push(&qUartTx, 'e');
Queue_Push(&qUartTx, 'u');
Queue_Push(&qUartTx, 'e');
// Dequeue
Queue_Pop(&qUartTx, &temp);
Queue_Pop(&qUartTx, &temp);
Queue_Pop(&qUartTx, &temp);
Queue_Pop(&qUartTx, &temp);
Queue_Pop(&qUartTx, &temp);
}
}
3. Configuration Instructions
Currently, QueueForMcu has only one static configuration item, as follows:
In the file <span>queue.h</span>, there is a macro definition <span>QUEUE_DATA_T</span> used to specify the data length of queue elements, which defaults to <span>unsigned char</span>, and can be changed to other data types as needed.
4. Data Structure
The data structure of the queue is <span>QUEUE_HandleTypeDef</span>, which is used to save the state of the queue. The source code is as follows:
typedef struct QUEUE_HandleTypeDef{
unsigned int head; // Queue head pointer
unsigned int tail; // Queue tail pointer
unsigned int buffer_length; // Queue buffer length (assigned during initialization)
QUEUE_DATA_T * buffer; // Queue buffer array (assigned during initialization)
}QUEUE_HandleTypeDef;
Where <span>QUEUE_DATA_T</span> is the custom data type defined in the configuration item.
5. Creating a Queue
1. Create Queue Buffer
Since we use a value-passing method to store queue data, we need to manually create a queue buffer before creating the queue to store the queue data.
QUEUE_DATA_T BufferUartTx[1024];
The above code creates a queue buffer of size <span>1024</span>.
2. Create Queue Structure
Next, use <span>QUEUE_HandleTypeDef</span> to create a queue structure to save the state of the queue:
QUEUE_HandleTypeDef qUartTx;
3. Initialize Queue
After preparing the queue buffer and queue structure, call the <span>Queue_Init</span> function to create the queue. The function prototype is as follows:
void Queue_Init(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * buffer, unsigned int len)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure to be initialized. If re-initialized, the original queue content will be cleared. |
| buffer | The pointer to the starting address of the queue buffer |
| len | The queue length, which cannot exceed the queue buffer length. |
Reference Code:
Queue_Init(&qUartTx, BufferUartTx, Q_UART_BUFFER_SIZE);
6. Enqueue
1. Single Data Enqueue
To enqueue data at the tail of the queue, use the <span>Queue_Push</span> function. The function prototype is as follows:
QUEUE_StatusTypeDef Queue_Push(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T data)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure to which data needs to be pushed. |
| data | The data to be pushed into the queue. |
Return Value Description:
This function will return a <span>QUEUE_StatusTypeDef</span> enumeration data type, and the return value will indicate the following based on the queue status:
| Return Value | Description |
|---|---|
| QUEUE_OK | Data successfully pushed into the queue. |
| QUEUE_OVERLOAD | Data not pushed into the queue, reason: queue is full. |
Reference Code:
Queue_Push(&qUartTx, 'Q');
Queue_Push(&qUartTx, 0x51);
Queue_Push(&qUartTx, 81);
2. Multiple Data Enqueue
If you need to push multiple data (array) into the queue, you can use the <span>Queue_Push_Array</span> function, which essentially calls the <span>Queue_Push</span> function in a loop. The function prototype is as follows:
unsigned int Queue_Push_Array(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * pdatas, unsigned int len)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure to which data needs to be pushed. |
| pdatas | The starting address of the array to be pushed into the queue. |
| len | The length of the array to be pushed into the queue. |
If the array length exceeds the remaining length of the queue, the excess data will be ignored.
Return Value Description:
-
This function will return the actual length of data pushed into the queue.
-
When the remaining length in the queue is sufficient, the return value will equal the parameter
<span>len</span>. -
When the remaining length in the queue is insufficient, the return value will be the actual length of data pushed into the queue.
7. Dequeue
1. Single Data Dequeue
To dequeue data from the head of the queue, use the <span>Queue_Pop</span> function. Note that the dequeued data will be removed from the queue. The function prototype is as follows:
QUEUE_StatusTypeDef Queue_Pop(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * pdata)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure from which data needs to be popped. |
| pdata | A pointer to save the popped data variable. |
Return Value Description:
This function will return a <span>QUEUE_StatusTypeDef</span> enumeration data type, and the return value will indicate the following based on the queue status:
| Return Value | Description |
|---|---|
| QUEUE_OK | Data successfully popped from the queue. |
| QUEUE_VOID | No data popped from the queue, reason: queue is empty. |
Reference Code:
QUEUE_DATA_T temp;
if(QUEUE_OK == Queue_Pop(&qUartTx, &temp))
{
// temp contains the data popped from the queue
}
else
{
// Failed to pop data
}
2. Multiple Data Dequeue
If you need to pop multiple data from the queue, you can use the <span>Queue_Pop_Array</span> function, which essentially calls the <span>Queue_Pop</span> function in a loop. Note that successfully popped data will be removed from the queue. The function prototype is as follows:
unsigned int Queue_Pop_Array(QUEUE_HandleTypeDef * hqueue, QUEUE_DATA_T * pdatas, unsigned int len)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure from which data needs to be popped. |
| pdatas | The starting address of the array to save popped data. |
| len | The length of the array for popping data. |
If the length of data to be popped exceeds the data length in the queue, the excess space in the array will not be assigned.
Return Value Description:
-
This function will return the actual length of data popped from the queue.
-
When the data length in the queue is sufficient, the return value will equal the parameter
<span>len</span>. -
When the data length in the queue is insufficient, the return value will be the actual length of data popped from the queue.
3. Single Data Peek
If you need to get data from the head of the queue without removing it, you can use the <span>Queue_Peek</span> function, which has the same parameters and return values as <span>Queue_Pop</span>.
The difference between using <span>Queue_Peek</span> and <span>Queue_Pop</span> is:
<span>Queue_Pop</span>removes the data from the queue after retrieving it.<span>Queue_Peek</span>retains the data in the queue after retrieving it.
4. Multiple Data Peek
If you need to get multiple data from the head of the queue without removing them, you can use the <span>Queue_Peek_Array</span> function, which has the same parameters and return values as <span>Queue_Pop_Array</span>.
The difference between using <span>Queue_Peek_Array</span> and <span>Queue_Pop_Array</span> is:
<span>Queue_Pop_Array</span>removes the data from the queue after retrieving it.<span>Queue_Peek_Array</span>retains the data in the queue after retrieving it.
8. Other Functions
1. Clear Queue
When you need to clear the queue data, there is no need to pop all data; just call <span>Queue_Clear</span> to quickly clear the specified queue. This function is called during queue creation to initialize the queue, so there is no need to call the clear queue function for a newly created queue.
Function Prototype:
void Queue_Clear(QUEUE_HandleTypeDef * hqueue)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure to be cleared. |
2. Get Queue Data Count
When you need to get the data length in the queue, call the <span>Queue_Count</span> function. The function prototype is as follows:
unsigned int Queue_Count(QUEUE_HandleTypeDef * hqueue)
Parameter Description:
| Parameter Name | Description |
|---|---|
| hqueue | The queue structure from which to get the data length. |
Return Value Description:
- This function will return the data length in the queue.
- The return value range is between 0 and the length at which the queue was created.
License
Copyright © 2020 QueueForMcu Released under the GPL-3.0 License.
Disclaimer: The materials in this article are sourced from the internet, and the copyright belongs to the original author. If there are any copyright issues, please contact me for removal.———— END ————
● Column “Embedded Tools”● Column “Embedded Development”● Column “Keil Tutorials”● Selected Tutorials in Embedded ColumnFollow our public accountReply “Add Group” to join the technical exchange group according to the rules, reply “1024” to see more content.Click “Read Original” to see more shares.