今天晚上,看朱老师的视频,以0.8倍的速度看,这样播放速度总算是跟上老师语速了。
除了讲技术之外,老师在课程里也分享了自己最初学习时的心历路程,这些内容,对于我们这些初学的自学者来说,真的是有很大的鼓励。其它的单片机教程,一上来就搞有一点难度的代码,我等看得头大的同时,还会有一定的挫败感——为什么别人那么聪明?为什么我怎么想也想不出来?我是不是傻?是不是不适合学?我的逻辑思维是不是不行?。。。
而朱老师并不会一开始就直接上那种简洁的代码,而是傻瓜式的,一条一条的写出来,然后,再把写出来的傻瓜代码进一步优化,提练。这样的好处,是先实现了基础功能,其次,代码可视化之后,可以看到得其中的规律。
这让我想起了吴军老师在得到的课程《数学通识50讲》中,美国人是如何解 鸡兔同笼 之类问题的:
在小学他们不教学生那些需要技巧的解法。对于鸡兔同笼问题,就是列表的笨办法。比如,在第一个例子中,他们先让学生们明白,兔子的数量不能超过94/4 = 24只,然后就列一张表,从24只开始往下试验,看看脚的数量有多少:
我当时看了他们的教科书,就想美国人真笨,果然数学学不好。
但是发现他们再做其它相似的问题时,就可以从上述过程中受到启发,比如前面的鸡蛋问题,美国人也是列表:
事实上,只要是有整数解的各种二元一次方程的问题,都可以用列表这种笨办法解决。也就是说,美国小学的做法实际上是教给了大家一个很笨的,但是很通用的工具。这样,能解决一个就能解决很多,虽然办法很笨,很花时间,但总不至于让孩子们无从下手。
至于那些解题技巧,他们很少在小学教,省得大家学不会,有挫败感。那些聪明的孩子,可以去上课外班。上述笨办法的另一个好处是,学生们在列表的过程中,更感受到数字变化的趋势,慢慢地就会知道大约从多少开始试验,而不是永远从零开始。
在开初学的时候,不妨先用笨办法,建立一种直观的感觉,同时,也要多加训练自己的逻辑思维,以缩短脑回路。为什么很多老一辈的人心算很快,而我们却离不开计算器?很大程度,跟他们以前用算盘有关——用算盘的时候,是可以看得见珠子的,慢慢的,就成了珠心算了。
说了那么多心得感悟,把今天的代码粘贴上来。
这个代码是我自己写的并在开发板上做了验证,还没有看老师对应的讲解视频,明天再把代码优化一下,应该可以更简洁些,然后再看老师的讲解视频。
思路是行、列扫描。按下按键的时间要远远大于单片机采样的时间,所以,在按下的时候,对单片机来说,是很容易扫描到的。世间武功唯快不破。
#include <reg51.h>
#define uchar unsigned char
uchar TempHang,TempLie,Number;
void delay();
sbit LED = P2^7;
uchar SingleLED[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//实现功能:矩阵按键,当按键按下时,显示对应的键值;
void main()
{
while(1)
{
P0 = 0xf0; //1111 0000 扫描行
TempHang = P0; //读取矩阵按键的值,看有没有按键按下
if(TempHang != 0xf0) //如果二者不相等,说明有按键接按下了。
{
P0 = 0x0f; //0000 1111 扫描列
TempLie = P0; //读取端口数据
if(TempLie != 0x0f)
{
Number = TempHang | TempLie; //对行、列数据进行按位或运算,定位出哪个按键按下了
switch (Number)
{
case 0xee : P1 = SingleLED[0];break; //0 1110 1110
case 0xde : P1 = SingleLED[1];break; //1 1101 1110
case 0xbe : P1 = SingleLED[2];break; //2 1011 1110
case 0x7e : P1 = SingleLED[3];break; //3 0111 1110行
case 0xed : P1 = SingleLED[4];break; //4 1110 1101
case 0xdd : P1 = SingleLED[5];break; //5 1101 1101
case 0xbd : P1 = SingleLED[6];break; //6 1011 1101
case 0x7d : P1 = SingleLED[7];break; //7 0111 1101行
case 0xeb : P1 = SingleLED[8];break; //8 1110 1011
case 0xdb : P1 = SingleLED[9];break; //9 1101 1011
case 0xbb : P1 = SingleLED[10];break; //a 1011 1011
case 0x7b : P1 = SingleLED[11];break; //b 0111 1011行
case 0xe7 : P1 = SingleLED[12];break; //c 1110 0111
case 0xd7 : P1 = SingleLED[13];break; //d 1101 0111
case 0xb7 : P1 = SingleLED[14];break; //e 1011 0111
case 0x77 : P1 = SingleLED[15];break; //f 0111 0111行
}
delay();
}
}
}
}
void delay()
{
uchar i,j;
for(i=0; i<100; i++)
for(j=0; j<100; j++);
}