C语言非OS编程架构

本文介绍了一种适用于单片机非操作系统程序的良好架构设计方案。该方案将系统分为驱动层、功能模块层和任务调用层三个层级,通过模块化设计降低耦合性,提高代码复用性和维护性。文章详细阐述了各层的设计原则和具体实现方法。

    对于单片机非OS程序来说好的架构必须具备如下特点:代码规范优雅,结构清晰,各模块之间低耦合。个人根据多年工作经历,总结如下:编写代码前应进行结构设计,C语言是面向过程的语言,所以一般系统结构分为三层:驱动功能模块层,任务调用层。为了降低耦合性,函数调用规则尽可能做到上层调用下层。

 

 

驱动

    非OS驱动层一般由硬件抽象层(HAL)和驱动程序组成,是系统中不可或缺的重要部分。它的作用是为上层程序提供外部设备的操作接口,并且实现设备的驱动程序。上层程序可以不管操作的设备内部实现,只需要调用驱动的接口即可。 

其中HAL只是对硬件的一个抽象,对一组API进行定义,却不提供具体的实现。HAL设计的一些要素是:

  1.   与硬件的密切相关性
  2.   与上层任务的无关性
  3.   接口的功能包括硬件或者系统所需硬件支持的所有功能
  4.   接口简单明了

例如我们想读取i2c设备上某个寄存器指定位的值,我们可以如下封装。

uint8_t RegisterGetField(uint8_t ChipAddr,
                         uint8_t Address,
                         uint8_t StartBit,
                         uint8_t FieldLong) 
{
    uint8_t ucBuffer;

	i2c_read(ChipAddr, Address, &ucBuffer);

    ucBuffer <<= (7 - StartBit);
    ucBuffer >>= (8 - FieldLong);

    return ucBuffer;
}

功能模块层

对于一个非OS系统,除了项目所需的需求模块,常用的功能模块应该包括:

  1. 消息模块
  2. 定时器模块
  3. 调试模块

消息模块主要用于各个任务之间参数的传递。例如串口接收到的数据包经过分析后,需要显示,保存。。。

void msg_wait_for_event(message_id_t *event,
                        void *data_ptr, 
                        uint16_t *data_size);
bool_t msg_post_event(message_id_t event,
                      void *data_ptr, 
                      uint16_t data_size);

定时器模块实现各种任务的轮询。例如键盘扫描,ADC采样。。。

个人喜好的定时器模块的数据结构如下:

typedef struct timer_tag {
    void (*timeout_func)(void *parameter);   /**< timeout function */
    void            *parameter;              /**< timeout function's parameter */

    uint32_t        init_tick;      /**< timer timeout tick */
    uint32_t        timeout_tick;   /**< timeout_tick = sys_tick + init_tick */

    uint8_t         flag;           /*bit0: TIMER_FLAG_ACTIVATED
                                      bit1: TIMER_FLAG_PERIODIC
                                      bit6: TIMER_FLAG_TIMEOUT
                                      bit7: TIMER_FLAG_USED
                                     */
} timer_t;

任务调用层

顶层的任务调度是系统运行起来的基本功能集合,来实现整个系统的功能,任务基本分为四个部分看门狗管理,定时任务,消息处理任务,中断任务Main函数结构大体如下:

void main(void)
{

    /*各个模块的初始化*/
    init();

    While(1)
    {
        /*喂狗*/
        feed_dog();

        /*各类消息汇总处理*/
        Handle_message();

        /*定时器任务*/
        timer_task();

        /*其他中断任务*/
        others_task();
    }

}

注:任务处理程序内部结构最好用状态转移法,这样设计的目的是模拟RTOS系统的多任务模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值