myvioletchen 发表于 2010-6-11 09:31:07

楼主好人啊!支持!

jjinhuang 发表于 2010-6-11 10:06:00

嗯嗯。希望集合成个合集的!支持!!

ITOP 发表于 2010-6-11 10:44:43

学习了!!

ball648500361 发表于 2010-6-11 19:01:39

mark

linhai 发表于 2010-6-11 19:16:17

谢谢

lerysun 发表于 2010-6-11 20:34:29

mark 好贴…… 建议加精

gxy508 发表于 2010-6-12 14:46:13

mark

liangtao 发表于 2010-6-12 16:12:16

mark

electricit 发表于 2010-6-12 16:34:27

mark

hhui02 发表于 2010-6-12 17:23:09

学习了,谢谢。

Linfanfeng 发表于 2010-6-12 17:55:10

我也觉得现在在网上的资料要么是供初学者用的,要么是功能很强,但是只是演示性质(晒),或者是卖广告的。
幸亏我们这个论坛的高手们都不吝赐教啊!代表所有初学者向你们致敬!

再说说楼主所提到的释放CPU、按键处理,我简单地说说我的看法(仅供参考)。
    释放CPU:在你所建立的工程不是很复杂并且实时性要求不高的时候,你不懂这个概念的话貌似问题不大,但是倘若你所设计的系统实时性要求较强时,你没有考虑过释放CPU,那你做出来的系统将是问题多多的。
   举个例子:做一个简单的门禁系统(真的是很简单的,高手们看到不能偷笑哦),有上位机、下位机,下位机需要串口与上位机进行通讯,两者的通讯协议是多字节的帧结构;下位机需要扫描按键,检查是否有按键按下,按键是由数字键和几个功能键组成;还要LCD显示。
    对于这个系统,按键扫描可采用“零耗时扫描”以及查表法来选择返回键码值的方式,这样设计的话,按键消抖处理的延时就可以用定时器来完成,不用CPU去软件延时;键盘扫描利用查表法的话,可以使得程序结构简单,不用太多的重复,也不用一大堆switch{case:……}结构,整个键盘扫描程序就一个循环查表搞定。
    与上位机通信这个模块,可以声明两个缓冲区,一个缓冲区(buffer1)是放置当前在接收中的帧,另外一个(buffer2)是放置已经接收完的帧。帧接收工作最好放在串口中断中完成,当接收完成即将buffer1的内容转到buffer2当中去,并将接收完成标志置1,让主程序去处理帧。
    如此一来,主程序就没有延时语句,就是循环判断各个标志位,若标志有效才去工作。
    按键处理:对于4X4键盘,可能很多像我一样的初学者都用或者用过类似下面程序的方法去扫描。下面说说基于查表法的键盘扫描方法
unsigned char key_check(void)

{

unsigned char code table[]={0x01,0x02,0x03,0x0a,
                            0x04,0x05,0x06,0x0b,
                            0x07,0x08,0x09,0x0c,
                            0x0f,0x00,0x0e,0x0d};
unsigned char temp;
unsigned char key;
unsigned char i,j;
unsigned char key_number=0xff;
unsigned int kk=0;
while(kk<=2)
    {
          kk=kk+1;
      P2=0xff;
      P2_4=0;
      temp=P2;
      temp=temp&0x0f;
      if (temp!=0x0f)
      {
          for(i=100;i>0;i--)
          for(j=200;j>0;j--);
          temp=P2;
          temp=temp & 0x0f;
          if (temp!=0x0f)
            {
            temp=P2;
            temp=temp&0x0f;            
            switch(temp)
                {
                  case 0x07:
                  key=0;
                  break;
                  case 0x0b:
                  key=4;
                  break;
                  case 0x0d:
                  key=8;
                  break;
                  case 0x0e:
                  key=12;
                  break;
                                        default:
                                        break;
                }
            temp=P2;
            key_number=table;
            temp=temp&0x0f;            
            while(temp!=0x0f)       //等待按键放开
                {
                  temp=P2;
                  temp=temp&0x0f;            
                }
                           return key_number;
            }
      }
      P2=0xff;
      P2_5=0;
      temp=P2;
      temp=temp & 0x0f;
      if (temp!=0x0f)
      {
          for(i=100;i>0;i--)
          for(j=200;j>0;j--);
          temp=P2;
          temp=temp & 0x0f;
          if (temp!=0x0f)
            {
            temp=P2;
            temp=temp & 0x0f;            
            switch(temp)
                {
                  case 0x07:
                  key=1;
                  break;
                  case 0x0b:
                  key=5;
                  break;
                  case 0x0d:
                  key=9;
                  break;
                  case 0x0e:
                  key=13;
                  break;
                }
            temp=P2;
            key_number=table;
            temp=temp & 0x0f;            
            while(temp!=0x0f)
                {
                  temp=P2;
                  temp=temp&0x0f;            
                }
                               return key_number;
            }
      }
      P2=0xff;
      P2_6=0;
      temp=P2;
      temp=temp & 0x0f;
      if (temp!=0x0f)
      {
          for(i=50;i>0;i--)
          for(j=200;j>0;j--);
          temp=P2;
          temp=temp & 0x0f;
          if (temp!=0x0f)
            {
            temp=P2;
            temp=temp & 0x0f;            
            switch(temp)
                {
                  case 0x07:
                  key=2;
                  break;
                  case 0x0b:
                  key=6;
                  break;
                  case 0x0d:
                  key=10;
                  break;
                  case 0x0e:
                  key=14;
                  break;
                }
            temp=P2;
            key_number=table;
            temp=temp & 0x0f;            
            while(temp!=0x0f)
                {
                  temp=P2;
                  temp=temp & 0x0f;            
                }
                               return key_number;
            }
      }
      P2=0xff;
      P2_7=0;
      temp=P2;
      temp=temp & 0x0f;
      if (temp!=0x0f)
      {
          for(i=100;i>0;i--)
          for(j=200;j>0;j--);
          temp=P2;
          temp=temp & 0x0f;
          if (temp!=0x0f)
            {
            temp=P2;
            temp=temp & 0x0f;            
            switch(temp)
                {
                  case 0x07:
                  key=3;
                  break;
                  case 0x0b:
                  key=7;
                  break;
                  case 0x0d:
                  key=11;
                  break;
                  case 0x0e:
                  key=15;
                  break;
                }
            temp=P2;
            key_number=table;
            temp=temp & 0x0f;            
            while(temp!=0x0f)
                {
                  temp=P2;
                  temp=temp & 0x0f;            
                }
                               return key_number;
            }
      }
    }
        return 0xff;
}
   

查表键盘扫描法:
首先,先建立一个表,
//键盘扫描所用的表格
//格式:输出值、输入值、对应的键码
unchar code KeyScanTable={
                                           0xef,0x0e,0x00,
0xef,0x0d,0x04,
                                           0xef,0x0b,0x08,
                                           0xef,0x07,0x0c,
                                           0xdf,0x0e,0x01,
                                           0xdf,0x0d,0x05,
                                           0xdf,0x0b,0x09,
                                           0xdf,0x07,0x0d,
                                           0xbf,0x0e,0x02,
0xbf,0x0d,0x06,
                                           0xbf,0x0b,0x0a,
                                           0xbf,0x07,0x0e,
                                           0x7f,0x0e,0x03,
                                           0x7f,0x0d,0x07,
                                           0x7f,0x0b,0x0b,
                                           0x7f,0x07,0x0f};
然后在键盘扫描程序里面就只需要一个循环去查表即可(注意下面的程序是没有消抖处理的,是在定时器中断服务程序中调用)
unchar KeyScan_No_Delay()
{
    unchar i,base_addr;
        unchar data_in;
         P2=0x0f;
        if(P2==0x0f)                                 //说明没有按键按下
        return 0xff;
        for(i=0;i<=0x0e;i++)
        {
           base_addr=i*0x03;
           P2=KeyScanTable;               //输出
            _nop_();
           _nop_();
           data_in=P2;                                 //读入
           if(data_in==KeyScanTable)      //比较,若相同则返回对应的键码
           return KeyScanTable;
        }
}

   
   写地不好,请见谅。
   That's all.(别拍砖呐!./emotion/em007.gif)

markloveyou 发表于 2010-6-12 19:01:09

写得很实际

07636678 发表于 2010-6-12 19:44:59

ding

07636678 发表于 2010-6-12 21:16:36

我的是用Keil uVision2好像建不起你那个模板,是不是一定要你那个版的KEIL才行啊?

chenzy 发表于 2010-6-13 12:57:59

不错,定一个

hwx123 发表于 2010-6-13 22:15:38

LZ,能否发个带组合键功能的按键扫描程序让大家学习学习

xiaohutu 发表于 2010-6-13 23:00:51

感谢分享。。。

liuyun_1969 发表于 2010-6-14 12:03:58

写的真好。我正在做一个项目。发现例程只是教你理解。而实际中根本不能那样用。是呀,CPU有很多事情要做,你得大致估算执行任务的时间,要尽量减少程序对CPU的占用。更不允许让CPU死等的情况。支持支持。

t632159 发表于 2010-6-14 18:59:22

恩,正在学习,期待后续!!!!

Linfanfeng 发表于 2010-6-17 00:53:38

写得非常好!希望LZ能够打包上传提供下载啊

iamwangwei 发表于 2010-6-18 09:48:17

回复【199楼】xuesongrenjun
-----------------------------------------------------------------------
非常好,学习。

shenzhenlang 发表于 2010-6-18 17:37:46

学习中

wjs1981 发表于 2010-6-19 15:50:08

mark

hopkins 发表于 2010-6-19 17:14:50

mark

hpdell 发表于 2010-6-19 17:52:35

不错哟!!!!!!!!!

zhangfuhg 发表于 2010-6-19 19:12:05

太好了!!!!!!!!!

KevinLee 发表于 2010-6-19 19:27:34

感谢分享。

ababvic 发表于 2010-6-19 22:58:49

mark

xslff 发表于 2010-6-19 23:39:21

一语点中要害!

wxx116zh 发表于 2010-6-20 20:37:26

学习了。。

ilovezeno 发表于 2010-6-20 21:55:37

其实农民_运动讲习所的那个经典文章更加透彻。。。。。

mdj-fish 发表于 2010-6-20 22:38:27

其实农民_运动讲习所的那个经典文章更加透彻。。。。。
 

myworkmail 发表于 2010-6-21 00:29:50

支持

xinyou 发表于 2010-6-21 08:58:18

学习了…

jring2002 发表于 2010-6-21 16:05:27

回复【139楼】tangwei039
-----------------------------------------------------------------------

TH0 = 255-CLOCK/TIME_PER_SEC/12/256;   
//CRY_OSC,TIME_PER_SEC在 os_cfg.h中定义
    TL0 = 255-CLOCK/TIME_PER_SEC/12%256;
什么意思?

jring2002 发表于 2010-6-21 17:27:51

回复【楼主位】tangwei039
-----------------------------------------------------------------------

为何初值如此计算?

jring2002 发表于 2010-6-24 17:23:13

初值应该是这样        TH0=(65535-clock/time_per_sec/12)/256;
        TL0=(65535-clock/time_per_sec/12)%256;

cocoasuny 发表于 2010-6-25 23:43:46

PDF呢??

KR770906 发表于 2010-6-26 13:33:37

和lz同感

liok 发表于 2010-6-26 15:14:23

楼主,各位牛人,有一段代码没看懂,帮忙解答一下:
while(1)
    {
      Timer0MainLoop() ;
      KeyMainLoop(&KeyValue) ;
         
      if(KeyValue == (KEY_VALUE_1 | KEY_DOWN)) P0 = ~1 ;
      if(KeyValue == (KEY_VALUE_1 | KEY_LONG)) P0 = ~2 ;
      if(KeyValue == (KEY_VALUE_1 | KEY_CONTINUE)) { P0 ^= 0xf0;}
      if(KeyValue == (KEY_VALUE_1 | KEY_UP)) P0 = 0xa5 ;
    }
这是楼主写的KEY第二章里面的一段代码,但是在这个主程序中有一个子函数的调用我没看懂   
Timer0MainLoop() ;
这个子函数的源代码是什么?放在这里的功能是什么?
请各位帮忙解答一下!谢谢!

qtds11 发表于 2010-6-28 17:27:52

顶一个标记,刚工作慢慢学习

hanzhifei_2004 发表于 2010-6-29 00:45:54

楼主很强悍,我深有同感,向楼主学习

Linfanfeng 发表于 2010-6-30 15:09:39

希望LZ打包上传提供下载的顶起!

./emotion/em018.gif
./emotion/em018.gif
./emotion/em018.gif

zgcumt 发表于 2010-6-30 15:37:42

mark

zjj2010 发表于 2010-6-30 22:44:46

记号

Imcu 发表于 2010-7-1 10:31:56

太好了

xytzc 发表于 2010-7-1 12:04:45

从上班看到下班还没看完,很是受益,做个记号,感谢楼主!

sharp0 发表于 2010-7-1 15:35:16

楼主热心肠,支持!

hanzhifei_2004 发表于 2010-7-1 21:36:04

回复【342楼】liok
-----------------------------------------------------------------------

Timer0MainLoop() ;
函数是一个20ms的系统周期,
还有我的板子要改成
if(KeyValue == (KEY_VALUE_1 & KEY_DOWN)) P0 = ~1 ;
      if(KeyValue == (KEY_VALUE_1 &KEY_LONG)) P0 = ~2 ;
      if(KeyValue == (KEY_VALUE_1 & KEY_CONTINUE)) { P0 ^= 0xf0;}
      if(KeyValue == (KEY_VALUE_1 & KEY_UP)) P0 = 0xa5 ;
功能才能实现;

zsgood6688 发表于 2010-7-2 17:30:43

不错

gmolzc 发表于 2010-7-2 17:49:21

頂,有時間好好看看!!!

pan90 发表于 2010-7-3 13:04:35

mark

qianlihu 发表于 2010-7-9 11:58:20

回复【楼主位】tangwei039
-----------------------------------------------------------------------

mark it

danielzhuang 发表于 2010-7-9 14:37:53

支持下了1

wxx116zh 发表于 2010-7-9 20:06:35

mark

liok 发表于 2010-7-10 13:04:26

回复【350楼】sharp0
-----------------------------------------------------------------------

那请问:
Timer0MainLoop() ;
这个函数放这里就只是起一个延时作用还是里面有其他什么功能,麻烦了!希望您能说明一下!谢谢!

zhaopapaya 发表于 2010-7-12 11:32:39

好啊,关注

l.htlht 发表于 2010-7-12 12:21:47

从单片机初学者迈向单片机工程师

liumaojun_cn 发表于 2010-7-12 13:18:26

mark

lusen 发表于 2010-7-12 15:05:34

茅塞顿开

shenqibuhui 发表于 2010-7-15 23:27:06

顶一下楼主~~~~~

gmolzc 发表于 2010-7-16 08:30:46

頂!強烈支持!

worldwindhuu 发表于 2010-7-16 16:18:53

顶!

hefei1314 发表于 2010-7-16 18:06:36

不错

zqd311107 发表于 2010-7-17 09:22:22

不错

zqq823557482 发表于 2010-7-17 16:11:38

mark

gyzzg2030 发表于 2010-7-17 16:30:27

学习,再学习

yasewang2 发表于 2010-7-20 18:38:47

这个必须顶

qq335702318 发表于 2010-7-21 00:16:35

mark
书本学不到的!!极为有用~~~~~~~~~~

aqjinhu 发表于 2010-7-21 11:30:06

怎么没复位电路的硬件设计啊?

zidong_MCU 发表于 2010-7-21 12:50:33

mark!!!!!!!!!!!

xujc0806 发表于 2010-7-22 15:40:14

怎么不传了啊,写的很好

Rocker 发表于 2010-7-22 16:03:56

咋不出本书呢?

watts_007 发表于 2010-7-22 17:14:31

留印,有更新一定看

rgb0 发表于 2010-7-22 18:59:56

谢楼主,MARK,收了

yasewang2 发表于 2010-7-22 19:38:06

请问这些知识,有哪些书本上提到过吗,或者说想学更高级的编程知识上哪去学,国外有好的网站吗

mcu_mouse 发表于 2010-7-30 20:48:31

mark

billiejean 发表于 2010-7-30 23:38:29

好贴,收藏了,本人初学

czg_82 发表于 2010-7-31 16:10:54

不错,受益匪浅!

gasolhu 发表于 2010-7-31 21:37:25

留标记

xyyjjb 发表于 2010-7-31 23:22:55

Mark

qilujie 发表于 2010-7-31 23:23:38

这些我觉得是初学者都应该会的。⊙﹏⊙b汗

some9009 发表于 2010-8-1 02:52:01

Mark

yesjustme1 发表于 2010-8-1 14:37:49

我决定了,摒弃从前,着眼此处,从头再学!哈哈

hexi8511 发表于 2010-8-1 17:35:04

期待楼主继续更新啊

ddaitt999 发表于 2010-8-1 17:56:10

这个牛

2006lc 发表于 2010-8-1 21:38:37

有启发

tangshanqiang 发表于 2010-8-2 11:07:57

强烈感谢楼主,强烈要求给一个cool,希望楼主能打包上传更多资料,顶。。。。。。。。。。。。。。。。

poet_lee 发表于 2010-8-3 10:14:01

好贴子 讲的不错

jinbangzhou 发表于 2010-8-3 10:35:02

mark

zwdxsky 发表于 2010-8-6 22:50:35

好好学习!

Mr_Cool 发表于 2010-8-7 01:54:14

激_情贴!顶!为人民服务!

zxycba 发表于 2010-8-9 11:22:45

一路走过,深有感触。希望大家继续把楼主顶出来!哈哈

youdianchedan 发表于 2010-8-9 16:17:08

谢谢楼主。
光那一段按键的程序都看了一个多小时才看明白,惭愧。
不过受益良多,继续看。

maxuedong 发表于 2010-8-10 13:02:04

学习中,顶!!

tianyi996 发表于 2010-8-10 21:10:46

回复【楼主位】tangwei039
-----------------------------------------------------------------------

LZ啊
后面的怎么没发
期待你重出江湖啊

wgm_123 发表于 2010-8-11 10:22:55

楼主的红外解码教程呢?楼主,快来看看那,这么多人在等候你的大作,快点儿啊,谢谢你对我们的帮助。

hope0903 发表于 2010-8-11 10:59:27

期待LZ的全套PDF!

tianyuanqike 发表于 2010-8-11 11:51:03

等我有成就了,在来回看此帖,谢谢您!

nanan1211 发表于 2010-8-11 15:45:21

学习了
页: 1 2 3 [4] 5 6 7 8 9 10 11 12 13
查看完整版本: 从单片机初学者迈向单片机工程师(一份正真的让你成为工程师的贴子)