第三节 调试消息队列
# 目录
# 3.0 课程资源
视频课链接 (opens new window) 密码:73enra
源代码链接:文件分享 (opens new window) 密码:vegtf7
消息队列调试-知乎文章 (opens new window)
# 3.1 什么是调试消息队列
单片机对实时性要求很高,也就是说,要求单片机快速反应、快速反馈,千分之一秒也不能等。 大部分调试过程中,要求输出信息都是要等待一段时间,再输出调试信息,无时无刻的输出调试信息是影响到单片机效率的。
消息队列是为了解决这个问题产生的。 我们输出调试信息时,如何保证实时性还尽量少占用单片机资源。最佳方式是消息队列。
它的基本原理是,我们输出简短的信息,甚至仅仅是一个数字、字符。用来展示单片机运行到的关键位置、关键参数。先把这些简短信息保存到一个缓冲区(一般是数组、结构等缓冲区),然后等等1~X秒不等再,把整个数组等缓冲区信息一起发送出来,这样既不影响单片机运行,也能获得我们调试的关键运行流程、关键参数。
# 3.2 目标
- 学会消息队列方式调试
- 知道通过消息队列可以节约单片机资源
- 节省代码空间,
- 很少占用单片机运行时间片
- 知道通过消息队列可以指导程序的运行流程
- 知道通过消息队列可以准确程序问题点
# 3.3 消息队列实现
需要两个文件:
- message.c
- message.h
头文件 message.h
#ifndef __MESSAGE_H__
#define __MESSAGE_H__
typedef char message;
#define QUEUELEN 64 //消息队列缓冲区大小
extern void PutMessage(message m); //送入一个字符到消息队列
extern void PutMsg(char *strMsg); //送一个字符串到消息队列
extern void Message_task(void); //将消息发送到串口输出
#endif
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
源文件 message.c
#include "message.h"
#include "string.h"
#include "main.h" //这里注释掉看错误
/*=============消息处理机制定义=================*/
char Messages[QUEUELEN]; //消息队列缓冲区
unsigned char MessageHead = 0; //消息队头
unsigned char MessageTail = 0; //消息队尾
void PutMessage(char m);
//消息发布
void PutMessage(char m)
{
Messages[MessageTail] = m ;
if(++MessageTail>=(QUEUELEN)) MessageTail=0;
}
//获取消息缓冲区的消息
message GetMessage(void)
{
message m = Messages[MessageHead];
if(++MessageHead>=QUEUELEN) MessageHead=0;
return m ;
}
//判断队列是否空或者错
bit QueueEmptyOrError(void)
{
return (MessageHead==MessageTail)?1:0;
}
void Message_task(void)
{
unsigned char bCount;
static unsigned int delayRS232;
if(++delayRS232>200) //延时输出
{
delayRS232=0;
if(!QueueEmptyOrError())
{
for(bCount=0; bCount<QUEUELEN; bCount++) {
//USART_SendData(UART4,(Messages[bCount]));
//uartSend(',');
SendData(Messages[bCount]);
//rt_kprintf("%c",Messages[bCount]);
}
SendData('\r');
SendData('\n');
}
}
}
void PutNumMsg(unsigned char num)
{
//PutMessage(num/100);
PutMessage(0x30+(num&0xFF)/10);
PutMessage(0x30+(num&0xFF)%10);
}
void PutMsg(char *strMsg)
{
unsigned int i;
unsigned int length = strlen(strMsg);
//while(*(strMsg+i)!='\0')
for(i=0;i<length;i++)
{
PutMessage(strMsg[i]);
PutMessage(strMsg[i+1]); //双字节存储?? 指针十六位数据?
i++;
}
}
/*
void sendstrs(char *str)
{
static unsigned char i,delay;
unsigned char length=strlen(str);
//if(++delay>100) //如有必要启动延时 此处不用是Message_task调用时已经延时
{
delay=0;
for( i=0; i<length; i++) // sizeof(*str) 如果str是数组 这样得到只是数组首地址尺寸 ...
{
//在主函数while(1)中 不延时会陷入死循环
USART_SendData(UART4,(*(str+i)));
}
}
}
uint8 HexToChar(uint8 temp)
{
uint8 dst;
if (temp < 10) {
dst = temp + '0';
} else {
dst = temp -10 +'A';
}
return dst;
}
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 3.4 仿真调试
还是使用proteus 仿真测试,具体看视频课程。