目录
1 邮箱
邮箱是特殊的队列,具有如下特点:
- 队列长度只有1。
- 写邮箱:新数据覆盖旧数据 ,既然是覆盖,那么无论邮箱中是否有数据,这些函数总能成功写入数据。
- 读邮箱:读数据时,数据不会被移除 这意味着,第一次调用时会因为无数据而阻塞,一旦曾经写入数据,以后读邮箱时总能成功。
2 示例程序
2.1 例程功能
创建一个邮箱,按键按下即往邮箱里面发送结构体地址并且结构体中的变量自增,创建另一个任务用来接收邮箱传来的结构体地址,并将结构体中的数据打印出来。
2.2 步骤
创建两个动态任务
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct
{
uint32_t var1;
uint32_t var2;
uint8_t var3;
}Amail_TypeDef;
/* USER CODE END PTD */
/*......*/
/* USER CODE BEGIN Init */
osMailQDef(mail,32,Amail_TypeDef);
myosMailQId=osMailCreate(osMailQ(mail),NULL);
/* USER CODE END Init */
定义一个结构体和创建一个邮箱
/* USER CODE END Header_StartTask_KEY */
void StartTask_KEY(void const * argument)
{
/* USER CODE BEGIN StartTask_KEY */
/* Infinite loop */
Amail_TypeDef *pTMail;
uint32_t ProducerValue1=0;
uint32_t ProducerValue2=0;
uint8_t ProducerValue3=0;
for(;;)
{
if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==0)
{
osDelay(10);
if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==0)
{
osThreadSuspendAll();
printf("KEY按下\n");
osThreadResumeAll();
pTMail=osMailAlloc(myosMailQId,osWaitForever);
pTMail->var1=ProducerValue1;
pTMail->var2=ProducerValue2;
pTMail->var3=ProducerValue3;
if(osMailPut(myosMailQId,pTMail)==osOK)
{
ProducerValue1++;
ProducerValue2+=2;
ProducerValue3+=3;
}
while(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==0)
{
osDelay(10);
}
}
}
osDelay(1);
}
/* USER CODE END StartTask_KEY */
}
按键按下,往邮箱里面发送数据
/* USER CODE END Header_StartTask01 */
void StartTask01(void const * argument)
{
/* USER CODE BEGIN StartTask01 */
/* Infinite loop */
osEvent event;
Amail_TypeDef *pRmail;
for(;;)
{
event=osMailGet(myosMailQId,osWaitForever);
if(event.status==osEventMail)
{
pRmail=event.value.p;
printf("%d %d %d \n",pRmail->var1,pRmail->var2,pRmail->var3);
osMailFree(myosMailQId,pRmail); //将分配的内存给清除
}
osDelay(1);
}
/* USER CODE END StartTask01 */
}
读取邮箱中的结构体地址,并将结构体中的数据打印出来,最后记得将分配的内存给清除
5.2.3 实验结果
按键按下,结构体成员变量自增
2.3程序源码
github链接:HaoJosephWen/FreeRtos_personal (github.com)
自我感悟
本例程所实现的邮箱的功能和韦东山描述的邮箱的功能有出入。在韦东山的视频中,邮箱是一个长度为1的队列,写邮箱会不断覆盖数据,不会阻塞,读邮箱数据不会删除,这意味着往邮箱里写一次数据,以后总能读取成功。而本例程所展现的功能更像一个不同的长度为1的队列,读邮箱数据也会删除。