《C嵌入式编程设计模式》
Bruce Powel Douglass著
刘旭东译

C嵌入式编程设计模式

标签: 读书笔记 嵌入式开发

  • C嵌入式编程设计模式

    • 1 嵌入式系统有何特殊之处

      • 11 嵌入式设计的约束
      • 12 嵌入式工具
      • 13 OSRTOS还是没有操作系统
      • 14 嵌入式中间件
      • 15 与硬件协同开发
      • 16 调试与测试
    • 2 面向对象还是结构化
      • 21 类
      • 22 对象
      • 23 多态和虚拟函数
      • 24 子类化
      • 25 有限状态机
    • 3 小结

1.1 嵌入式系统有何特殊之处

实时系统,”实时”并不意味着很快。

1.1.1 嵌入式设计的约束

减少使用硬件的需求
性能:吞吐量
可靠性:衡量系统正确完成功能的可能性
健壮性:违反先决条件下仍能提供相应服务的能力
安全性:系统的风险水平,可能会造成那些意外或者损失

1.1.2 嵌入式工具

交叉编译器:在主机上运行,开发的可执行代码在不同环境中运行
连接器
载入程序
调试器工具集
以上集成到IDE中

1.1.3 OS,RTOS,还是没有操作系统

1.1.4 嵌入式中间件

中间件是一种使用某种方法将软件组件连接的软件

1.1.5 与硬件协同开发

1.1.6 调试与测试

1.2 面向对象还是结构化

结构化编程:一方面,函数和过程形成基本的编程基础;另一方面是数据结构的概念。
面向对象编程:基于正交范式。面向对象编程仅有基于类概念的一个分类标准。类将数据(存储为属性)和在数据上的操作的过程(称为操作)组合到一起。对象是类的实例。
像C一样的结构化语言能够完成面向对象的编程么?可以。
如何实现?接着往下看。

1.2.1 类

类仅是一个C语言的结构体,但特殊之处是包含两种不同的特性:数据(属性)和行为(操作)。
最简单的实现类的方法是简单使用文件作为封装边界;公共变量和方法在头文件中课件,而在实现文件中包含方法体、私有变量和方法。
一个更为灵活的方式是使用文件内的结构体来表示类。类的操作用位于相同文件内的结构体的函数定义。
这允许我们拥有同一个类的多个实例,并且保证成员函数在正确的数据拷贝上工作。此外,类可以赋予“特殊”的操作。构造函数创建类的一个对象。初始化程序(可选择)初始化对象和它的属性。析构函数销毁类并释放已使用的内存。

代码1-1 sensor.h

#ifndef SENSOR_H
#define SENDOR_Htypedef struct sensor
{int filterFrequency;int updateFrequency;int value;char whatKindOfInterface;
}SENSOR;int Sensor_getFilterFrequency(const SENSOR* const me);
void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency);
int Sensor_getUpdateFrequency(const SENSOR* const me);
void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency);
int Sensor_getValue(const SENSOR* const me);
//int acquireValue(SENSOR* me);
SENSOR* Sensor_create(void);
void Sensor_Destroy(Sensor* const me);#endif

代码1-2 sensor.c

#include "sensor.h"void Sensor_Init(SENSOR* const me){}void Sensor_Cleanup(SENSOR* const me){}int Sensor_getFilterFrequency(const SENSOR* const me){return me->filterFrequency;
}void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency){me->filterFrequency=p_filterFrequency;
}int Sensor_getUpdateFrequency(const SENSOR* const me){return me->updateFrequency;
}void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency){me->updateFrequency=p_updateFrequency;
}int Sensor_getValue(const SENSOR* const me){return me->value;
}/*
int acquireValue(SENSOR* me){int *r, *w;int j;switch(me->whatKindOfInterface){case MEMPRYMAPPED:w=(int*)WRITEADDR; //Address to write to sensor*w=WRITEMASK;      //sensor command to force a readfor (j = 0; j < count; j++){// wait loop }r=(int*)READADDR;  //Address to returned valueme->value=r;break;case PORTMAPPED:me->value=inp(SENSORPORT);//inp() is a compliler-specific port functionbreak;}return me->value;
}
*/SENSOR* Sensor_create(void){SENSOR* me=(SENSOR*)malloc(sizeof(SENSOR));if (me != NULL){Sensor_Init(me);}return me;
}void Sensor_Destroy(SENSOR* const me){if (me != NULL){Sensor_Cleanup(me);}free(me);
}

1.2.2 对象

对象是类的实例。

代码1-3 main.c

#include "sensor.h"
#include <stdlib.h>
#include <stdio.h>int main(int argc, char const *argv[])
{SENSOR *p_sensor0, *p_sensor1;p_sensor0=Sensor_create();p_sensor1=Sensor_create();p_sensor0->value=99;p_sensor1->value=-1;printf("The current value from sensor0 is %d\n",Sensor_getValue(p_sensor0));printf("The current value from sensor1 is %d\n",Sensor_getValue(p_sensor1));Sensor_Destroy(p_sensor0);Sensor_Destroy(p_sensor1);return 0;
}

1.2.3 多态和虚拟函数

多态允许相同函数名在一种上下文中完成一种功能,在另一种上下文中完成另一种功能。
在C语言中,标准的做法是使用选择语句if或者switch。当出现多种上下文时,不方便;此外在最开始编写时就要知道所有可能的上下文,或者提供修改功能。

代码修改 1-1 sensor.h

#ifndef SENSOR_H
#define SENDOR_Htypedef struct sensor
{int filterFrequency;int updateFrequency;int value;char whatKindOfInterface;
}SENSOR;int Sensor_getFilterFrequency(const SENSOR* const me);
void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency);
int Sensor_getUpdateFrequency(const SENSOR* const me);
void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency);
//int Sensor_getValue(const SENSOR* const me);
int acquireValue(SENSOR* me);
SENSOR* Sensor_create(void);
void Sensor_Destroy(Sensor* const me);#endif

代码修改 1-2 sensor.c

#include "sensor.h"void Sensor_Init(SENSOR* const me){}void Sensor_Cleanup(SENSOR* const me){}int Sensor_getFilterFrequency(const SENSOR* const me){return me->filterFrequency;
}void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency){me->filterFrequency=p_filterFrequency;
}int Sensor_getUpdateFrequency(const SENSOR* const me){return me->updateFrequency;
}void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency){me->updateFrequency=p_updateFrequency;
}/*
int Sensor_getValue(const SENSOR* const me){return me->value;
}
*/int acquireValue(SENSOR* me){int *r, *w;int j;switch(me->whatKindOfInterface){case MEMPRYMAPPED:w=(int*)WRITEADDR; //Address to write to sensor*w=WRITEMASK;      //sensor command to force a readfor (j = 0; j < count; j++){/* wait loop */}r=(int*)READADDR;  //Address to returned valueme->value=r;break;case PORTMAPPED:me->value=inp(SENSORPORT);//inp() is a compliler-specific port functionbreak;}return me->value;
}SENSOR* Sensor_create(void){SENSOR* me=(SENSOR*)malloc(sizeof(SENSOR));if (me != NULL){Sensor_Init(me);}return me;
}void Sensor_Destroy(SENSOR* const me){if (me != NULL){Sensor_Cleanup(me);}free(me);
}

1.2.4 子类化

子类化(也被称为泛化或者继承),能够重用设计或代码。

代码 1-4 queue.h

#ifndef QUEUE_H
#define QUEUE_H#define QUEUE_SIZE 10typedef struct queue
{int buffer[QUEUE_SIZE];int head;int size;int tail;int (*isFull)(struct queue* const me);int (*isEmpty)(struct queue* const me);int (*getSize)(struct queue* const me);void (*insert)(struct queue* const me, int k);int (*remove)(struct queue* const me);
}QUEUE;void Queue_Init(QUEUE* me, int (*isFullFunction)(QUEUE* const me),int (*isEmptyFunction)(QUEUE* const me),int (*getSizeFunction)(QUEUE* const me),void (*insertFunction)(QUEUE* const me, int k),int (*removeFunction)(QUEUE* const me));
void Queue_Cleanup(QUEUE* const me);int Queue_isFull(QUEUE* const me);
int Queue_isEmpty(QUEUE* const me);
int Queue_getSize(QUEUE* const me);
void Queue_insert(QUEUE* const me, int k);
int Queue_remove(QUEUE* const me);QUEUE* Queue_Create(void);
void Queue_Destroy(QUEUE* const me);#endif

代码 1-5 queue.c

#include <stdio.h>
#include <stdlib.h>
#include "queue.h"void Queue_Init(QUEUE* me, int (*isFullFunction)(QUEUE* const me),int (*isEmptyFunction)(QUEUE* const me),int (*getSizeFunction)(QUEUE* const me),void (*insertFunction)(QUEUE* const me, int k),int (*removeFunction)(QUEUE* const me)){me->head=0;me->tail=0;me->size=0;me->isFull=isFullFunction;me->isEmpty=isEmptyFunction;me->getSize=getSizeFunction;me->insert=insertFunction;me->remove=removeFunction;
}void Queue_Cleanup(QUEUE* const me){}int Queue_isFull(QUEUE* const me){return (me->head+1)%QUEUE_SIZE==me->tail;
}int Queue_isEmpty(QUEUE* const me){return me->head==me->tail;
}int Queue_getSize(QUEUE* const me){return me->size;
}void Queue_insert(QUEUE* const me, int k){if (!me->isFull(me)){me->buffer[me->head]=k;me->head=(me->head+1)%QUEUE_SIZE;++me->size;}
}int Queue_remove(QUEUE* const me){int value=-9999;if(!me->isEmpty(me)){value=me->buffer[me->tail];me->tail=(me->tail+1)%QUEUE_SIZE;--me->size;}return value;
}QUEUE* Queue_Create(void){QUEUE* me=(QUEUE*)malloc(sizeof(QUEUE));if (me!=NULL){Queue_Init(me,Queue_isFull,Queue_isEmpty,Queue_getSize,Queue_insert,Queue_remove);}return me;
}void Queue_Destroy(QUEUE* const me){if (me!=NULL){Queue_Cleanup(me);}free(me);
}

代码 1-6 test_queue.c

#include "queue.h"
#include <stdlib.h>
#include <stdio.h>int main(void)
{int j,k,h,t;QUEUE* myQ;myQ=Queue_Create();k=1000;for (j = 0; j<QUEUE_SIZE; j++){h=myQ->head;myQ->insert(myQ, k);printf("inserting %d at position %d, size=%d\n", k--,h,myQ->getSize(myQ));}printf("Iserted %d elements\n", myQ->getSize(myQ));for (j = 0; j<QUEUE_SIZE; j++){t=myQ->tail;k=myQ->remove(myQ);printf("Removing %d at position %d, size=%d\n", k, t, myQ->getSize(myQ));}printf("Last item removed = %d\n", k);printf("Current queue size %d\n", myQ->getSize(myQ));puts("Queue test program");return 0;
}

代码 1-7 cachedqueue.h

//cached queue means the memory does not have enough space to store the whole queue
//so we divide the queue into two sides:
//one store in memory
//another store in disk#ifndef CACHEDQUEUE_H
#define CACHEDQUEUE_H#include "queue.h"typedef struct cachedqueue
{QUEUE* queue;       //base classchar filename[80];  //new attributesint numberElementsOnDisk;QUEUE* outputQueue; //aggregation in subclass//Inherited virtual functionsint (*isFull)(struct cachedqueue* const me);int (*isEmpty)(struct cachedqueue* const me);int (*getSize)(struct cachedqueue* const me);void (*insert)(struct cachedqueue* const me, int k);int (*remove)(struct cachedqueue* const me);//new virtual functionsvoid (*flush)(struct cachedqueue* const me);void (*load)(struct cachedqueue* const me);}CACHEDQUEUE;void CachedQueue_Init(CACHEDQUEUE* const me, char* filename,int (*isFullFunction)(CACHEDQUEUE* const me),int (*isEmptyFunction)(CACHEDQUEUE* const me),int (*getSizeFunction)(CACHEDQUEUE* const me),void (*insertFunction)(CACHEDQUEUE* const me),int (*removeFunction)(CACHEDQUEUE* const me),void (*flushFunction)(CACHEDQUEUE* const me),void (*loadFunction)(CACHEDQUEUE* const me));
void CachedQueue_Cleanup(CACHEDQUEUE* const me);int CachedQueue_isFull(CACHEDQUEUE* const me);
int Cachedqueue_isEmpty(CACHEDQUEUE* const me);
int Cachedqueue_getSize(CACHEDQUEUE* const me);
void Cachedqueue_insert(CACHEDQUEUE* const me, int k);
int CachedQueue_remove(CACHEDQUEUE* const me);
void Cachedqueue_flush(CACHEDQUEUE* const me);
void Cachedqueue_load(CACHEDQUEUE* const me);CACHEDQUEUE* CachedQueue_Create(void);
void CachedQueue_Destroy(CACHEDQUEUE* const me);#endif

代码 1-8 cachedqueue.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cachedqueue.h"void CachedQueue_Init(CACHEDQUEUE* const me, char* filename,int (*isFullFunction)(CACHEDQUEUE* const me),int (*isEmptyFunction)(CACHEDQUEUE* const me),int (*getSizeFunction)(CACHEDQUEUE* const me),void (*insertFunction)(CACHEDQUEUE* const me),int (*removeFunction)(CACHEDQUEUE* const me),void (*flushFunction)(CACHEDQUEUE* const me),void (*loadFunction)(CACHEDQUEUE* const me)){me->queue=Queue_Create();me->numberElementsOnDisk=0;strcpy(me->filename,filename);me->outputQueue=Queue_Create();me->isFull=isFullFunction;me->isEmpty=isEmptyFunction;me->getSize=getSizeFunction;me->insert=insertFunction;me->remove=removeFunction;me->flush=flushFunction;me->load=loadFunction;
}void CachedQueue_Cleanup(CACHEDQUEUE* const me){Queue_Cleanup(me->queue);
}int CachedQueue_isFull(CACHEDQUEUE* const me){return me->queue->isFull(me->queue) &&me->outputQueue->isFull(me->outputQueue);
}int CachedQueue_isEmpty(CACHEDQUEUE* const me){return me->queue->isEmpty(me->queue) &&me->outputQueue->isEmpty(me->outputQueue) &&(me->numberElementsOnDisk==0);
}int CachedQueue_getSize(CACHEDQUEUE* const me){return me->queue->getSize(me->queue)+me->outputQueue->getSize(me->outputQueue)+me->numberElementsOnDisk;
}void CachedQueue_insert(CACHEDQUEUE* const me,int k){if (me->queue->isFull(me->queue)){me->flush(me);}me->queue->insert(me->queue,k);
}int CachedQueue_remove(CACHEDQUEUE* const me){if (!me->outputQueue->isEmpty(me->outputQueue)){return me->outputQueue->remove(me->outputQueue);}else if (me->numberElementsOnDisk>0){me->load(me);return me->queue->remove(me->remove);}else{return me->queue->remove(me->remove);}
}void CachedQueue_flush(CACHEDQUEUE* const me){//while not queue->isEmpty()//          queue->remove();//          write date to disk//          numberElementsOnDisk++//end while
}void CachedQueue_load(CACHEDQUEUE* const me){//while (!outputQueue->isFull()&&(numberElementsOnDisk>0))//      read from start of file//      numberElementsOnDisk--;//      outputQueue->insert();//end while
}CACHEDQUEUE* CachedQueue_Create(CACHEDQUEUE* const me){CACHEDQUEUE* me=(CACHEDQUEUE*)malloc(sizeof(CACHEDQUEUE));if(me!=NULL){CachedQueue_Init(me,"C:\\queuebuffer.dat",CachedQueue_isFull,CachedQueue_isEmpty,CachedQueue_getSize,CachedQueue_insert,CachedQueue_remove,CachedQueue_flush,CachedQueue_load);}return me;
}void CachedQueue_Destroy(CACHEDQUEUE* const me){if(me!=NULL){CachedQueue_Cleanup(me);}free(me);
}

1.2.5 有限状态机

有限状态机(Finite State Machine,FSM)

代码 1-9 SecuritySupervisor.c

static eventStatus dispatchEvent(short id){eventStatus res=eventNotConsumed;switch (activeState){case SecuritySupervisor_Idle:{if (id==NULL_id){if(retries>=3){activeState=SecuritySupervisor_ErrorState;displayMSg("ERROR: Max retries Exceeded");res=eventConsumed;}else{++retries;activeState=SecuritySupervisor_Accepting;res=eventConsumed;}}}break;case SecuritySupervisor_Accepting:{if (id==keypress_SequritySupervisor_Event_id){if (isCANCEL(params->keys)){retries=0;displayMSg("Cancelled");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}else{if (isDigit(params->keys)){addKey(params->keys);activeState=SecuritySupervisor_Accepting;res=eventConsumed;}else{if(isEnter(params->keys)){activeState=SecuritySupervisor_CheckingLength;res=eventConsumed;}}}}}break;case SecuritySupervisor_CheckingLength:{if (id==NULL_id){if(strlen(pin)==4){activeState=SecuritySupervisor_ValidatingPIN;res=eventConsumed;}else{displayMSg("ERROR:PIN wrong length");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}}}break;case SecuritySupervisor_ValidatingPIN:{if (id==NULL_id){if (isValid(pin)){unlockDoor();displayMSg("Door unlocked");activeState=SecuritySupervisor_SecurityOpen;res=eventConsumed;}else{displayMSg("ERROR: Invalid PIN");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}}}break;case SecuritySupervisor_SecurityOpen:{if (id==keypress_SequritySupervisor_Event_id){if (isRESET(params->keys)){lockDoor();displayMSg("Door locked");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}}}break;default:break;}return res;
}

1.3 小结

结构化方法将软件组织成两个并行分类,一个是数据,另一个是行为。面向对象的方法将两者结合,当低耦合时,为固有紧密耦合的元素和内容的封装提高内聚力。C不是面向对象语言,可以用于开发基于对象或面向对象的嵌入式系统。

C嵌入式编程设计模式相关推荐

  1. 《C嵌入式编程设计模式》读书笔记

    <C嵌入式编程设计模式> 第一章 什么是嵌入式编程 嵌入式系统的基本知识 面向对象编程与结构化编程 使用C语言实现类.继承.状态机 第二章 嵌入式实时过程Harmony的嵌入式编程 嵌入式 ...

  2. 时间触发嵌入式系统设计模式 读书笔记

    1 下载地址: https://download.csdn.net/download/longzitailang8/10496129 本书前所未有地提出一整套软件模式,为开发嵌入式软件系统提供帮助.书 ...

  3. 做嵌入式编程,为什么用的是C语言而不是C++呢?

    1.前言 几十年来,嵌入式软件工程师们一直在争论是否应该使用C++替代C语言进行开发工作.根据2019年IEEE和github的市场调查显示,微控制器制造商提供的软件大部分都是由C语言编写. 事实上, ...

  4. 嵌入式C设计模式---职责链设计模式

     更新记录链接:嵌入式C设计模式---前言_嵌入式学习_force的博客-CSDN博客_嵌入式前言 目录         1.职责链设计模式动漫详解         2.智慧温室大棚监控系统项目详解职 ...

  5. 嵌入式C设计模式---模板方法设计模式

     更新记录链接:嵌入式C设计模式---前言_嵌入式学习_force的博客-CSDN博客_嵌入式前言 目录         1.模板方法设计模式动漫详解         2.智慧温室大棚监控系统项目详解 ...

  6. 嵌入式C设计模式---工厂设计模式

    更新记录链接:嵌入式C设计模式---前言_嵌入式学习_force的博客-CSDN博客_嵌入式前言 目录         1.工厂设计模式动漫详解         2.智慧温室大棚监控系统项目详解工厂应 ...

  7. 嵌入式C设计模式---状态机设计模式

     更新记录链接:嵌入式C设计模式---前言_嵌入式学习_force的博客-CSDN博客_嵌入式前言 目录         1.状态机设计模式动漫详解         2.智慧温室大棚监控系统项目详解状 ...

  8. 嵌入式编程C语言提高代码效率的14种方法

    嵌入式编程C语言提高代码效率的14种方法 1.在可能的情况下使用typedef替代define.当然有时候你无法避免define,但是typedef更好. typedef int* INT_PTR; ...

  9. 窗体 局部变量转换为全局_从嵌入式编程中感悟「栈」为何方神圣?

    ID:技术让梦想更伟大 作者:李肖遥 何为变量? 变量一般可以细分为如下图: 本节重点为了让大家理解内存模型的"栈",暂时不考虑"静态变量" 的情况,并约定如下 ...

最新文章

  1. BCH压力测试最终统计
  2. linux shell顺序执行,shell 执行顺序
  3. 什么是MIME?什么是MIME邮件?
  4. 一步一步学习iOS 5编程(第三版)-PDF中文版-正式发布!
  5. Mvp快速搭建商城购物车模块
  6. oracle动态性能视图和静态,oracle最重要的9个动态性能视图
  7. 入门科普:一文看懂NLP和中文分词算法(附代码举例)
  8. 前端发送http的get请求 - 代码篇
  9. MFC开发IM-第二十篇、MFC添加自定义消息
  10. android判断是否登陆过_如何判断车辆是否受到过碰撞?_搜狐汽车
  11. Flink1.6系列之—数据流编程模型
  12. java中判斷主鍵重複
  13. l298n电机哪一端为正_L298N控制直流电机正反转
  14. 多多进鱼带VUE源码-任务悬赏网站源码-活动营销三级分销返佣积分商城版
  15. 计算机程序设计c++ 9-7:类的抽象描述举例-汽车类及圆类设计
  16. 目前住院病人需要护士护理,这样做不仅需要大量护士,而且由于不能随时观察病人情况,还可能会延误抢救时即。某医院呢打算开发一个以计算机为中心的患者监护系统,试写出问题定义,并分析开发这个系统的可行性
  17. 9个可视化图表在线制作工具,总有一款适合你
  18. openlayers摸爬滚打 5.openlayers使用GeoJSON绘制点、线
  19. html制作小短片,如何制作视频短片
  20. 高斯混合模型下的变分推断

热门文章

  1. 影视后期制作学习(AE)(父子级链接-表达式)
  2. [ 网络协议篇 ] IGP 详解之 OSPF 详解(二)--- 四种网络类型 虚链路 详解
  3. matlab热应力计算,不同温度下热应力的计算 - 仿真模拟 - 小木虫 - 学术 科研 互动社区...
  4. MDS(多维尺度变换)降维算法
  5. 山庄老酒唐山大区举办“喜迎八一”主题书画笔会活动
  6. Laravel项目+Google验证器
  7. python调用R语言
  8. ClientDisconnectionReason(客户端断开原因)_羊豆豆_新浪博客
  9. Gym - 100889H Hitting Points 计算几何+三分+二分
  10. 洛谷P4643 [国家集训队]阿狸和桃子的游戏