一、关于Stream Buffer的介绍
Stream Buffer,顾名思义,是一种用于存储和传输流式数据的缓冲区,也就是数据结构中的循环队列。它能够在不同的组件或任务之间高效地传递和处理连续的数据流,如音频、视频、文件传输等。Stream Buffer通过提供一个环形缓冲区(ring buffer)来存储数据,允许数据连续地写入和读取,从而优化了数据的处理效率,同时也可以避免内存浪费。
循环队列数据结构定义: int read;//指向队列头,指向第一个数据节点 int write;//指向队列尾(并不是指向最后一个数据节点,而是最后一个数据节点后面的位置) char data[];//节点数据,根据实际需要可以是不同的数据类型.
二、关于RS485介绍
RS-485是一种串行通信协议,是串口通信的变种之一,设计用于工业环境中的数据通信。它采用平衡发送和差分接收的方式,相较于普通串口通信和RS232通信,RS485通信干扰能力更强,适用于长距离通信,最长可达1200米。RS-485标准允许在一条总线上连接多个设备,支持半双工通信。这种通信方式特别适合于工业控制系统中,需要采集多点数据或传输大量数据的场景。
rs485模块的rs485_dir管脚置高处于数据发送状态,置低处于数据接收状态
三、STM32cubeMX配置
四、代码编写
#include "freertos_demo.h"
#include "FreeRTOS.h"
#include "task.h"
#include "gpio.h"
#include "tim.h"
#include "usart.h"
#include <stdio.h>
#define START_TASK_STACK_SIZE 64
#define START_TASK_PRIO 1
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );
#define TASK1_STACK_SIZE 128
#define TASK1_PRIO 2
TaskHandle_t task1_handler;
void task1( void * pvParameters );
circqueue_t que;
circqueue_t *queue=&que;
void freertos_demo(void)
{
xTaskCreate( (TaskFunction_t) start_task,
(char *) "start_task",
(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,
(void *) NULL,
(UBaseType_t) START_TASK_PRIO,
(TaskHandle_t *) &start_task_handler);
vTaskStartScheduler();
}
void start_task( void * pvParameters )
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t) task1,
(char *) "task1",
(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,
(void *) NULL,
(UBaseType_t) TASK1_PRIO,
(TaskHandle_t *) &task1_handler);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
/*处理数据再发送出去*/
void task1( void * pvParameters )
{
char buf[32];
char ch;
printf("task1\r\n");
while(1)
{
ch = circQueueRemove(queue);
printf("%x\n",ch);
while(ch != NULL)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);//置高发送数据
HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xffff);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);//置低接收数据
ch = circQueueRemove(queue);
}
vTaskDelay(500);
}
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "streambuf.h"
void circqueue_init(circqueue_t *queue)//初始化队列
{
queue->write = 0;
queue->read = 0;
memset(queue->data, 0, MAX_NODE_NUM);
}
void circqueue_delete(circqueue_t *queue)//清空队列
{
if(queue)
{
printf("will free queue, write is:%d,read is %d\n",queue->write, queue->read);
free(queue);
}
}
int isQueueEmpty(circqueue_t *queue)//判空
{
return (queue->read==queue->write);
}
int isQueueFull(circqueue_t *queue)//判满
{
return (((queue->write + 1) % MAX_NODE_NUM == queue->read));
}
int writecircQueue(circqueue_t *queue, char newdata)//入队
{
if(isQueueFull(queue))
{
printf("queue is full, add node failed!\n");
return (queue->read-queue->write+MAX_NODE_NUM)%MAX_NODE_NUM;
}
queue->data[queue->write] = newdata;
queue->write = (queue->write + 1)%MAX_NODE_NUM;
//printf("write is %d, read is %d, %d\n", queue->write, queue->read, (queue->write-queue->read+MAX_NODE_NUM)%MAX_NODE_NUM);
return (queue->write-queue->read+MAX_NODE_NUM)%MAX_NODE_NUM;
}
char readcircQueue(circqueue_t *queue)//出队
{
char nodeValue;
if(isQueueEmpty(queue))
{
printf("queue is empty, remove node failed\n");
return NULL;
}
nodeValue = queue->data[queue->read];
queue->read = (queue->read+1)%MAX_NODE_NUM;
return nodeValue;
}
void printQueueData(circqueue_t *queue)//遍历队列
{
int i=0;
printf("write is %d, read is %d\n", queue->write, queue->read);
for(i=queue->read; i!= queue->write; i=(i+1)%MAX_NODE_NUM)
{
printf("%c ", queue->data[i]);
}
printf("\n");
}