芯查查logo
  • 物料选型
  • 数据服务
    1. 新产品
    2. 查替代
    3. 丝印反查
    4. 查品牌
    5. PCN/PDN
    6. 查方案
    7. 查代理
    8. 数据合作
  • SaaS/方案
      SaaS产品
    1. 供应链波动监测预警
    2. 半导体产业链地图
    3. BOM管理
    4. 解决方案
    5. 汽车电子
    6. 政府机构
    7. 数据API
  • 商城
  • 行业资讯
    1. 资讯
    2. 直播
  • 论坛社区
    1. 论坛
    2. 学习
    3. 测评中心
    4. 活动中心
    5. 积分商城
  • 查一下
【星允派 NEBULA PI】17:使用消息队列创建工程项目
原创 发布时间:前天 19:09
版块:
单片机/MCU论坛
简介:使用消息队列,完成项目的正常运行。

之前使用时间任务调度的方式,完成任务调度处理。今天和大家分享另外一种任务调度的方法。

一:消息队列的基础知识:

1、消息队列只 是一种先进先出的队列型数据结构口,实际上是系统内核中的一个内部链表。消息被顺序插入队列中,其中发送进程将消息添加到队列未尾,接受进程从队列头读取消息。

2、多个进程可同时向一个消息队列发送消息,也可以同时从一个消息队列中接收消息。发送进程把消息发送到队列尾部,接受进程从消息队列头部读取消息,消息一旦被读出就从队列中删除。在主程序中进行处理任务,删除任务。若不删除任务,会导致任务堆栈的溢出,从而导致程序的进入硬件错误。

二:结构:

1:消息队列中消息本身由消息类型和消息数据组成,通常使用如下结构:

typedef  struct MESSAGE0    //消息结构体
{
   int iWParm;   //消息参数
   int iLParm;
   int Mnumber;  //消息值,取值1-254
}MESSAGE;

1) iWparm 指定了消息类型,为正整数。

引入消息类型之后,消息队列在逻辑上由一个消息链表转化为多个消息链表。发送进程仍然无条件把消息写入队列的尾部,但接收进程却可以有选择地读取某个特定类型的消息中最接近队列头的一个,即使该消息不在队列头。相应消息一旦被读取,就从队列中删除,其它消息维持不变。

2)iLParm指定了消息的数据。我们可以定义任意的数据类型甚至包括结构来描述消息数据。

 

2:消息队列的创建:

定义消息队列的深度和当前指针的个数

MESSAGE ArrayMessage[MES_MAX];   //消息队列最大64
static char  CurrentMesgPoint;   //当前需要操作的消息指针

3:具体的创建任务如下所示:

/***************************************************************************************
SendMessage()
发送消息到消息队列
Mnumber:消息值
WParm:消息参数1
LParm:消息参数2
****************************************************************************************/
void SendMessage(char Mnumber,int WParm,int LParm)
{
    char i;
    CurrentMesgPoint++; //这样处理的原因是避免在SendMessage函数重入导致的消息被改写的BUG
    if(CurrentMesgPoint >= MES_MAX)
        CurrentMesgPoint = 0;
    i = CurrentMesgPoint;
    if(ArrayMessage[i].Mnumber == 0)
    {
        ArrayMessage[i].Mnumber = Mnumber;
        ArrayMessage[i].iWParm = WParm;
        ArrayMessage[i].iLParm = LParm;
        return;
    }
}

4:删除任务:

/***************************************************************************************
DeleteMessage()
从消息队列中删除消息
MPoint:消息队列数组下标
***************************************************************************************/
void DeleteMessage(char MPoint)
{
    ArrayMessage[MPoint].iWParm = 0;
    ArrayMessage[MPoint].iLParm = 0;
    ArrayMessage[MPoint].Mnumber=0; //避免函数重载出现BUG,对Mnumber的改写放在最后面
}

5:在定时器中添加不同间隔的消息队列:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */

  /* USER CODE BEGIN Callback 1 */
  if (htim->Instance == TIM6) 
  {
		Time6point++ ;
		if(Time6point %100 == 0)
				SendMessage(MW_TIMERINT,1,0);  //发出TIM 100ms中断消息
		if(Time6point %200 == 0)
				SendMessage(MW_TIMERINT,2,0);  //发出TIM 200ms中断消息
		if(Time6point %500 == 0)
				SendMessage(MW_TIMERINT,5,0);  //发出TIM 500ms中断消息
		if(Time6point %1000 == 0)
		{
			 Time6point = 0 ;
			 SendMessage(MW_TIMERINT,10,0);  //发出TIM 1000ms中断消息
		}
	}
}

时间任务的处理函数如下所示:

void System_Tim_Driver(char Tim_Intev)
{
    switch(Tim_Intev)
    {
        case 1:
								
        break;
        case 2:     HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);
        break;
        case 5:   	printf("STM32F103VETEST!  by queue test!!\n");//500ms
        break;
        case 10:   
         break ;
        default:break;
    }
}

主程序中添加任务处理,删除的函数如下所示:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
        mspoint ++;
        if(mspoint>=MES_MAX)    mspoint = 0;    //消息循环查讯
        if(ArrayMessage[mspoint].Mnumber !=0)
        {
            switch(ArrayMessage[mspoint].Mnumber)
            {
                case MW_TIMERINT:
                         System_Tim_Driver(ArrayMessage[mspoint].iWParm);
                break;
                default:
                break;
            }
            DeleteMessage(mspoint);  //删除已经处理的消息
        }
  }

实物验证如下所示:

后记:

1、采用消息队列方式比之前采用时间任务调度具有更多的灵活性,通信的进程不但没有时间上的要求,也不需要进行同步处理。只需要根据消息触发的顺序,进行执行,从响应时效性上更加的灵活。

2、消息队列是一种先进先出的队列型数据结构;

3、消息队列将输出的信息进行了打包处理,可以保证以消息为单位进行接收;为了防止消息队列的溢出,可以将任务队列加大,从而使实现任务深度的增加,防止任务的丢失。

申请原创奖励
前天 19:09
  • 举报
😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷😸😹😺😻😼😽😾😿🙀🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏✂✅✈✉✊✋✌✏✒✔✖✨✳✴❄❇❌❎❓❔❕❗❤➕➖➗➡➰🚀🚃🚄🚅🚇🚉🚌🚏🚑🚒🚓🚕🚗🚙🚚🚢🚤🚥🚧🚨🚩🚪🚫🚬🚭🚲🚶🚹🚺🚻🚼🚽🚾🛀Ⓜ🅰🅱🅾🅿🆎🆑🆒🆓🆔🆕
@好友

全部评论

加载中
游客登录通知
已选择 0 人
自定义圈子
移动
发布帖子
发布动态
发布问答
发布者
聪聪哥哥
最新帖子
【星允派 NEBULA PI】17:使用消息队列创建工程项目【拆解活动】开源恒温加热台拆解分析5A快速充电宝1.0【开源项目】DIY智能手表Monica:极客的腕上科技艺术品【星允派 NEBULA PI】09:USB虚拟CDC与串口1
热门版块
查看更多
问型号
问技术
问行情
汽车电子工程师论坛
工业电子专区
新手入门指南
单片机/MCU论坛
PCB设计
开源项目
电子DIY

点赞

收藏

分享

微信扫码
分享给好友

评论