范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

嵌入式软件开发常用的三种架构你知道吗?

  摘要  :对于单片机程序来说,大家都不陌生,但是真正使用架构,考虑架构的恐怕并不多,随着程序开发的不断增多,架构是非常必要的。
  应用程序的架构大致有三种:
  1、 简单的前后台顺序执行程序  ,这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接通过执行顺序编写应用程序即可。
  2、 时间片轮询法  ,此方法是介于顺序执行与操作系统之间的一种方法。
  3、 操作系统  ,此法应该是应用程序编写的最高境界。 一、程序框架设计
  1、前后台顺序执行法
  这是初学者们常用的程序框架设计方案,不用考虑太多东西,代码简单,或者对系统的整体实时性和并发性要求不高;初始化后通过while(1){}   或for(;;)   {}`循环不断调用自己编写完成的函数,也基本不考虑每个函数执行所需要的时间,大部分情况下函数中或多或少都存在毫秒级别的延时等待。优点  :对于初学者来说,这是最容易也是最直观的程序架构,逻辑简单明了,适用于逻辑简单,复杂度比较低的软件开发。 缺点  :实时性低,由于每个函数或多或少存在毫秒级别的延时,即使是1ms,也会造成其他函数间隔执行时间的不同,虽然可通过定时器中断的方式,但是前提是中断执行函数花的时间必须短。当程序逻辑复杂度提升时,会导致后来维护人员的大脑混乱,很难理清楚该程序的运行状态。
  以下是在校期间做的寝室防盗系统的部分代码(当时也存在部分BUG,没有解决。现在再看,其实很多问题,而且比较严重,比如中断服务函数内竟然有3000ms延时,这太可怕了,还有串口发送等等;由于实时性要求不算太高,因此主函数中的毫秒级别延时对系统运行没有多大影响,当然除BUG外;若是后期需要维护,那就是一个大工程,还不如推翻重写 ):int main(void){    u8 temperature;          u8 humidity;     int a;  delay_init();  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   I2c_init();   uart2_Init(9600);  uart_init(9600);//串口初始化为115200    TIM3_Int_Init(4999,7199);  ds1302_init();  while(DHT11_Init())//DHT11初始化   {   led2=0;  }  a1602_init();     Ds1302Init();  EXTIX_Init();     GPIOX_Init();  lcd12864_INIT();  LcdInit();  beep_init();  RED_Init();  led1=1;  beep=0;  while(1)  {   for(a=0;a<11;a++)   {    num[a+3]=At24c02Read(a+2)-208;    delay_us(10);        }   for(a=0;a<6;a++)   {    shuru[a]=At24c02Read(a+13)-208;    delay_us(10);       }     delay_ms(10);     RED_Scan();   Ds1302ReadTime();  //读取ds1302的日期时间   shi=At24c02Read(0); //读取闹钟保存的数据   delay_ms(10);   fen=At24c02Read(1); //读取闹钟保存的数据      usart2_scan();   //蓝牙数据扫描   usart2_bian();   //蓝牙处理数据   usart2_gai();   nao_scan();   k++;   if(k<20)   {    if(k==1)     LcdWriteCom(0x01);//清屏     LcdDisplay();     //显示日期时间    }   if(RED==0)      RED_Scan();       if(k>=20&&k<30)   {    if(k==20)     LcdWriteCom(0x01); //清屏    Lcddisplay(); //显示温湿度    LcdWriteCom(0x80+6);     DHT11_Read_Data(&temperature,&humidity); //读取温湿度值    Temp=temperature;Humi=humidity;    LcdWriteData("0"+temperature/10);    LcdWriteData("0"+temperature%10);    LcdWriteCom(0x80+0X40+6);     LcdWriteData("0"+humidity/10);    LcdWriteData("0"+humidity%10);   }   if(k==30)    k=0;   lcd12864(); //显示防盗闹钟状态   }   }   //定时器3中断服务程序 void TIM3_IRQHandler(void)//TIM3中断{  int i;  if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否  {   TIM_ClearITPendingBit(TIM3, TIM_IT_Update);//清除TIMx更新中断标志    if(key1==1&&FEN-fen==0&&SHI-shi==0)//时间一到闹钟响起   {     f=1;         }   if(key1==0||FEN-fen!=0||SHI-shi!=0)   else   {     f=0;   }     if(USART_RX_BUF[0]=="R"&&USART_RX_BUF[1]=="I"&&USART_RX_BUF[2]=="N"&&USART_RX_BUF[3]=="G")   {    key0=1;    for(i=0;i<17;i++)    {     USART_SendData(USART1, num[i]);//向串口1发送数据     while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束     USART_RX_STA=0;     }     delay_ms(3000);    for(i=0;i<3;i++)    {     USART_SendData(USART1, num1[i]);//向串口1发送数据     while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束     USART_RX_STA=0;     }      }  } }2、时间片论法
  介于前后台顺序执行法 和操作系统 之间的一种程序架构设计方案。该设计方案需能帮助嵌入式软件开发者更上一层楼,在嵌入式软件开发过程中,若遇到以下几点,那么该设计方案可以说是最优选择,适用于程序较复杂的嵌入式系统;目前的需求设计需要完全没有必要上操作系统。 任务函数无需时刻执行,存在间隔时间(比如按键,一般情况下,都需要软件防抖,初学者的做法通常是延时10ms左右再去判断,但10ms极大浪费了CPU的资源,在这段时间内CPU完全可以处理很多其他事情) 实时性有一定的要求。
  该设计方案需要使用一个定时器,一般情况下定时1ms即可(定时时间可随意定,但中断过于频繁效率就低,中断太长,实时性差),因此需要考虑到每个任务函数的执行时间,建议不能超过1ms(能通过程序优化缩短执行时间则最好优化,如果不能优化的,则必须保证该任务的执行周期必须远大于任务所执行的耗时时间),同时要求主循环或任务函数中不能存在毫秒级别的延时。"
  如何确定每个函数的任务周期呢?根据任务的耗时和效果决定、如按键扫描任务周期为 10ms(为了提高响应),指示灯控制任务周期为 100ms(通常情况下最高100ms的闪烁频率正好,特殊需求除外),LCD/OLED 显示周期为 100ms(通过这种通过SPI/IIC等接口的方式耗时大约在 1~10ms,甚至更长,所以任务周期必须远大于耗时,同时为了满足人眼所能接受的刷屏效果,也不能太长,100ms 的任务周期比较合适)等。
  "
  以下介绍两种不同的实现方案,分别针对无函数指针概念的朋友和想进一步学习的朋友。
  1、无函数指针的设计方式 /**   * @brief      主函数.   * @param      None.   * @return     None.   */  int main(void){     System_Init();          while (1)     {         if (TIM_1msFlag)// 1ms         {             CAN_CommTask(); // CAN发送/接收通信任务                          TIM_1msFlag = 0;         }                 if (TIM_10msFlag)  // 10ms         {             KEY_ScanTask(); // 按键扫描处理任务                          TIM_10msFlag = 0;         }                 if (TIM_20msFlag) // 20ms         {             LOGIC_HandleTask();// 逻辑处理任务               TIM_20msFlag = 0;         }                 if (TIM_100msFlag) // 100ms         {              LED_CtrlTask(); // 指示灯控制任务                          TIM_100msFlag = 0;         }                if (TIM_500msFlag)// 500ms         {             TIM_500msFlag = 0;         }                 if (TIM_1secFlag) // 1s         {             WDog_Task(); // 喂狗任务                         TIM_1secFlag = 0;         }       } }   /**   * @brief      定时器3中断服务函数.   * @param      None.   * @return     None.   */ void TIM3_IRQHandler(void){     if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET) //溢出中断     {         sg_1msTic++;                 sg_1msTic % 1 == 0 ? TIM_1msFlag = 1 : 0;                 sg_1msTic % 10 == 0 ? TIM_10msFlag = 1 : 0;                 sg_1msTic % 20 == 0 ? TIM_20msFlag = 1 : 0;                 sg_1msTic % 100 == 0 ? TIM_100msFlag = 1 : 0;                sg_1msTic % 500 == 0 ? TIM_500msFlag = 1 : 0;                sg_1msTic % 1000 == 0 ? (TIM_1secFlag  = 1, sg_1msTic = 0) : 0;     }         TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  // 清除中断标志位 }
  2、含函数指针的设计方式 /**   * @brief 任务函数相关信息结构体定义.   */ typedef struct{     uint8 m_runFlag;                 /*!< 程序运行标记:0-不运行,1运行 */     uint16 m_timer;                  /*!< 计时器 */     uint16 m_itvTime;                /*!< 任务运行间隔时间 */     void (*m_pTaskHook)(void);       /*!< 要运行的任务函数 */ } TASK_InfoType;    #define TASKS_MAX     5              // 定义任务数目   /** 任务函数相关信息 */ static TASK_InfoType sg_tTaskInfo[TASKS_MAX] = {     {0, 1, 1, CAN_CommTask},         // CAN通信任务     {0, 10, 10, KEY_ScanTask},       // 按键扫描任务     {0, 20, 20, LOGIC_HandleTask},   // 逻辑处理任务     {0, 100, 100, LED_CtrlTask},     // 指示灯控制任务     {0, 1000, 1000, WDog_Task},      // 喂狗任务 };     /**   * @brief      任务函数运行标志处理.   * @note       该函数由1ms定时器中断调用   * @param      None.   * @return     None.   */ void TASK_Remarks(void){     uint8 i;      for (i = 0; i < TASKS_MAX; i++)     {         if (sg_tTaskInfo[i].m_timer)         {             sg_tTaskInfo[i].m_timer--;              if (0 == sg_tTaskInfo[i].m_timer)             {                  sg_tTaskInfo[i].m_timer = sg_tTaskInfo[i].m_itvTime;                  sg_tTaskInfo[i].m_runFlag = 1;             }         }    } }   /**   * @brief      任务函数运行处理.   * @note       该函数由主循环调用   * @param      None.   * @return     None.   */ void TASK_Process(void){     uint8 i;      for (i = 0; i < TASKS_MAX; i++)     {         if (sg_tTaskInfo[i].m_runFlag)         {              sg_tTaskInfo[i].m_pTaskHook();         // 运行任务              sg_tTaskInfo[i].m_runFlag = 0;         // 标志清0         }     }    }   /**   * @brief      主函数.   * @param      None.   * @return     None.   */ int main(void){     System_Init();         while (1)     {         TASK_Process();     } }   /**   * @brief      定时器3中断服务函数.   * @param      None.   * @return     None.   */ void TIM3_IRQHandler(void){     if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET) //溢出中断     {         TASK_Remarks();     }         TIM_ClearITPendingBit(TIM3,TIM_IT_Update);// 清除中断标志位 }三、操作系统
  嵌入式操作系统EOS(Embedded OperatingSystem   )是一种用途广泛的系统软件,过去它主要应用于工业控制和国防系统领域,而对于单片机来说,比较常用的有UCOS、FreeRTOS、RT-Thread    Nano和RTX 等多种抢占式操作系统(其他如Linux等操作系统不适用于单片机)
  操作系统和"时间片论法   ",在任务执行方面来说,操作系统对每个任务的耗时没有过多的要求,需要通过设置每个任务的优先级,在高优先级的任务就绪时,会抢占低优先级的任务;操作系统相对复杂,因此这里没有详细介绍了。
  关于如何选择合适的操作系统(uCOS   、FreeRTOS   、RTThread   、RTX   等RTOS的对比之特点:uCOS:网上资料丰富,非常适合学习,但是在产品上使用则需要收费。 FreeRTOS:使用免费,因此很多产品都在用。 RT-Thread:国产物联网操作系统,有着十分丰富的组件,也免费,资料:RT-Thread文档中心。 RTX:为ARM和Cortex-M设备设计的免版税,确定性的实时操作系统。
  借网上一张对比图:
  四、总结
  从上述的对比中可以看出,时间片轮询法的优势还是比较大的,它既有前后台顺序执行法的优点,也有操作系统的优点。结构清晰,简单,非常容易理解,所以这种是比较常用的单片机设计框架。

微信里面的零钱通安全吗?风险大不大?微信零钱通是微信的一款零钱理财服务,具有支付和理财两个功能,类似于支付宝的余额宝。零钱通对接的是货币基金,安全性主要在支付和理财两个层面,那么,零钱通的安全性怎么样呢?我们一起来看中国移动,下了步好棋有的时候我会感叹,在当下智慧创新的无穷领域中,在有着万物互联的无穷未来,中国移动无处不在,不仅在国内,中国移动交出了一份满意的答卷,在国外甚至是好多我们想不到的地方,中国移动以基础中国激光晶体垄断全球!美国上门恳求合作被拒,如今又有了新突破美国作为第一大科技强国,掌握着很多重要的技术,也垄断了许多产业,有绝对话语权。近年来,中国飞速发展,美国怕影响到它的地位,在各方面都对中国进行打压与技术封锁。美国综合国力确实很强大数字人民币内测体验,能替代微信支付宝吗?今年初收到了交行的一条短信,说有数字人民币的红包可以抢,当时随手申请了一下试用体验就抛到了脑后。最近看到关于数字人民币的讨论越来越火热,前不久支付宝也接入了数字人民币,让我感受到了为什么在日本是实体店干掉电商,在中国却是电商干掉实体?之所以会出现这种现象,原因大概有一下几点吧1在我国电商起步的时候,平台因为有资本操作,基本上是赔本引流,再加上征税不规范,电商的成本比实体店要低很多。而在日本,是不一样的,他们的税OPPOReno6三款配色全公开,周冬雨代言IT之家5月20日消息OPPOReno6系列将于5月27日18点发布,搭载6400万像素主摄,支持65W闪充。此前官方已公布了该机的夏日晴海配色。刚刚,OPPO放出了系列3款配色的全球首款折叠平板电脑,三星Zfold来了,十分惊艳在三星的折叠机艰难的开始后,三星近年来折叠机已经发展得非常不错,三星GalaxyZFold2和GalaxyZFlip的市场反响都非常不错,接下来三星的全球首款折叠平板电脑即将发布。比亚迪一季度净利润翻倍新能源车销量增150位列中国市场Top3据韩国Newsis新闻网近日报道,中国大型电动汽车厂商比亚迪今年第1季度净利润同比增长110。73,达到2。37亿元人民币。报道介绍,2021年第1季度,比亚迪新能源车和燃油车的新鸿蒙到底是不是安卓换壳?2017年,华为手机靠着1。53亿台的销量和20。4的市场占有率,稳坐中国手机市场老大的位置。当大家都在庆祝这个里程碑时刻时,2018年初,华为消费者业务软件部门的负责人王成录却向为什么微信朋友圈这个功能删不掉?微信朋友圈你是删不掉的。这是你加进来的朋友的共同交流圈。如果你由于某种原因不想看某人或几位的内容,可屏蔽其朋友圈,你就看不到其内容。或者自己不玩微信,直接把自己退出来,你就看不到朋买手机该选择Redminote9pro还是RedmiK40?买手机该选择红米Note9Pro,还是红米K40,价格只差400元,怎么选?首先可以确认的是,能买红米K40,就不要考虑红米Note9Pro,下面给大家介绍下两款手机的配置。1。红
谜一样的中本聪究竟是谁?持有一百万枚比特币却人间蒸发文章每日更新,每天和大家分享我的思考,说不上有用,但希望能帮助到大家!多数人看问题用眼睛,但我希望你是那用脑的极少数。我是芮芮小魔王,欢迎大家来到我的小世界!废话不多说,正文开始前苹果iphonexsmax换大容量电池教程xsmax这款18年的旗舰机已经过3年时间但热度还是不减它的A12芯片目前除了打不过(哥哥)A13(爸爸)A14没有其他对手在与iphone11差不多价位的情况下玩大型游戏依然顺畅一分钟资讯鸿蒙AirPodsiPhone13OPPO柔性屏,最新消息哈喽,我是毛小毛。每日带你了解最新数码资讯!一分钟资讯第31期,感谢你的阅读。最新全球智能手表市场TOP5市调机构Counterpoint近日发布了一份2021年第一季度(13月)正式入场618,抖音布局电商的第一场大战即将到来的618电商混战又迎来了一名新入局者。近日,抖音电商宣布推出抖音618好物节,正式加入618大促。大促期间,抖音将推出上万场直播,并且投入千万元货品补贴。抖音在电商方面的布聚焦鸿蒙原创沧海一粟趋势逻辑学华为鸿蒙来了华为将于6月2日举办鸿蒙OS的新品发布会,而且这次鸿蒙OS的发布会不同于之前的开发者测试版,这次绝大部分都可以更新升级,这意味着鸿蒙系统正式版本终华为HiLink版新日电动车上市在即,你定了吗?作为民生产业的电动车制造,也在二十余年间完成了从手工组装到自动化生产的高速发展,也让中国成为了世界电动车王国。新日领军行业二十余年,在一次次的产业变革中担当着先行者的重担,为中国电IP代理更改IP地址能在互联网起到哪些作用?如今网络快速的发展和普及使得人们方方面面都离不开它的存在,通过网络进行办公学习休闲娱乐等操作早已成为常态,每天都在和它打交道但是要实现网络的互联互通就少不了IP的支持,它是每个联网我利用知识付费月入十万,是因为做对了这3点,推荐学习去年十月开始搭建自己的知识付费平台,经过半年的努力从刚开始每天几十元地做到了五月份月入十万。今天我们算笔帐和大家算一算做到月入十万需要卖多少课程?需要做哪些工作才可以实现这个收入?上市2个月跌价500元,12GB内存哈苏认证ColorOS,胡歌代言这次618购物节非常的火热,特别是手机行业,可谓是火药味十足,小米OPPO和vivo等手机厂商打得不亦乐乎,特别是子品牌的竞争更加激烈,很多新机刚上市不久,就面临大幅度跌价,这对于高通5G芯片骁龙778G号称888青春版?旗舰气质,首发合作荣耀这几天,高通5G芯片骁龙778G的发布,引发了不少网友的关注。作为高通和荣耀首次合作的鹊桥,也是荣耀重新披挂上阵以后首款机型选择的芯片,高通骁龙778G必然有其与众不同的魅力。其实宏光MINIEV我气囊是少没错,但别质疑我的安全性相信提起宏光MINIEV这款车,国内消费者是再熟悉不过了,这款黑马神车自上市以后便迅速霸榜新能源市场。根据销量来看,宏光MINIEV在今年4月售出26592台,14月累计销量为99