stm32 ucosii消息队列 串口_Freertos操作系统基础篇【第二篇】队列

上文中提到单片机中竟然能用printf函数,一般这种输出打印格式在上位机软件开发调试中会经常使用到。众所周知,嵌入式软件就是数据流的控制。在单片机开发中使用printf函数进行数据流的观测极大方便开发人员调试,在不进行断点调试中,对关键点的信息进行及时的输出,方便开发人员知道信息数据流的流动情况和数据是否正确。下面讲解如何在单片机中使用printf函数。

第一步,需要将单片机的USART调试成功并且初始化,然后将串口的发送和接收函数重构如下:

1//发送字符串 2int fputc(int ch, FILE *f) 3{ 4 5   USART_SendData(USART1, (u8) ch); 6 7 8   while(!(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == SET)) 9   {10   }1112   return ch;13}14/*接收一个字节数据*/15int fgetc(FILE *f)16{1718   while(!(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET))19   {20   }2122   return (USART_ReceiveData(USART1));23}

第二步,打开KEIL工程中的Project->Options for Target '***',选项卡如下,勾选上 "Use MicroLIB",便能够实现单片机通过串口实现printf函数。microlib 是缺省 C 库的备选库。它旨在与需要装入到极少量内存中的深层嵌入式应用程序配合使用。

48222ce35730ac691799f8d6f6f6f1b7.png         言归正传 ,讲解今天的主要内容 队列 。 在裸板开发中两个应用程序之间需要进行数据交互时候,一般会通过全局变量进行数据交互,如果在操作系统开发中使用大量的全局变量进行数据交互时候,就会涉及到“资源管理”问题,为此FreeRTOS提供了一种叫做“队列”的机制进行任务与任务之间,任务与中断之间的数据交互。 FreeRTOS提供的队列支持FIFO存储缓冲,同时也支持LIFO存储缓冲(这就涉及到了数据结构相关的知识,后续有时间的话讲解下数据结构),需要注意的是FreeRTOS提供的队列是采用值传递方式。 1、队列原理

下面讲解下采用FIFO机制下的队列数据的写入和读出。为了实现任务A和任务B通讯,创建了一个可以容纳5个整数的队列,队列在创建时不包含任何数据,所以队列是空的如图1所示。

ff862fe87774532b58ec255ed697e112.png

图 1 创建任务

任务A向队列中写入x的值,由于创建队列时队列为空,写入的10既在队列的尾也在队列的首。因为FreeRTOS采用的是值传递,所以当10写入队列中后,x可以再次被使用,x值改为20,再次向队列中写入,因此队列中包含两个数值,10在队列首部,20在队列尾部如图2 所示

42ee585a45dda771b52e915fc098cdde.png 96e40b2cde71247ad1e85e5faf089244.png

图 2 写入队列

任务B从队列中读取一个数值,首先位于队列首部的10会被任务B读取,赋值给y,既y=10,读取完成后,10将会被移除队列,20将会移动到10的位置,即队列首部,此时队列中剩余四个空位。如图3所示。

1c4313a3a1e286f4495b84b106e6fd99.png 517c7ce11461e731f50b2e95c2071b7a.png

图 3 读队列、

在进行入队和出队操作时,FreeRTOS支持“入队阻塞”和“出队阻塞”,下面讲解下入队阻塞,当任务A向队列发送消息时,此时若队列满,此时任务A向队列写入不了任何数据,FreeRTOS应对此种情况提供了三种方式:

  • 不等待,立马执行接下来的代码。
  • 等待一定时间,在等待时间内如果队列空,则任务跳转至就绪态,若超过等待时间,自动转为就绪态。
  • “死等”,一直等,直到队列为空。
2、 代码编写

创建两个任务,一个串口接收中断,串口接收中断接收数值后写入串口队列中;任务1向数值队列中写入定数值;任务二打印串口中断中写入串口队列中的数值,打印任务一种写入数值队列中的数值。代码如下:

串口中断中向串口队列写入数值:

1void  USART1_IRQHandler(void) 2{     3    BaseType_t xHigherPriorityTaskWoken; 4    static uint8_t  Res=0;    5    xHigherPriorityTaskWoken = pdFALSE; 6    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  7        { 8        RXbuffer[Res] =USART_ReceiveData(USART1);    //读取接收到的数据   9        Res++;  10        if(Res ==ConfigUASRTRxLength)11             Res =0;12         printf("Res is %d\r\n",Res);13//向串口队列中写入数值     14        xQueueSendFromISR( USART_Handler, &RXbuffer, &xHigherPriorityTaskWoken );         15         USART_ClearITPendingBit(USART1, USART_IT_RXNE);// 清除中断标志16         USART_ClearFlag(USART1,USART_IT_RXNE); //一定要清除接收中断 17         portYIELD_FROM_ISR( xHigherPriorityTaskWoken );         18        }19//溢出-如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题20  if(USART_GetFlagStatus(USART1,USART_FLAG_ORE) == SET)21    {22      USART_ReceiveData(USART1);23      USART_ClearFlag(USART1,USART_FLAG_ORE);24     }    25}

任务1向数值队列中写入数值,任务2打印两个队列中的数值。

1//task1 向数值数列中写入定值  2void task1_task(void *pvParameters) 3{ 4    uint8_t temp=10; 5    while(1) 6    { 7        if( xQueueSend( KEY_Q_Handler,&temp,10 )!=pdTRUE) 8        { 9            printf("send to queue is error,queue is full\n\r");10        }else11        {12            printf("senddata is  %d\n\r",temp);13        }14     vTaskDelay(1000);  15    }16} 17//task2 读取两个队列中的数值,并打印18void task2_task(void *pvParameters)19{20    uint8_t  recdata;21  uint8_t buffer[ConfigUASRTRxLength],u;22    while(1)23    {24            if( xQueueReceive( KEY_Q_Handler, &recdata, 10 ) != pdPASS )25            {26                    printf("receive queue is error,queue is empty\n\r");27            }else28            {29                printf("recedata is %d\n\r",recdata);30            }3132        if( xQueueReceive( USART_Handler, &buffer, 10 ) != pdPASS )33            {34                    //printf("receive queue is error,queue is empty\n\r");35            }else36            {37                for(u=0;u38                printf("buffer is %c\n\r",buffer[u]);39            }4041            vTaskDelay(1000);42    }43} 

3、测试

通过串口调试软件向下发送1~5,串口中断接收到后写入队列,在任务2中打印出来,任务2同时打印任务1向数值中断中写入的10,测试结果如下:

2f3b696dc42bd077b8e174c2b8db09a8.png

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值