当前位置: 首页 > wzjs >正文

用dw做的网站容易变形活动推广宣传方案

用dw做的网站容易变形,活动推广宣传方案,sketch做网站,手机版网站怎么做的单片机串口异步打印 文章目录 单片机串口异步打印前言设计思路准备队列创建完整代码 总结 前言 🌊在单片机开发中串口的异步打印异步打印允许单片机在执行其他任务的同时进行打印操作,无需等待打印完成后再继续执行后续代码,避免了在多处调用…

单片机串口异步打印

文章目录

  • 单片机串口异步打印
    • 前言
      • 设计思路
      • 准备
      • 队列创建
      • 完整代码
    • 总结

前言

🌊在单片机开发中串口的异步打印异步打印允许单片机在执行其他任务的同时进行打印操作,无需等待打印完成后再继续执行后续代码,避免了在多处调用的时候数据覆盖的问题。

设计思路

  • 👍通过创建环形缓冲区队列,设计任务调度或缓冲区管理机制,在FreeRTOS中创建队列来进行数据的接收,新建一个打印任务优先级设置为最低优先级,用来检测FIFO中是否有数据,如果有数据就将FIFO中的数据打印出来。
  • 通过定时器定时检测实现非阻塞数据打印。

准备

  • 移植好FreeRTOS操作系统
  • 串口输出重定向到printf

队列创建

🚗队列的创建涉及到了数据结构,详解可以参考数据结构与算法书籍。

/* 定义环形缓冲区结构体 */ 
typedef struct {uint8_t  buffer[BUFFER_SIZE];    /* 缓冲区            */ volatile uint32_t head;   		 /* 写入指针          */ volatile uint32_t tail;          /* 读取指针          */ SemaphoreHandle_t mutex;         /* 互斥锁,保证线程安全 */ 
} ringbuffer_t;

这里新建了ringbuffer_t里面包含了buffer数据包,它的大小由BUFFER_SIZE这个宏来决定,可以通过这个宏来修改预期的buffer大小。👌

😁实例化结构体,给结构体的成员进行赋值操作。

ringbuffer_t ringBuffer = {.head = 0,.tail = 0,.mutex = NULL
};

🎈初始化环形缓冲区队列。通过创建RingBuffer_Init函数来实现,传入的参数是ringbuffer_trb的结构体指针。这时队列的headtail为0表示这个队列是空的,接着创建了一个互斥量,用来保护线程安全。

/* 初始化环形缓冲区 */ 
void RingBuffer_Init(ringbuffer_t *rb) {rb->head = 0;rb->tail = 0;rb->mutex = xSemaphoreCreateMutex();if (rb->mutex == NULL) {printf("Mutex creation failed.\n");while (1);}
}

🥣判断队列是否为空,传入环形缓冲区的结构体,如果队列的head和队列的tail相等那代表这个队列是空的。

/* 判断环形缓冲区是否为空 */ 
int32_t RingBuffer_IsEmpty(ringbuffer_t *rb) {/* head == tail 为空 */return (rb->head == rb->tail);
}

📡判断队列是否是满,传入缓冲区结构体,如果满足head + 1 %buffer的大小求余数,如果余数等于tail那么就代表这个队列已经填满数据了。

/* 判断环形缓冲区是否已满 */ 
int32_t RingBuffer_IsFull(ringbuffer_t *rb) {return ((rb->head + 1) % BUFFER_SIZE == rb->tail);
}

😍向队列写入数据,是按照字节进行写入,传入的参数的ringbuffer_t 结构体指针,和写入的数据data

/* 向环形缓冲区写入数据 */ 
int32_t RingBuffer_Write(ringbuffer_t *rb, char data) {int32_t result = pdFALSE;if (xSemaphoreTake(rb->mutex, portMAX_DELAY) == pdTRUE) {if (!RingBuffer_IsFull(rb)) {rb->buffer[rb->head] = data;rb->head = (rb->head + 1) % BUFFER_SIZE;result = pdTRUE;}xSemaphoreGive(rb->mutex); /* 释放互斥锁 */}return result;
}

😘从环形缓冲区读取数据,思路是传入ringbuffer_t 的结构体指针,和需要读取的指针类型字符,在读取函数中先判断是否获取到了互斥锁,如果是就判断队列是否非空,如果队列非空,就将buffer数据指针就指向尾部每读取队列的一个数就指针向前偏移一位,直到读取完成,满足if语句每次读取完成之后返回true,读取而结束就释放互斥锁🔒。

/* 从环形缓冲区读取数据 */ 
int32_t RingBuffer_Read(ringbuffer_t *rb, uint8_t *data) {int32_t result = pdFALSE;if (xSemaphoreTake(rb->mutex, portMAX_DELAY) == pdTRUE) {if (!RingBuffer_IsEmpty(rb)) {*data = rb->buffer[rb->tail];rb->tail = (rb->tail + 1) % BUFFER_SIZE;result = pdTRUE;}xSemaphoreGive(rb->mutex); /* 释放互斥锁 */}return result;
}

在这里插入图片描述

😊在填充数据的时候参考了C语言中标准格式化输出,需要进行标准的格式化输出需要先引入其头文件#include"stdarg.h"之后就可以进行标准的格式化输出了。在函数内部,其中可以使用 va_start()va_end() 宏来访问变长参数列表中的值,创建临时的缓冲区来存放格式化的数据,然后再通过vsnprintf函数将可变的数据存到locabuffer中,返回写入的长度。

/* 格式化并写入数据的函数 */ 
void RingBufferWriteFormatted(ringbuffer_t* rb, const uint8_t* format, ...) {va_list args;va_start(args, format);/* 使用 vsnprintf 来格式化字符串到局部缓冲区 */ uint8_t localBuffer[BUFFER_SIZE]; // 根据需要调整大小uint32_t written = vsnprintf(localBuffer, sizeof(localBuffer), format, args);/* 检查格式化是否成功 */ if (written > 0) {/* 将格式化后的字符串逐字符写入环形缓冲区 */ for (int i = 0; i < written; ++i) {     if (!RingBuffer_Write(rb, localBuffer[i])) {break;}}}va_end(args);
}

😄创建打印任务不断的取读取环形缓冲区的数据如果有数据就打印出来。

/* 数据读取和打印任务 */ 
void PrintTask(void *pvParameters) {char data;while (1) {/* 读取缓冲区,有数据就打印 */if (RingBuffer_Read(&ringBuffer, &data)) {printf("%c",data);} }
}

完整代码

/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "stdarg.h"#define BUFFER_SIZE 1024           /* 环形缓冲区大小 根据实际的数据大小进行调整 */ /* 定义环形缓冲区结构体 */ 
typedef struct {uint8_t  buffer[BUFFER_SIZE];  /* 缓冲区   */ volatile uint32_t head;    /* 写入指针 */ volatile uint32_t tail;    /* 读取指针 */ SemaphoreHandle_t mutex;   /* 互斥锁,保证线程安全 */ 
} ringbuffer_t;/* 创建一个全局环形缓冲区实例 */ 
ringbuffer_t ringBuffer = {.head = 0,.tail = 0,.mutex = NULL
};/* 初始化环形缓冲区 */ 
void RingBuffer_Init(ringbuffer_t *rb) {rb->head = 0;rb->tail = 0;rb->mutex = xSemaphoreCreateMutex();if (rb->mutex == NULL) {printf("Mutex creation failed.\n");while (1);}
}/* 判断环形缓冲区是否为空 */ 
int32_t RingBuffer_IsEmpty(ringbuffer_t *rb) {/* head == tail 为空 */return (rb->head == rb->tail);
}/* 判断环形缓冲区是否已满 */ 
int32_t RingBuffer_IsFull(ringbuffer_t *rb) {return ((rb->head + 1) % BUFFER_SIZE == rb->tail);
}/* 向环形缓冲区写入数据 */ 
int32_t RingBuffer_Write(ringbuffer_t *rb, char data) {int32_t result = pdFALSE;if (xSemaphoreTake(rb->mutex, portMAX_DELAY) == pdTRUE) {if (!RingBuffer_IsFull(rb)) {rb->buffer[rb->head] = data;rb->head = (rb->head + 1) % BUFFER_SIZE;result = pdTRUE;}xSemaphoreGive(rb->mutex); /* 释放互斥锁 */}return result;
}/* 从环形缓冲区读取数据 */ 
int32_t RingBuffer_Read(ringbuffer_t *rb, char *data) {int32_t result = pdFALSE;if (xSemaphoreTake(rb->mutex, portMAX_DELAY) == pdTRUE) {if (!RingBuffer_IsEmpty(rb)) {*data = rb->buffer[rb->tail];rb->tail = (rb->tail + 1) % BUFFER_SIZE;result = pdTRUE;}xSemaphoreGive(rb->mutex); /* 释放互斥锁 */}return result;
}
/* 格式化并写入数据的函数 */ 
void RingBufferWriteFormatted(ringbuffer_t* rb, const char* format, ...) {va_list args;va_start(args, format);/* 使用 vsnprintf 来格式化字符串到局部缓冲区 */ char localBuffer[BUFFER_SIZE]; // 根据需要调整大小int written = vsnprintf(localBuffer, sizeof(localBuffer), format, args);// 检查格式化是否成功if (written > 0) {// 将格式化后的字符串逐字符写入环形缓冲区for (int i = 0; i < written; ++i) {     if (!RingBuffer_Write(rb, localBuffer[i])) {break;}}}va_end(args);
}
/* 数据填充任务 测试任务向队列填充数据依次进行添加 */ 
void DataFillTask(void *p) {RingBufferWriteFormatted(&ringBuffer," 1 test test test %d\r\n",0x88);RingBufferWriteFormatted(&ringBuffer, "2 test size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "3 xx size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "4 00 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "5 11 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "6 22 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "7 33 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "8 44 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "9 55 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "10 66 size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "11 ww size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "12 xiao size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer, "13 bai size value %d\r\n", 0x88);RingBufferWriteFormatted(&ringBuffer,"*************DataFillTask******************\n");while (1) {vTaskDelay(200);}
}/* 数据读取和打印任务 */ 
void PrintTask(void *pvParameters) {char data;while (1) {/* 读取缓冲区,有数据就打印 */if (RingBuffer_Read(&ringBuffer, &data)) {printf("%c",data);// printf("Data '%c' read from buffer.\n", data);  /* 从缓冲区去取数据并打印 */} }
}/* 创建任务 */ 
void app_CreateTasks(void) {if(pdPASS != xTaskCreate(DataFillTask, "DataFillTask", 512, NULL, 1, NULL)) {printf("Task DataFillTask creation failed!\r\n");}/* 设置打印任务为最低优先级 */if (pdPASS != xTaskCreate(PrintTask, "PrintTask", 256, NULL, 0, NULL)) {printf("Task PrintTask creation failed!\r\n");}
}
/* 函数入口 */
int main(void) {/* 在这里进行硬件的初始化操作 */printf("rtos_log print\r\n");/* 初始化环形缓冲区*/ RingBuffer_Init(&ringBuffer);/* 创建任务 */ app_CreateTasks();/* 启动调度器*/ vTaskStartScheduler();/* 如果调度器启动失败 */while (1) {};return 0;
}

总结

本文主要介绍了在单片机中实现串口的异步打印,避免了数据覆盖的问题。

http://www.dtcms.com/wzjs/49581.html

相关文章:

  • 住房和城乡建设网站青岛seo关键字排名
  • qq小程序开放平台优化关键词推广
  • 建设大学智慧党建网站关于手机的软文营销
  • 海口网站制作站长工具查询系统
  • 网站做产品的审核工作内容360站长平台
  • 全国房产查询系统西安seo阳建
  • 上海工商网上办事平台网站怎么优化关键词
  • 中国在菲律宾做网站百度pc端首页
  • 自己 做 网站天津seo排名公司
  • 亳州做商标网站的公司快速开发网站的应用程序
  • 营销推广型网站公司uc浏览网页版进入
  • 高端网站的建设站长之家seo查询
  • 做网站用服务器网络推广员每天的工作是什么
  • wordpress怎么让文章只显示摘要seo优化排名经验
  • 东莞国药官网网上商城郑州官网网站推广优化
  • 公司微网站建设方案seo怎么弄
  • 免费在线做网站seo流量增加软件
  • 茂县建设局网站网络营销推广有效方式
  • 怎样提高网站的打开速度网店如何引流与推广
  • 企业信用修复单页网站怎么优化
  • 南昌网站空间教育机构排名
  • 网站开发与app差距关键词查询工具
  • 中邮保险网站关键词有几种类型
  • 网站是专门对生活中的一些所谓常识做辟谣的深圳网络品牌推广公司
  • 安徽省建设工程信网站百度人工服务热线电话
  • 如何做视频播放网站北京网络推广公司排行
  • 自己家里做网站网速慢网址怎么推广
  • 企业网站类型主要包括互动营销公司
  • 邯郸做网站服务商如何增加网站的外链
  • 徐州市做网站图片优化软件