STM32F103基于标准库开发串口中断接收数据环形队列例程
✨本示例源码来源于野火-STM32库开发实战指南
,是一个值得学习借鉴的资源。
- 📑一个完整的串口数据包通讯协议一般包含:帧头、地址信息、数据类型、数据长度、数据块、校验码、帧尾。在一般开发过程当中,如果仅仅是作为调试信息使用,那么串口的使用就没有必要代码这么健壮。毕竟功能越完善,所需要提供的代码越复杂,处理的逻辑增加,以及资源的占用。
🔖有关环形列队的优点可以自行去搜索科普,这里不做介绍了。
🛠环形列队实现
🔖接收数据环形列队实现依托开启串口中断接收以及空闲中断。
#ifndef __ESP_DATA_QUEUE_H_
#define __ESP_DATA_QUEUE_H_
#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#define QUEUE_NODE_NUM (2)
#define QUEUE_NODE_DATA_LEN (2*1024 )
#define QUEUE_DATA_TYPE ESP_USART_FRAME
#define DATA_QUEUE_LOG QUEUE_DEBUG
#define DATA_QUEUE_LOG_ARRAY QUEUE_DEBUG_ARRAY
typedef struct
{
char *head;
uint16_t len;
}ESP_USART_FRAME;
typedef struct {
int size;
int read;
int write;
int read_using;
int write_using;
QUEUE_DATA_TYPE *elems[QUEUE_NODE_NUM];
} QueueBuffer;
extern QueueBuffer rx_queue;
#define QUEUE_DEBUG_ON 1
#define QUEUE_DEBUG_ARRAY_ON 0
#define QUEUE_INFO(fmt,arg...) printf("<<-QUEUE-INFO->> "fmt"\n",##arg)
#define QUEUE_ERROR(fmt,arg...) printf("<<-QUEUE-ERROR->> "fmt"\n",##arg)
#define QUEUE_DEBUG(fmt,arg...) do{\
if(QUEUE_DEBUG_ON)\
printf("[%d]"fmt"\n",__LINE__, ##arg);\
}while(0)
#define QUEUE_DEBUG_ARRAY(array, num) do{\
int32_t i;\
uint8_t* a = array;\
if(QUEUE_DEBUG_ARRAY_ON)\
{\
printf("\n<<-QUEUE-DEBUG-ARRAY->>\n");\
for (i = 0; i < (num); i++)\
{\
printf("%02x ", (a)[i]);\
if ((i + 1 ) %10 == 0)\
{\
printf("\n");\
}\
}\
printf("\n");\
}\
}while(0)
#define cbPrint(cb) DATA_QUEUE_LOG("size=0x%x, read=%d, write=%d\n", cb.size, cb.read, cb.write);\
DATA_QUEUE_LOG("size=0x%x, read_using=%d, write_using=%d\n", cb.size, cb.read_using, cb.write_using);
QUEUE_DATA_TYPE* cbWrite(QueueBuffer *cb);
QUEUE_DATA_TYPE* cbRead(QueueBuffer *cb);
void cbReadFinish(QueueBuffer *cb);
void cbWriteFinish(QueueBuffer *cb);
QUEUE_DATA_TYPE* cbWriteUsing(QueueBuffer *cb) ;
int cbIsFull(QueueBuffer *cb) ;
int cbIsEmpty(QueueBuffer *cb) ;
void rx_queue_init(void);
void pull_data_from_queue(void);
void push_data_to_queue(char *src_dat,uint16_t src_len);
#endif
#include "./usart/rx_data_queue.h"
QUEUE_DATA_TYPE node_data[QUEUE_NODE_NUM];
QueueBuffer rx_queue;
__align(4) char node_buff[QUEUE_NODE_NUM][QUEUE_NODE_DATA_LEN] ;
void cbInit(QueueBuffer *cb, int size)
{
cb->size = size;
cb->read = 0;
cb->write = 0;
}
int cbIsFull(QueueBuffer *cb)
{
return cb->write == (cb->read ^ cb->size);
}
int cbIsEmpty(QueueBuffer *cb)
{
return cb->write == cb->read;
}
int cbIncr(QueueBuffer *cb, int p)
{
return (p + 1)&(2*cb->size-1);
}
QUEUE_DATA_TYPE* cbWrite(QueueBuffer *cb)
{
if (cbIsFull(cb))
{
return NULL;
}
else
{
if(cb->write == cb->write_using)
{
cb->write_using = cbIncr(cb, cb->write);
}
}
return cb->elems[cb->write_using&(cb->size-1)];
}
void cbWriteFinish(QueueBuffer *cb)
{
cb->write = cb->write_using;
}
QUEUE_DATA_TYPE* cbRead(QueueBuffer *cb)
{
if(cbIsEmpty(cb))
return NULL;
if(cb->read == cb->read_using)
cb->read_using = cbIncr(cb, cb->read);
return cb->elems[cb->read_using&(cb->size-1)];
}
void cbReadFinish(QueueBuffer *cb)
{
cb->elems[cb->read_using&(cb->size-1)]->len = 0;
cb->read = cb->read_using;
}
void camera_queue_free(void)
{
uint32_t i = 0;
for(i = 0; i < QUEUE_NODE_NUM; i ++)
{
if(node_data[i].head != NULL)
{
node_data[i].head = NULL;
}
}
return;
}
void rx_queue_init(void)
{
uint32_t i = 0;
memset(node_data, 0, sizeof(node_data));
cbInit(&rx_queue,QUEUE_NODE_NUM);
for(i = 0; i < QUEUE_NODE_NUM; i ++)
{
node_data[i].head = node_buff[i];
rx_queue.elems[i] = &node_data[i];
DATA_QUEUE_LOG("node_data[i].head=0x%x,\r\nrx_queue.elems[i] =0x%x", (uint32_t)node_data[i].head,(uint32_t)rx_queue.elems[i]->head);
memset(node_data[i].head, 0, QUEUE_NODE_DATA_LEN);
}
}
void push_data_to_queue(char *src_dat,uint16_t src_len)
{
QUEUE_DATA_TYPE *data_p;
uint8_t i;
for(i=0;i<src_len;i++)
{
data_p = cbWrite(&rx_queue);
if (data_p != NULL)
{
*(data_p->head + i) = src_dat[i];
data_p->len++;
printf("\r\ndata_p->len =%d",data_p->len);
}else return;
cbPrint(rx_queue);
}
cbWriteFinish(&rx_queue);
cbPrint(rx_queue);
}
void pull_data_from_queue(void)
{
QUEUE_DATA_TYPE *rx_data;
rx_data = cbRead(&rx_queue);
if(rx_data != NULL)
{
*(rx_data->head+rx_data->len) = '\0';
QUEUE_DEBUG("接收到的数据:%s",rx_data->head);
QUEUE_DEBUG_ARRAY((uint8_t*)rx_data->head,rx_data->len);
cbReadFinish(&rx_queue);
}
}
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(DEBUG_USARTx, &USART_InitStructure);
NVIC_Configuration();
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
USART_ITConfig ( DEBUG_USARTx, USART_IT_IDLE, ENABLE );
USART_Cmd(DEBUG_USARTx, ENABLE);
}
int fputc(int ch, FILE *f)
{
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
int fgetc(FILE *f)
{
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USARTx);
}
#include "stm32f10x.h"
#include "bsp_usart.h"
#include "./usart/rx_data_queue.h"
int main(void)
{
USART_Config();
rx_queue_init();
Usart_SendString( DEBUG_USARTx,"这是一个串口中断接收回显实验\n");
printf("STM32F103VCT6\r\n");
while(1)
{
pull_data_from_queue();
}
}
- 📜串口打印信息
![在这里插入图片描述](https://img-blog.csdnimg.cn/dfacfe5ab5f544c6b0f0fa58019c5cee.png)
📚程序源码
⚡基于Keil5,ARMcompiler:5.06
链接:https:
提取码:wdr0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)