OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9808|回复: 37

关于单片机的一种框架!!!个人观点,欢迎拍砖!!!

[复制链接]

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
发表于 2013-10-4 14:41:59 | 显示全部楼层 |阅读模式

工作也已经三个多月了,谈点自己个人的观点吧,欢迎大家讨论!如有误人子弟的地方,欢迎指正!我平时不太善于写文字,所以文笔不好的话勿见怪,想加我好友聊天的话,我的QQ610967340!好了,废话不多说了,开始讲正题吧!

 

一、关于单片机分时


在大学,我们学习单片机程序,都是只有涉及到定时或需要精确计时的时候我们才会使用定时器,而其他情况下我们一般不用!例如我们学习流水灯,学习按键的时候都没有用定时器。按键所需要的消抖时间也是通过一个死循环(通过for语句或while语句实现的软件延时程序)来实现。其实CPU是很宝贵的,它在不断的执行我们所需要的功能,如果让它在那里等待,执行死循环,是在浪费它的资源。因为它执行死循环的时候,是不能干其他的事的,只有当死循环退出的时候,才能执行其他的功能。所以,我们应该让CPU分时的执行我们的功能,也就是说,当哪个功能发生的时候,我们才去执行它,否则不执行。其实操作系统的分时,也是利用定时器产生一个时间,然后所有的计时都是通过那个时间来实现。而定时器定时是在中断里实现的。所以,它不会浪费资源,只有当定时时间到了,才去执行我们需要的功能,定时时间没有到,就不执行。

下面我就讲讲如何用单片机的定时器来实现一个简易的分时机制,从而使各个功能函数有条不紊的执行。方法如下:


首先在一个C文件里定义如下变量


bit fTimer0_10ms = 0;//10ms计时到标志位
bit fTimer0_100ms= 0;//100ms计时到标志位
bit fTimer0_500ms = 0;//500ms计时到标志位
bit fTimer0_1min = 0;//1min计时到标志位

uchar dTimer0_100ms = 0;//100ms计时变量
uchar dTimer0_500ms = 0;//500ms计时变量
uchar dTimer0_1min = 0;//1min计时变量

/**********************************************************************
***************程序主循环**********************************************
**********************************************************************/
void main(void)
{
    MPort_Init();//IO端口初始化函数
    MTimer_Init();//定时器初始化函数
/************************************************************************************
****
************************************************************************************/
 while(1){
     if(fTimer0_10ms){  
   //--------------------------------------10ms程序区
      fTimer0_10ms = 0;  
        //下面可以放一些优先级比较高的函数,例如按键扫描函数,按键功能函数等
        MKey_Scan();//按键扫描函数,所有用到的按键都在这里扫描出来
        MKey1_Function();//下面是每个按键的功能函数,这里为了方面说明,用按键1表示,下面可以写按键2......
    }
    if(fTimer0_100ms){
     //--------------------------------------100ms程序区
      fTimer0_100ms = 0;
        //这里可以放一些需要100ms执行一次的函数,或者是声明一个全局变量,然后让它自加,从而可以放入一些需要1s执行一次的函数,例如i++;if(i == 10){//放入需要执行的函数},这样就可以实现一个功能,这个功能是1s执行一次的,没有到1秒是不会执行该功能的。通过这样的方法,我们可以实现任何我们想要的功能,只要我们设置一个时间变量,让它自加,然后放入10ms,100ms,500ms,1min四个中的一个,就可以了。再举个例子,比如我们要实现一个10min钟自动关机的功能MPower_OFF(),我们可以定义一个变量j,让它自加,if(j++ == 10){MPower_OFF();},我们把if(j++ == 10){MPower_OFF();}放到1min计时到标志下就可以了。不知道讲明白没有,其他的也一样。通过这种方法后,我们可以实现一个简易分时,从而不需要用死循环,包括按键扫描也不需要死循环,从而不浪费CPU资源。这种框架下的按键扫描程序在第二点会讲到。
    }

     if(fTimer0_500ms){
     //--------------------------------------500ms程序区
      fTimer0_500ms = 0;
      MStandby_Off();
      MPowerLow();
     }
  if(fTimer0_1min){
  //--------------------------------------1min程序区
   fTimer0_1min = 0;
  }
  }
}

void timer() interrupt 1
{
 TH0=(65536-10000)/256;
 TL0=(65536-10000)%256;
 fTimer0_10ms = 1;
 dTimer0_100ms++;
 if(dTimer0_100ms == 10){
  dTimer0_100ms = 0;
  fTimer0_100ms = 1;
  dTimer0_500ms++;
  if(dTimer0_500ms == 5){
   dTimer0_500ms = 0;
   fTimer0_500ms = 1;
   dTimer0_1min++;
   if(dTimer0_1min == 120){
    dTimer0_1min = 0;
    fTimer0_1min = 1;
   }
  }
 }
}
这里我只是在讲一个框架,所以大家不用去深究具体函数的功能,我也没有把具体函数的代码贴出来。这就是我要讲的单片机简单分时,有了这四个分时标志的话,需要延时的地方我们就不用去
delay了,比如按键扫描,写好了直接放到10ms程序区就可以了,而不用去delay,一到10ms产生一次中断,扫描一次按键,而不用像delay一样在那里死等,浪费CPU。
还有比如我们有一个一个小时才发生的任务,我们不可能去delay,这是我们可以声明一个变量,然后让他自加到60,如果到了60,再执行需要的任务,然后放到1min程序区就可以了。
至于其他的任务,也是那样用,比较紧急的任务,放10ms程序区,其他的根据任务根据自己的时间变量放到相应的程序区。不知道讲的明不明白,不明白的欢迎提问。

二、按键


在大学里面学习按键扫描,买的开发板,不用说,学习按键几乎都是一个模式。if判断IO端口电平,再delay。熟不知,用delay是非常浪费单片机CPU的资源的,因为delay是死循环,单片机一直在那里死等,不能干别的事情!所以我觉得这种方法不是一种好的按键扫描方法。下面就讲一下自己在工作中用的一种方法吧!
#define cKey_Connect_NUM    0x0f
#define Power_FUN_NUM      0x01//开机键
#define AddSub_FUN_NUM   0x02//加挡键
#define Touch_FUN_NUM   0x04//触摸键
#define DcOk_FUN_NUM        0x08//充电完成检测口

uchar dKey_Filter = 0;//滤波
uchar dKey_NUM = 0;//键值传递
uchar dKey_Process = 0;//按键处理标志

uchar dKey_TimerH = 0;
uchar dKey_TimerL = 0;
uchar dKey_L_flag = 0;//按键长按标志

/*********************************************************************************
** 1.函数名称: MKey_Scan(void).
** 功能描述: 按键扫描函数.
** 输入参数: None.        
** 输出参数: None.
** 返回参数: None.
**********************************************************************************/
void MKey_Scan(void)
{
 uchar gLocal_L;
 if(FP11 == 1) gLocal_L |= 0X01;//开机没按下
 else gLocal_L &= 0xFE;开机按下
 if(FP20 == 1) gLocal_L |= 0X02;//加挡
 else gLocal_L &= 0xFD;
 if(FP24==0) gLocal_L |= 0X04;//触摸
 else gLocal_L &= 0xFB;
 if(FP50==1) gLocal_L |= 0X08;//充电完成检测口
 else gLocal_L &= 0xF7;
 if((gLocal_L&cKey_Connect_NUM) != cKey_Connect_NUM)
 {   //有键按下
  ++dKey_Filter;
  if(dKey_Filter > 3)
  {  //滤波
   dKey_Filter = 0;
   dKey_NUM = gLocal_L&cKey_Connect_NUM;
   gLocal_L = dKey_NUM ^ dKey_Process;
   dKey_Process &= gLocal_L;    
  } 
 }
 else
 {
  dKey_Process = 0;
  dKey_Filter = 0;
  dKey_NUM = cKey_Connect_NUM; 
  dKey_TimerH = 0;
  dKey_TimerL = 0;
 }
}


 

/*********************************************************************************
** 4.函数名称: MKeyAddSub_Function(void)
** 功能描述: 红光LED和马达档位切换功能函数.
** 输入参数: None.        
** 输出参数: None.
** 返回参数: None.
**********************************************************************************/
void MKeyAddSub_Function(void){
 if((dKey_NUM &AddSub_FUN_NUM) == 0)
 {
  if((dKey_Process &AddSub_FUN_NUM) == 0)
  {
   dKey_Process |= AddSub_FUN_NUM;
    //这个函数中,前面语句都是确认该按键已经按下,执行到这里说明按下了,一下语句就是

    //该函数要处理一些什么东西了,每个按键都是这种模式,具体里面代码大家不用去深究,只要知道这个框架,以后可以根据自己需要在里面添加代码
   if(fPowerOn_flag) //开机状态下
   {
    dSYS_PowerOFF_Tmr = 0; //清定时1分钟关机变量
    if(dKeyPowerOnCount == 1)
    {
     if(++dRedLed_Gear > 3) dRedLed_Gear = 0;
     AT24CXX_WriteOneByte(0,dRedLed_Gear);
     if(fTouchKey_flag == 1){
      if(fExitDCPower_flag == 0)MPwm1_Out(pwmtable[dRedLed_Gear]);
      else MPwm1_Out(TAB_EXPower_Led[dRedLed_Gear]); 
     }
     MRed_Speed(dRedLed_Gear+1); 
    }
    if(dKeyPowerOnCount == 2)
    {      
     if(++dMotor_Gear > 3) dMotor_Gear = 0;
     AT24CXX_WriteOneByte(1,dMotor_Gear);
     MMotor_Speed(dMotor_Gear+1);
    }
   }
  }
 }
}
/*********************************************************************************
** 5.函数名称: MTouch_Function(void)
** 功能描述: 触摸按键处理函数.
** 输入参数: None.        
** 输出参数: None.
** 返回参数: None.
**********************************************************************************/
void MTouch_Function(void)
{
 if((dKey_NUM &Touch_FUN_NUM) == 0)//按键发生处理部分
 {
  if((dKey_Process &Touch_FUN_NUM) == 0)
  {
   dKey_Process |= Touch_FUN_NUM;
   if(fPowerOn_flag){
    fTouchKey_flag = 1; 
    dSYS_PowerOFF_Tmr = 0; //清定时1分钟关机变量
    _Standby = 0;
    _BackLightLed = 0; //关背光
    FTC1ENB = 1;
    FPWM1OUT = 1; 
    if(dKeyPowerOnCount == 1){
     if(fExitDCPower_flag == 0)MPwm1_Out(pwmtable[dRedLed_Gear]);
     else MPwm1_Out(TAB_EXPower_Led[dRedLed_Gear]);
    }
    else if(dKeyPowerOnCount == 2){ //固定红光为0挡 250mA
     if(fExitDCPower_flag == 0)MPwm1_Out(pwmtable[0]);
     else MPwm1_Out(TAB_EXPower_Led[0]);    
    }   
    dMotor_PWM_TMR = 0; //马达停止
   }
  }
 }
 else//按键没有发生处理部分
 {
  if(fTouchKey_flag == 1){
   fTouchKey_flag = 0; 
   FPWM1OUT = 0; 
   FTC1ENB = 0;
   _BackLightLed = 1; //开背光
   dMotor_PWM_TMR = 0; //马达停止
   _Standby = 1;
  }  
 }
}

然后在第一部分讲的分时里面,把这三个函数放到10ms程序区,这样就可以中断扫描外部按键的按下与否了!而不用delay了。

这里变量gLocal_L是用来记录哪个按键按下的变量。这种按键扫描的方法还有个好处就是,你按下一个按键的同时,不会妨碍另外的按键正常工作,不像你delay的,你一直按着

一个按键不松开,再去按其他的按键,没有用!讲的比较乱,不知道大家懂了多少,不懂的可以提问!

还在这里提点,大家养成好的习惯,形成自己的代码风格。我写的也不咋滴,但是我在努力改进!例如:一般一个函数不要超过一屏,一个C文件配合一个.H文件等,这个自己根据个人喜好!

好了,今天就讲到这里吧,讲的比较乱,希望大家不要嫌弃!从现在开始,抛弃delay吧!只有像I2C那种很少的微秒级延时才去用delay,其他情况尽量不用!



 

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

123

帖子

0

精华

初级会员

Rank: 2

积分
197
金钱
197
注册时间
2013-8-3
在线时间
0 小时
发表于 2013-10-4 15:56:48 | 显示全部楼层
楼主能留个邮箱吗?我现在是在校大学生,刚大二。一直在自学单片机,感觉学到一定程度后,就很难有突破了,而且还从来没做过具体的项目。想向你学习一下,不知楼主是否愿意共同探讨。
回复 支持 反对

使用道具 举报

53

主题

608

帖子

0

精华

高级会员

Rank: 4

积分
890
金钱
890
注册时间
2013-3-29
在线时间
18 小时
发表于 2013-10-4 18:54:57 | 显示全部楼层
回复【楼主位】liuyongliuyong:
---------------------------------
楼主想表达什么没看出来,前面一段话好像说待遇低,但也没见说自己多少钱一个月
学电子,学音乐!!
回复 支持 反对

使用道具 举报

56

主题

143

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
376
金钱
376
注册时间
2013-4-25
在线时间
0 小时
发表于 2013-10-4 19:33:28 | 显示全部楼层
不错
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-4 21:53:51 | 显示全部楼层
回复【3楼】XINSI:
---------------------------------
这只是随便说一下!我只是想说一个单片机的简单分时和怎样扫描按键更好!告诉大家尽量不要在程序中使用delay死循环延时!
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-4 21:59:56 | 显示全部楼层
回复【2楼】SCMartian:
---------------------------------
可以啊!610967340@qq.com!!!
回复 支持 反对

使用道具 举报

13

主题

123

帖子

0

精华

初级会员

Rank: 2

积分
197
金钱
197
注册时间
2013-8-3
在线时间
0 小时
发表于 2013-10-4 23:56:08 | 显示全部楼层
回复【6楼】liuyongliuyong:
---------------------------------
好的,谢谢。
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-5 10:42:18 | 显示全部楼层
回复【7楼】SCMartian:
---------------------------------
不谢,大家一起交流交流!!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2013-10-5 11:33:25 | 显示全部楼层
顶楼主
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-5 20:31:41 | 显示全部楼层
回复【9楼】正点原子:
---------------------------------
哎,文笔很差!有人说看不懂啊!不过有一两个人看懂了也算是不枉我写了
回复 支持 反对

使用道具 举报

170

主题

917

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1824
金钱
1824
注册时间
2013-4-13
在线时间
63 小时
发表于 2013-10-6 23:03:52 | 显示全部楼层
没怎么看懂,但觉得思路很好。
手艺人要内外兼修。
回复 支持 反对

使用道具 举报

1

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-9-8
在线时间
2 小时
发表于 2013-10-7 00:32:45 | 显示全部楼层
文笔是有点差  呵呵  不过楼主这种思想的确是学校和工作两种写代码明显的区别
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-7 22:02:11 | 显示全部楼层
回复【12楼】谷子木:
---------------------------------
哈哈,,,将就着看呗!我也觉得,学校开发板配的那种程序框架,在工作中根本就不能用!特别是按键扫描,如果用死循环的话是很不明智的!
回复 支持 反对

使用道具 举报

8

主题

93

帖子

2

精华

中级会员

Rank: 3Rank: 3

积分
446
金钱
446
注册时间
2013-9-22
在线时间
0 小时
发表于 2013-10-8 20:44:46 | 显示全部楼层
写得不错,但是这段程序还是有提升的空间的。
比如,假设事件A每100ms做一次,事件B每500毫秒做一次,那么按照楼主的算法,在第500ms的时候,做事件A还是做事件B呢?其次,假设先做事件A,那么等事件A执行完毕再做事件B时,事件B已经有时间延迟了。也就是说系统存在时间延迟。如果任务有多个,这种时间延迟现象必然存在累积,那个时候,估计每个事件都不是按照既定的时间间隔来执行了。所以,楼主在算法上还要加强。另外,建议楼主在while(1)循环内部建议用函数指针数组来实现,也就是将各个事件(我更喜欢称其为“任务”)封装成函数,在while(1)内根据条件判断CPU执行哪段代码(用函数指针来实现),这样程序效率更高、可读性更好。
本人不才,不知这些建议可不可行,我的QQ:986796621,可以交流交流。推荐楼主一本书,强烈建议楼主看看:《时间触发嵌入式系统设计模式  使用8051系列微控制器开发可靠应用》。
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-9 09:34:04 | 显示全部楼层
回复【14楼】shr5791:
---------------------------------
哈哈。。。你已经很有才了!我这里只是一个很简单的框架,没有考虑任务优先级等,毕竟不是操作系统。还有就是我公司用的单片机是台湾的,只有4k左右的rom,所以还能应付过来!没想到你能想到那么多!谢谢你的书,我会找时间看看的
回复 支持 反对

使用道具 举报

8

主题

93

帖子

2

精华

中级会员

Rank: 3Rank: 3

积分
446
金钱
446
注册时间
2013-9-22
在线时间
0 小时
发表于 2013-10-9 09:58:16 | 显示全部楼层
回复【15楼】liuyongliuyong:
---------------------------------
以前我自己也写过一些调度器(还是不敢称之为“操作系统”),期间出现过很多问题,在想办法解决问题的过程中,不断仿真调试成功才是真正乐趣所在。共勉哈~
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-9 12:14:38 | 显示全部楼层
回复【16楼】shr5791:
---------------------------------
恩恩!!!!
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2013-10-10 13:28:26 | 显示全部楼层
顶楼主,分析的不错
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

2

主题

42

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
222
金钱
222
注册时间
2013-10-10
在线时间
1 小时
发表于 2013-10-15 20:04:40 | 显示全部楼层
LZ,这个有点儿像操作系统的任务调度和消息机制的思想。楼主能自发感觉出这种思路是很有灵性的,在操作系统的最开始,这种事情是一帮天才在搞的。

1、这种优先级处理的方式思路是对的,操作系统里叫:时间片,简单用可以,完善起来比较复杂。因为,代码段如果不能被中断的话,有时候往往不好估计代码的处理时间。操作系统里是作为线程优先级来调度的,任何一个线程都可以被挂起(终止)。

2、不管发生什么事情,先不着急处理,让系统先用消息队列记录下来先。系统再把这个事情,作为消息的方式,通知所有该知道的模块,模块可以选择性响应各种消息。这样的话,事件怎么来的开放者不关心,只关心如何处理事件。而且一个消息,允许被多个模块接收。

3、MCU在处理简单任务的时候,不要带框架,可能更直接,复杂任务的话,也有RTOS的。
你以为我在工作,其实我在玩;你以为我在玩,其实我在工作。
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2013-10-15 21:36:39 | 显示全部楼层
回复【19楼】光联:
---------------------------------
呵呵,,,谢谢指导!
回复 支持 反对

使用道具 举报

6

主题

124

帖子

0

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2013-8-12
在线时间
0 小时
发表于 2013-11-21 18:26:22 | 显示全部楼层
帮顶
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2014-1-4
在线时间
1 小时
发表于 2014-1-4 12:54:20 | 显示全部楼层
额,你的这个框架是可以用的,但不是理想的,因为单片机是过程控制系统不是电脑的多任务控制系统,就是C语言与VB的区别,你的那个定时条件执行相当于VB的对象执行了。单片片机还是过顺序执行的好,对于紧急事件可用中断,本人做单片机仿三菱PLC  http://www.tm-auto.com/index.php?m=Contact&a=index&id=70
回复 支持 反对

使用道具 举报

20

主题

158

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
334
金钱
334
注册时间
2012-8-21
在线时间
27 小时
发表于 2014-1-6 17:41:39 | 显示全部楼层
回复【楼主位】liuyongliuyong:
---------------------------------
 TH0=(65536-10000)/256;
 TL0=(65536-10000)%256;
 fTimer0_10ms = 1;
 dTimer0_100ms++;
 if(dTimer0_100ms == 10){
  dTimer0_100ms = 0;
  fTimer0_100ms = 1;
  dTimer0_500ms++;
  if(dTimer0_500ms == 5){
   dTimer0_500ms = 0;
   fTimer0_500ms = 1;
   dTimer0_1min++;
   if(dTimer0_1min == 120){
    dTimer0_1min = 0;
    fTimer0_1min = 1;
   }
  }
 }
这段代码完全可以放到主循环
还有,在使用定时器中断的时候
最好用一个变量即可,比如
u32 g_Flag10ms_timerirq =  c_32BitAllSet;这个代码在中断代码里处理
在使用定时器标志的时候,使用一个就用掉一个位
如:
if(g_Flag10ms_timerirq & c_TimerIrq_ScanKey_BtMask)
{
    g_Flag10ms_timerirq &=~c_TimerIrq_ScanKey_BtMask;
  //user code
}
这样写的话,定时的扩展性很强,方便维护
回复 支持 反对

使用道具 举报

20

主题

158

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
334
金钱
334
注册时间
2012-8-21
在线时间
27 小时
发表于 2014-1-6 17:43:56 | 显示全部楼层
回复【楼主位】liuyongliuyong:
---------------------------------
关于按键这部分,最好是使用一个编号,比如

const int T_KeyCodeRemap[]=
{
//orig real
0, c_Key_1,
1,  c_Key_2,
2,  c_Key_3,
3,  c_Key_Null,
4,  c_Key_Null,
5,  c_Key_Null,
6, c_Key_Null,
7, c_Key_12,
8,  c_Key_4,
9,  c_Key_5,
10, c_Key_6,
11, c_Key_12,
12,  c_Key_Null,
13,  c_Key_Null,
14, c_Key_Null,
15, c_Key_Null,
16,  c_Key_7,
17,  c_Key_8,
18, c_Key_9,
19, c_Key_Null,
20, c_Key_Null,
21, c_Key_Null,

22,  c_Key_Null,
23,  c_Key_Null,
24, c_Key_10,
25, c_Key_11,
26,  c_Key_Null,
27,  c_Key_Null,
28, c_Key_Null,
29, c_Key_Null,
30, c_Key_Null,
31, c_Key_Null,



};
使用表格方式

void KeyCodeRemap(int* keycode)
{
int tempi;

for(tempi=0; tempi<(sizeof(T_KeyCodeRemap)>>1); tempi++)
{
if(T_KeyCodeRemap[tempi<<1] == *keycode)
{
*keycode = T_KeyCodeRemap[(tempi<<1) + 1];
return;
}
}
*keycode = c_Key_Null;
}
通过扫键的时候获取的ID号,去或者按键具体值,方便维护
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-1-7 20:06:40 | 显示全部楼层
回复【23楼】lxj19901115:
---------------------------------
恩,谢谢指教!
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-1-7 20:07:05 | 显示全部楼层
回复【24楼】lxj19901115:
---------------------------------
哈,不错!谢谢指点哈!
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-1-7 20:11:45 | 显示全部楼层
回复【24楼】lxj19901115:
---------------------------------
可以给一个你用这个按键程序的例子看看么?感激不尽,我觉得你的比我的好多了!谢谢!!!
回复 支持 反对

使用道具 举报

17

主题

587

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4467
金钱
4467
注册时间
2013-6-27
在线时间
565 小时
发表于 2014-1-10 21:58:38 | 显示全部楼层
本人前后台系统定时器中断服务程序,有机会可以共同学习。
void SystickIntHandler(void) interrupt 1 //1MS
{
static uchar _XDATA TickPhase = 0;
TH0 = TH0VAL;         //定时1MS  重新载值   
TL0 = TL0VAL; 
TickPhase ++;
SysLinearTimer ++;
switch(TickPhase)
{
case 1:
ProF_10mS_Lamper();//指示灯
break;
case 2:
ProF_10mS_Beeper();//蜂鸣器
break;
case 3:
ProF_10mS_Key();//按键
break;
case 10:
TickPhase = 0;
break;
}

if(DelayTimer)
DelayTimer --;//延时控制
}
让我们的思维驾驭在电的速度之上!
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-1-11 13:05:55 | 显示全部楼层
回复【28楼】DongInker:
---------------------------------
恩,你这个也是一种方法,跟我的差不多!但是一般比较紧急的任务才放在中断里面处理,对不怎么紧急的任务,可以在中断里产生标志位,然后在主循环里面处理,这样比较好点!中断里面不要放太多东西
回复 支持 反对

使用道具 举报

2

主题

69

帖子

0

精华

初级会员

Rank: 2

积分
97
金钱
97
注册时间
2013-7-17
在线时间
0 小时
发表于 2014-1-14 21:44:36 | 显示全部楼层
学习了。今年也要毕业找工作了,非常感谢各位前辈和学长们的经验和指教。加楼主的QQ时需要回答问题,所以,能不能劳请楼主加一下我的呢?294653382 。希望以后能多多指教:)
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-1-15 12:23:47 | 显示全部楼层
回复【30楼】zqdhls:
---------------------------------
呵呵,,,指教不敢,互相学习吧!
回复 支持 反对

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2014-1-21
在线时间
0 小时
发表于 2014-2-15 16:42:52 | 显示全部楼层
学习了!!!!!在操作系统的最开始,这种事情是一帮天才在搞的
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-2-15 17:46:17 | 显示全部楼层
回复【32楼】子周:
---------------------------------
呵呵,,,这个东东很低级了!没涉及到操作系统的内容呢
回复 支持 反对

使用道具 举报

55

主题

1231

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2624
金钱
2624
注册时间
2014-2-13
在线时间
514 小时
发表于 2014-2-16 11:07:15 | 显示全部楼层
感谢楼主的分享!!!
技术交流,Sell 中颖单片机,欢迎私信骚扰
回复 支持 反对

使用道具 举报

69

主题

289

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1294
金钱
1294
注册时间
2013-3-14
在线时间
62 小时
 楼主| 发表于 2014-2-16 13:52:40 | 显示全部楼层
回复【34楼】黑夜之狼:
---------------------------------
共勉
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
发表于 2015-8-4 09:51:45 | 显示全部楼层
mark一下,方便日后学习
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2015-8-4 10:17:55 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

2

主题

75

帖子

0

精华

初级会员

Rank: 2

积分
106
金钱
106
注册时间
2015-7-30
在线时间
1 小时
发表于 2015-8-4 21:36:59 | 显示全部楼层
写的不错,顶一个
方法比问题多,思路决定出路,人生无极限贵在坚持。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 12:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表