【原创】【单片机到嵌入式之路】序列之三:苦逼的CPU

  • 冰山一角
  • LV5工程师
  • |      2014-01-09 11:02:35
  • 浏览量 10060
  • 回复:68

软件平台
硬件平台:单片机
编译环境:keil

二、苦逼的CPU

【事故起因】:单片机是单核的,所以在做多线程问题的时候,我们要考虑的太多。但是大部分人都会让单片机一直工作,比如while死循环,然后就抱怨单片机太简单了,只能点灯,其它的事情就不行了。

【现场分析】:1.单片机是单核的;

                          2.做多线程,方法两种:a.上操作系统,b.仿操作系统;

       3.自己想释放单片机的CPU,但是格局有限,就怪单片机;

      4.要想马儿跑,必须给马儿吃草。要想单片机多工作,必须优化代码,多下功夫。

【案例列举】:单灯闪烁

void main(void)

{

LED_Init();  //LED初始化

while(1)

{

LED = ON;      //LED亮

Delay_Ms(1000); //延时1s

LED = OFF;    //LED灭

Delay_Ms(1000); //延时1s

}

}

【案例分析】:单灯闪烁分析

声明几点:1.如果你只用单片机作为单灯闪烁,那么单片机就完全可以;

              2.如果你不想玩那么高级,那么单机这样也是OK的;

  3.如果你想玩高级的,那么肯定不行。

  分析:咋一看,程序没有什么问题,但是暗藏玄机。

1.程序被死循环卡死;

2.死循环里面就是一个产生2s周期的频率,那么灯就是2s闪烁一次; 

3.单片机就这样被你“征服”了。但是你这是把单片机浪费了。

这是单片机CPU的苦啊,他是没有口啊,有口要骂人的哦!O(∩_∩)O哈哈~




三、单片机CPU的苦衷——请释放CPU

1.硬件电路分析


用上面的电路来做分析,当P1口为低电平的时候,LED灯才亮,高电平则灭。

1.软件分析

由硬件可以知道,我们可以通过宏定义来对接口进行简单的定义

#define  LED_Light  P1                 //LED灯端口

#define  LED_ON()  LED_Light = 0x00   //LED灯亮

#define  LED_OFF()  LED_Light = 0xFF   //LED灯灭

现在端口也定义好了,下面单片机要哭诉了。

3.你误解了单片机

单片机其实可以干很多活,结果你误解了。

为了让单片机不白忙活我们可以通过两种方式来实现LED灯闪烁:a.定时器中断,b.计时+标志位。

A.定时器中断

定时器中断大家都知道,这里就不说了,就是产生xms的中断就可以了。

B.计时+标志位

计时+标志位太有用了,这一下帮单片机洗清沉冤了。我们只要产生一个对200ms的时间,然后对该时间进行计数到了5次,然后就清0该计数值,同时反转LED灯的状态即可。

代码部分:

unsigned int      LedTimeCount  =  0 ; //LED计数器
unsigned char  LedStatus = 0 ;    //LED状态标志, 0表示亮,1表示熄灭

/***************************************

* 函数描述:LED灯线程处理函数

* 输入参数:No

* 返 回 值:No

* 说    明:通过标志位来实现LED的反转

* 修改记录: 

****************************************/  
void LEDThread_Process(void)
{
  if(0  ==  LedStatus) //如果LED的状态为0,则点亮LED
  {
  LED_ON() ; //点亮LED
 }
  else    //否则熄灭LED
  {
  LED_OFF() ;
  }
}
/***************************************

* 函数描述:计时和标志位函数

* 输入参数:No

* 返 回 值:No

* 说    明:状态标志位改变

* 修改记录: 

****************************************/  
void LEDStatus_Change(void)
{
  if(Sys_200MS)  //系统200ms时标到
  {
  Sys_200MS =  0 ;
  LedTimeCount ++ ; //LED计数器加1
  if(LedTimeCount >= 5) //计数达到5,即1s到了,改变LED的状态。
  {
  LedTimeCount =  0 ;
  LedStatus = ! LedStatus;
  }
  }
}
/***************************************

* 函数描述:主函数

* 输入参数:No

* 返 回 值:No

* 说    明:

* 修改记录: 

****************************************/  
void main(void)
{
  while(1)
  {
  LEDThread_Process() ;
LEDStatus_Change() ;
  } 
}
通过上面的程序就可以释放单片机的CPU。因为LED灯亮灭是有标志位(LedStatus)来决定,而标志位由计数器(LedTimeCount)来决定,两个函数都没有绑架单片机的CPU,所以单片机的CPU是自由的。终于洗冤了。O(∩_∩)O哈哈~

到此结束!!! 谢谢阅读,欢迎拍砖!!!!




  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:62
电子大拿 2016-12-06
默默地给楼主点个赞
0   回复
举报
发布
2016大圣 2016-06-22
跟楼主学了一手。
0   回复
举报
发布
yhxc8979797 2016-06-20
学习一下,谢谢分享。。。
0   回复
举报
发布
冰山一角 2015-07-06
0   回复
举报
发布
冰山一角 2014-11-15
0   回复
举报
发布
冰山一角 2014-07-21
0   回复
举报
发布
空中翱翔的老虎 2014-06-19
顶 冰哥
0   回复
举报
发布
冰山一角 2014-06-11
 谢谢  顶起
0   回复
举报
发布
小宝 2014-06-10
谢谢冰哥分享。。。
0   回复
举报
发布
冰山一角 2014-05-28
0   回复
举报
发布
查看更多
x
收藏成功!点击 我的收藏 查看收藏的全部帖子