signed

QiShunwang

“诚信为本、客户至上”

单片机开发——应用消息队列处理事件

2020/8/19 21:27:13   来源:

消息队列的5个常见应用场景

https://segmentfault.com/a/1190000017130224

想要在单片机开发应用消息队列处理事件主要是为了解耦,减少模块与模块之间的耦合。

看过挺恶心的代码,一个事件就用一个变量做标志位,全局变量满天飞。 就想着用消息队列模仿消息驱动的机制来处理事件。

有类似这样处理的:
https://blog.csdn.net/u012210286/article/details/83313099

然而这样的话处理队列事件的函数在每次增减消息都要去改动,所以想写个每次增加消息处理函数不用修改的

实现

数据结构:

typedef struct msg_node{
	void *parm;
	void (*handler)(void *parm);	
}msg_node_t;  /* 消息数据结构 */

typedef struct msg_driver{
    unsigned int in;               //写入的位置
    unsigned int out;              //读出的位置
    msg_node_t *buf[MSG_DRIVER_SIZE];    
}msg_driver_t;

将消息插入到消息队列中:

这里就直接将事件的处理函数直接插入到队列中,缺点就是比较浪费资源。

bool publish_msg(msg_driver_t *msg_buf, msg_node_t *msg)
{
    if( is_msg_buf_full (msg_buf) == TRUE )
    {
        return FALSE;
    }

    msg_buf->buf[msg_buf->in] = msg;
    msg_buf->in = (++msg_buf->in) % MSG_DRIVER_SIZE;    //防止越界
	
	return TRUE;
}

获取消息:

static msg_node_t *get_messge(msg_driver_t *msg_buf)
{
	msg_node_t *msg = NULL;
    if( is_msg_buf_empty(msg_buf) )
    {
        return NULL;
    }

    msg = msg_buf->buf[msg_buf->out];
    msg_buf->out = (++msg_buf->out) % MSG_DRIVER_SIZE;    //防止越界

    return msg;
} 

从队列循环取出消息处理:

由于每次发布消息都是送的处理函数指针,所以处理函数都不用修改。

void message_driver_handle(msg_driver_t *msg_buf)
{
	msg_node_t *msg;
	while( (msg = get_messge(msg_buf)) != NULL )
	{
		msg->handler(msg->parm);
	}
}

简单的测试是可行

msg_driver_t msg_driver;

static void msg1_handle(void *parm)
{
	printf("gets msg1\r\n");
}

static void msg2_handle(void *parm)
{
	printf("get msg2\r\n");
}

static void msg3_handle(void *parm)
{
	printf("do msg3\r\n");
}

msg_node_t msg1 = {
	.parm = "I love u",
	.handler = msg1_handle
};

msg_node_t msg2 = {
	.parm = "I hate u",
	.handler = msg2_handle
};

msg_node_t msg3 = {
	.parm = NULL,
	.handler = msg3_handle
};

publish_msg(&msg_driver, &msg1);
publish_msg(&msg_driver, &msg2);
publish_msg(&msg_driver, &msg3);

int main(void)
{
	while(1)
	{
		 message_driver_handle(&msg_driver);
	}
}

应该还是可以有更好的方法,比较菜,想不出来了。