良许Linux教程网 干货合集 嵌入式并行多线程处理器,了解一下!

嵌入式并行多线程处理器,了解一下!

在嵌入式开发中,标志位处理是不可避免的,特别是对于玩单片机、裸机开发的朋友来说。例如,在与一些模块配合进行联调时,可能会遇到各种信号是否到位、是否成功等状态的处理,而这些信号往往都是布尔类型,只需要一个bit来进行标识。

当然,如果只涉及几个标志位,直接使用一个uint8_t类型的整数来进行标识并不会造成太大的内存浪费。

然而,为了更好地管理这些标志位,下面提供几种方式以便大家更好地管理:

位域直接标识

采用位域是管理这些标志位比较直接且方便的方式,代码如下所示:

 1typedef union _tag_SystemFlag
 2{
 3    uint16_t all;
 4    struct 
 5    {
 6        uint16_t Run         :1;
 7        uint16_t Alarm       :1;
 8        uint16_t Online      :1;
 9        uint16_t TimerOver   :1;
10        uint16_t Reserver    :12;
11    }bit;
12
13} uSystemFlag;
14
15uSystemFlag  unSystemFlag;
16
17int main(int argc, char *argv[]) {
18
19    unSystemFlag.all = 0x00; //系统标志清除
20
21    unSystemFlag.bit.Run       = 1; //置位
22    unSystemFlag.bit.Alarm     = 1;
23    unSystemFlag.bit.Online    = 1;
24    unSystemFlag.bit.TimerOver = 1;
25
26    unSystemFlag.bit.Run       = 0; //清零
27    unSystemFlag.bit.Alarm     = 0;
28    unSystemFlag.bit.Online    = 0;
29    unSystemFlag.bit.TimerOver = 0;
30
31    return 0;
32}

这些标志位的操作无非就是置位、清零,以及读取三种方式。

但如代码中这样的操作方式在语句或语义表达上还是不够直观。

我经常谈到,代码可以不写注释,不过你的每个变量、函数名称等需要足够的直观,所以很多朋友习惯把这些标志封装起来。

2

枚举+移位

为了更好的表达一般会对标志位进行进一步的封装,如下代码所示:

 1typedef enum _tag_Flag {
 2cEmRun = 0,
 3cEmAlarm,
 4cEmOnline,
 5cEmTimerOver
 6}emSystemFlag;
 7
 8uint16_t SystemFlag ;
 9//置位
10void SetFlag(emSystemFlag flag)
11{
12    SystemFlag |=  ((uint16_t)0x01) return (((SystemFlag & (((uint16_t)0x01) true:false);  
23}
24
25int main(int argc, char *argv[]) {
26
27    SetFlag(cEmAlarm);
28
29    if(GetFlag(cEmAlarm) == true)
30    {
31        printf("ClrFlag\r\n");
32        ClrFlag(cEmAlarm);
33    }
34    else
35    {
36        printf("SetFlag\r\n");
37        SetFlag(cEmAlarm);
38    }
39    return 0;
40}

当然,封装成函数是相对比较耗时的,不过代码也会更加的易懂,如果确实容忍不了函数封装带来的时间消耗,把函数修改为宏代码片段或者内敛函数(前提是编译器支持)也是可行的。

3

宏列表

或许这里才是本文的重中之重~

以前跟大家介绍过,用宏自动化的生成各种代码片段,以使得代码更加的紧凑。当然可读性会相对降低一点,但对于重复性代码就不需要太多考虑了。

 1#include 
 2#include 
 3
 4typedef unsigned char uint8_t;
 5typedef unsigned int uint16_t;
 6typedef signed char int8_t;
 7typedef int  int16_t;
 8
 9#define true  1
10#define false 0
11
12
13//宏列表
14#define TAG_LIST(tag) \
15tag(Run)\
16tag(Alarm)\
17tag(Online)\
18tag(TimerOver)
19
20
21//枚举处理
22#define DEFINE_TAG(_tag) _tag,
23enum Flag {
24None = 0,
25TAG_LIST(DEFINE_TAG)
26EmMAX
27};
28#undef DEFINE_TAG
29
30//位定义变量
31uint16_t SysFlag = 0x0000;
32
33
34//通用方法定义
35uint8_t GetFlags(uint16_t mask)
36{
37    return ((SysFlag & mask) != 0)? true:false;
38}
39
40void SetFlags(uint16_t mask)
41{
42     SysFlag |=  mask;
43}
44
45void ClrFlags(uint16_t mask)
46{
47     SysFlag &=  ~mask;
48}
49
50
51//自动生成三类函数定义
52#define FLAG_Operater(flag) \
53uint8_t  get##flag()  {\
54return GetFlags(1 set##flag() {\
57SetFlags(1 ##flag() {\
60ClrFlags(1 if(getAlarm() == true)
72    {
73        printf("set \r\n");
74    }
75    else
76    {
77        printf("clr \r\n");
78    }
79
80    return 0;
81}

如果以前有过类似代码处理的朋友,应该看这段代码还是比较轻松的吧,如果有点生疏,可以一层一层展开了解。

其主要的功能是,通过宏替换和代码拼接符号,自动的生成通用的代码片段。这样做的好处是,不再需要我们在代码中定义一大堆setflag、clrflag、getflag等函数。

通过上面的代码当我们向TAGLIST宏中添加一个标识符,即可生成一系列相关的操作函数等。

这样一方面可以及简化代码,同时也能避免一些人工编码带来的错误。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部