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

wordpress登录验证码网站seo教材

wordpress登录验证码,网站seo教材,网站正在建设 英文翻译,wps2016怎么做网站目录 一、消息缓冲区功能概述 二、消息缓冲区操作相关函数 1、相关函数概述 2、部分函数详解 (1)创建消息缓冲区 (2)写入消息 (3)读取消息 (4)消息缓冲区状态查询 三、消息…

目录

一、消息缓冲区功能概述

二、消息缓冲区操作相关函数

1、相关函数概述

2、部分函数详解

(1)创建消息缓冲区

(2)写入消息

(3)读取消息

(4)消息缓冲区状态查询

三、消息缓冲区使用示例

1、示例功能与CubeMX项目设置

(1)RCC、SYS、Code Generator、USART3、TIM6

(2)RTC的设置

(3)FreeRTOS的设置

(4)NVIC

2、程序功能实现

(1)主程序

(2)FreeRTOS对象初始化

(3)RTC的唤醒中断

(4)任务Task_Show的功能

3、运行调试


一、消息缓冲区功能概述

        消息缓冲区(message buffer)是基于流缓冲区实现的,也就是它的实现使用了流缓冲区的技术,如同信号量是基于队列实现的。与流缓冲区的差异在于:消息缓冲区传输的是可变长度的消息,如10字节、20字节或35字节的消息。写入者向消息缓冲区写入一个10字节的消息,读取者也必须以10字节的消息读出,而不是像流缓冲区那样,按字节流读出。

        每个消息都有一个消息头,就是消息数据的字节数。在STM32 MCU上,消息头就是一个uint32_t类型的整数。消息头的写入和读取是由FreeRTOS的API函数自动处理的,例如,向消息缓冲区写入一个长度为20字节的消息,实际占用空间是24字节。

        消息缓冲区没有触发水平,写入和读取都是以一条消息为单位的,操作要么成功,要么失败。

        消息缓冲区的其他特性与流缓冲区一样。例如:在只有一个写入者和一个读取者的情况下,可以安全操作消息缓冲区;如果有多个写入者或多个读取者,读写消息缓冲区的代码必须在临界代码段内,且等待时间必须设置为0。

二、消息缓冲区操作相关函数

1、相关函数概述

        消息缓冲区相关函数的头文件message_buffer.h,源程序都在文件stream_buffer.c里,因为消息缓冲区是基于流缓冲区实现的,要在程序中使用消息缓冲区,需包含头文件message_buffer.h。

分组

函数

功能

创建


删除

xMessageBufferCreate()

创建一个消息缓冲区,只需设置缓冲区大小

xMessageBufferCreateStatic()

创建一个消息缓冲区,静态分配内存

vMessageBufferDelete()

删除一个消息缓冲区

xMessageBufferReset()

复位一个消息缓冲区,清空数据。只有没有任务在阻塞状态下读或写消息缓冲区时,才可以复位消息缓冲区

写入

xMessageBufferSend()

向消息缓冲区发送一个消息

xMessageBufferSendFromISR()

xMessageBufferSend()的ISR版本

读取

xMessageBufferReceive()

从消息缓冲区接收一条消息

xMessageBufferReceiveFromISR()

xMessageBufferReceive()的ISR版本

状态

查询

xMessageBufferIsEmpty()

查询消息缓冲区是否为空,返回值pdTRUE表示无任何消息

xMessageBufferIsFull()

查询消息缓冲区是否满了,返回值pdTRUE表示不能
再写入任何消息

xMessageBufferSpacesAvailable()

查询消息缓冲区的剩余存储空间

        与流缓冲区不同的是:消息缓冲区无须设置触发水平,在写入或读取消息超时的时候,实际写入或读取的数据字节数为0,不会只写入或读取部分数据。

2、部分函数详解

(1)创建消息缓冲区

        用于创建消息缓冲区的函数是xMessageBufferCreate(),这是个宏函数,其原型定义如下:

/**
* \defgroup xMessageBufferCreate xMessageBufferCreate
* \ingroup MessageBufferManagement
*/
#define xMessageBufferCreate( xBufferSizeBytes ) ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE )

        调用函数xMessageBufferCreate()时,只需传递缓冲区大小xBufferSizeBytes。这个函数实际上调用了函数xStreamBufferGenericCreate(),传递的触发水平参数为0,因为消息缓冲区没有触发水平,最后的参数pdTRUE表示要创建的是消息缓冲区。

        函数xMessageBufferCreate()的返回值是MessageBufferHandle_t类型的,就是所创建的消息缓冲区对象指针。

(2)写入消息

        用于向消息缓冲区写入消息的函数是xMessageBufferSend(),这是个宏函数,其原型定义如下:

/**
* \defgroup xMessageBufferSend xMessageBufferSend
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait )

        实际上,它是执行了流缓冲区写入数据的函数xStreamBufferSend()。函数中各参数的意义如下。

  • xMessageBuffer,所操作的消息缓冲区的句柄。
  • pvTxData,准备写入的数据缓冲区指针。
  • xDataLengthBytes,消息数据的字节数,不包括消息头的4字节。
  • xTicksToWait,等待的节拍数,如果消息缓冲区没有足够的空间用于写入这条消息,任务可以进入阻塞状态等待。若设置为0,则表示不等待;若设置为portMAX_DELAY,则表示一直等待。

        函数xStreamBufferSend()内部会判断传递来的缓冲区对象的类型。如果是消息缓冲区,就在实际写入数据前面加上一个uint32_t类型的整数,表示消息的字节数;如果是流缓冲区,就直接写入数据。

        函数xMessageBufferSend()的返回值是实际写入消息的字节数,不包括消息头的4字节。如果函数是因为等待超时而退出的,则返回值为0;如果写入成功,返回值就是写入的消息数据的字节数。这是与流缓冲区不同的一个地方,使用函数xStreamBufferSend()向流缓冲区写入数据时,如果因等待超时而退出,仍然可能向流缓冲区写入了一些数据。

        在ISR中,向消息缓冲区写入消息的函数是xMessageBufferSendFromISR(),它是个宏函数,实际就是执行了函数xStreamBufferSendFromISR(),其原型定义如下:

/**
* \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
* \ingroup MessageBufferManagement
*/
#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken )

(3)读取消息

        用于从消息缓冲区读取消息的函数是xMessageBufferReceive(),其原型定义如下:

/**
* \defgroup xMessageBufferReceive xMessageBufferReceive
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait )

        它就是执行了函数xStreamBufferReceive()。函数中各参数的意义如下。

  • xMessageBuffer,所操作的消息缓冲区的句柄。
  • pvRxData,保存读出数据的缓冲区指针。
  • xBufferLengthBytes,缓冲区pvRxData的长度,也就是最大能读取的字节数。
  • xTicksToWait,等待的节拍数。如果消息缓冲区里没有消息,任务可以进入阻塞状态等待。若设置为0,则表示不等待;若设置为portMAX_DELAY,则表示一直等待。

        函数xStreamBufferReceive()会自动区分参数xMessageBuffer是流缓冲区,还是消息缓冲区。如果是消息缓冲区,它会先读取表示消息长度的4字节消息头,然后按照长度读取后面的消息数据。

        函数xMessageBufferReceive()返回的是实际读取的消息的字节数,不包括消息头的4字节。如果函数是因为等待超时而退出的,则返回值为0。

        在ISR中从消息缓冲区读取消息的函数是xMessageBufferReceiveFromISR(),它是个宏函数,实际就是执行了函数xStreamBufferReceiveFromISR(),其原型定义如下:

/**
* \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
* \ingroup MessageBufferManagement
*/
#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken )

(4)消息缓冲区状态查询

        以下几个查询消息缓冲区状态的函数,只需使用消息缓冲区的句柄作为函数的输入参数。

  • xMessageBufferIsEmpty()查询一个消息缓冲区是否为空,若返回pdTRUE,则表示缓冲区不包含任何消息。
  • xMessageBufferIsFull()查询一个消息缓冲区是否已满,若返回pdTRUE,则表示不能再写入任何消息。
  • xMessageBufferSpacesAvailable()查询一个消息缓冲区剩余的存储空间字节数,返回值类型为uint32_t。

三、消息缓冲区使用示例

1、示例功能与CubeMX项目设置

        本示例演示消息缓冲区的使用,实例的功能和使用流程如下。

  • 创建一个消息缓冲区和一个任务Task_Show。
  • 使用RTC的唤醒中断,唤醒周期为1s。在RTC的唤醒中断里读取当前时间,转化为字符串后,作为消息写入消息缓冲区,每次写入的消息长度不一样。
  • 在任务Task_Show里读取消息缓冲区的消息,并在串口助手上显示。
  • 继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。

  • 一些设置可以参考本文作者写的其他文章:

        细说STM32单片机FreeRTOS流缓冲区及其应用实例-CSDN博客  https://wenchm.blog.csdn.net/article/details/148168854?spm=1011.2415.3001.5331

(1)RCC、SYS、Code Generator、USART3、TIM6

        配置时钟树,将APB1定时器时钟频率设置为84MHz,APB2定时器时钟频率设置为168MHz ;设置TIM6作为基础时钟源;其它设置可见参考文章。

(2)RTC的设置

        启用LSE,启用RTC,在时钟树上将LSE作为RTC的时钟源。启用周期唤醒功能,设置唤醒周期为1s,其他参数用默认值即可。

 

(3)FreeRTOS的设置

        设置FreeRTOS接口为CMSIS_V2,所有“Config”和“Include”参数保持默认值。在FreeRTOS里创建一个任务Task_Show,其主要参数如图所示。

(4)NVIC

        在NVIC里开启RTC唤醒中断,设置其中断优先级为5,因为要在其ISR里使用FreeRTOS API函数。

2、程序功能实现

(1)主程序

        完成设置后,CubeMX自动生成代码。在CubeIDE中打开项目,添加用户功能代码后,主程序代码如下:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "rtc.h"
#include "usart.h"
#include "gpio.h"/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_FREERTOS_Init(void);/*** @brief  The application entry point.* @retval int*/
int main(void)
{/* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();MX_RTC_Init();MX_USART3_UART_Init();/* USER CODE BEGIN 2 *///Start Menuuint8_t startstr[] = "Demo9_2:Using Message Buffer.\r\n\r\n";HAL_UART_Transmit(&huart3,startstr,sizeof(startstr),0xFFFF);/* USER CODE END 2 *//* Init scheduler */osKernelInitialize();/* Call init function for freertos objects (in cmsis_os2.c) */MX_FREERTOS_Init();/* Start scheduler */osKernelStart();/* We should never get here as control is now taken by the scheduler *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

(2)FreeRTOS对象初始化

        自动生成的函数MX_FREERTOS_Init()只创建了任务,在CubeMX里不能可视化地创建消息缓冲区,需要在CubeMX生成的CubeIDE初始代码的基础上,编程创建消息缓冲区。在文件freertos.c中定义两个常量和消息缓冲区对象,在函数MX_FREERTOS_Init()中增加创建消息缓冲区对象的代码。完成后的代码如下:

        自动生成includes,并手动添加私有includes: 

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "message_buffer.h"
#include "usart.h"
#include <stdio.h>		//用到函数sprintf()
#include <string.h>		//用到函数strlen()
/* USER CODE END Includes */

        手动添加私有宏定义:

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define	MSG_BUFFER_LEN	50		//消息缓存区长度,单位:字节
#define	MSG_MAX_LEN		20		//消息最大长度,单位:字节
/* USER CODE END PD */

        手动添加创建消息缓冲区句柄变量代码;

        自动生成任务函数句柄变量代码:

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
MessageBufferHandle_t  msgBuffer;		//消息缓存区句柄变量
/* USER CODE END Variables */
/* Definitions for Task_Show */
osThreadId_t Task_ShowHandle;
const osThreadAttr_t Task_Show_attributes = {.name = "Task_Show",.stack_size = 256 * 4,.priority = (osPriority_t) osPriorityNormal,
};/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void AppTask_Show(void *argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) 
{/* Create the thread(s) *//* creation of Task_Show */Task_ShowHandle = osThreadNew(AppTask_Show, NULL, &Task_Show_attributes);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... */msgBuffer=xMessageBufferCreate(MSG_BUFFER_LEN);		//创建消息缓存区/* USER CODE END RTOS_THREADS */
}

(3)RTC的唤醒中断

        在RTC的唤醒中断里读取当前时间,将其转换为字符串后写入消息缓冲区。RTC唤醒中断的回调函数是HAL_RTCEx_WakeUpTimerEventCallback()。为便于使用消息缓冲区句柄变量msgBuffer,在文件freertos.c中重新实现这个回调函数:

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{RTC_TimeTypeDef sTime;RTC_DateTypeDef sDate;if (HAL_RTC_GetTime(hrtc, &sTime,  RTC_FORMAT_BIN) != HAL_OK)return;if (HAL_RTC_GetDate(hrtc, &sDate,  RTC_FORMAT_BIN) !=HAL_OK)return;char dtArray[MSG_MAX_LEN];   						//存储消息的数组, MSG_MAX_LEN=20if ((sTime.Seconds % 2)==0)  						//分奇偶秒,发送不同长度的消息字符串siprintf(dtArray,"Seconds = %u",sTime.Seconds);	//转换为字符串,自动加'\0'elsesiprintf(dtArray,"Minute= %u",sTime.Minutes);	//转换为字符串,自动加'\0'uint8_t bytesCount=strlen(dtArray);					//字符串长度,不带最后的结束符BaseType_t  highTaskWoken=pdFALSE;if (msgBuffer != NULL){uint16_t  realCnt=xMessageBufferSendFromISR(msgBuffer,dtArray, bytesCount+1, &highTaskWoken);  // bytesCount+1,带结束符'\0'printf("Write bytes=   %d\r\n", realCnt);		 //实际写入消息长度portYIELD_FROM_ISR(highTaskWoken);				 //申请进行一次任务调度}
}int __io_putchar(int ch)
{HAL_UART_Transmit(&huart3,(uint8_t*)&ch,1,0xFFFF);return ch;
}
/* USER CODE END Application */

        上述程序首先读取RTC的时间和日期,根据当前时间的秒数是奇数还是偶数,生成不同长度的字符串数据并保存到数组dtArray里。这里用到了C语言标准库中的两个函数siprintf()和strlen()。siprintf()与printf()类似,只是把字符串写入一个数组,并且在字符串最后自动添加结束符\0。strlen()用于得到字符串的长度,但是不包括最后的结束符。

        在使用函数xMessageBufferSendFromISR()向消息缓冲区写入消息时,执行的代码如下:

uint16_t realCnt = xMessageBufferSendFromISR(msgBuffer,dtArray,bytesCount+1,&highTaskwoken);

        这里传递的第3个参数值是bytesCount+1,也就是加上了字符串的结束符,否则,读取者读出的消息字符串将不带结束符,串口助手将无法正常显示字符串。bytesCount+1的值必须小于或等于MSG_MAX_LEN。

        函数的返回值realCnt是实际写入的消息长度,不带消息头的4个字节。如果消息写入成功,那么realCnt等于bytesCount+1。

        这里写入消息的数据是字符串,这只是为了演示方便,实际写入消息的数据可以是任意类型的数据,而不一定是字符串。

(4)任务Task_Show的功能

        在任务Task_Show里读取消息缓冲区里的消息,并在串口助手上显示,其任务函数代码如下:

/* USER CODE BEGIN Header_AppTask_Show */
/*** @brief  Function implementing the Task_Show thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_AppTask_Show */
void AppTask_Show(void *argument)
{/* USER CODE BEGIN AppTask_Show *//* Infinite loop */uint8_t dtArray[MSG_MAX_LEN];								//读出的数据临时保存数组for(;;){uint16_t realCnt=xMessageBufferReceive(msgBuffer, dtArray,MSG_MAX_LEN, portMAX_DELAY);					//读取消息printf("Read message bytes  =  %d\r\n", realCnt);		//实际读出字节数printf("message string Read =  %s\r\n", dtArray);		//显示读出的消息字符串}/* USER CODE END AppTask_Show */
}

        上述程序用函数xMessageBufferReceive()读取消息缓冲区里的消息,然后在串口助手上显示实际读取的消息长度和消息字符串。调用函数xMessageBufferReceive()的代码如下:

uint16_t realCnt = xMessageBufferReceive(msgBuffer,dtArray,MSG_MAX_LEN,portMAX_DELAY);

        其中,dtArray是用于存储读出数据的uint8_t类型数组,传递的第3个参数是MSG_MAX_LEN,也就是最大可以读取的消息的长度。函数返回值realCnt是实际读取的消息的长度,不包括消息头的4个字节。MSG_MAX_LEN应该大于或等于realCnt,否则,会导致无法读出一条完整的消息。

3、运行调试

        构建项目后,下载到开发板上并运行测试,会发现显示的写入消息长度和读出消息长度是一致 的,串口助手上显示的消息字符串也是正确的,说明可以写入和读出不同长度的消息。在实际使用消息缓冲区时,写入者和读取者之间应该定义好消息的格式,如同串口通信一样定义通信协议。

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

相关文章:

  • 福建建设工程有限公司网站班级优化大师免费下载学生版
  • 为什么百度地图嵌入网站不显示百度关键词推广公司
  • 服务器怎么租用青岛推广优化
  • 做网站需要注意的事项营销推广费用方案
  • 软件开发工作岗位windows优化大师要会员
  • 网站做目录中百度站长平台网站收录
  • 网站备案 代办自己代理一款手游需要多少钱
  • 环保类网站建设网站seo外包价格
  • 做调查靠谱的网站有哪些上海做关键词推广企业
  • 互联网网站有哪些网络推广公司哪家好
  • 廊坊企业网站团队口碑营销渠道
  • 郑州居家办公全员核酸广州百度推广优化排名
  • app加网站开发seo培训教程
  • 广州市羊城晚报郑州网站建设推广优化
  • 幼儿园建设网站意义seo关键词排名优化系统
  • php做网站好吗如何优化推广中的关键词
  • 网站开发所用到的技术seo专员
  • 化妆品可做的团购网站有哪些百度网盘搜索引擎入口官网
  • 如何做搞笑的视频视频网站网站运营和维护
  • 建筑公司转让seo快速排名代理
  • 江苏网站建设电话免费私人网站建设软件
  • 温州网站设计网站搭建平台都有哪些
  • WordPress日主题登录问题厦门seo屈兴东
  • 网站tag页面如何做营销网站制作公司
  • 视频网站自己做服务器会计培训班一般多少钱
  • 电商网站seo怎么做seo排名优化工具
  • 大连网络建站公司分析广州网络营销
  • 备案的网站 ,能拿来做仿站吗网站关键词提升
  • 建立手机个人网站app开发价格表
  • 合肥营销型网站建设百度推广投诉人工电话