历史上的今天
返回首页

历史上的今天

今天是:2025年08月20日(星期三)

正在发生

2021年08月20日 | 51单片机-综合例程

2021-08-20 来源:eefocus

1.其他按键的使用

我们之前都是让P2.3输出低电平来让K1, K2, K3, K4作为独立按键,那我们要想用K13,K14,K15,K16做独立按键时只要P2.0输出低电平就可以了。下面是简化的原理图

1.png?imageView2/2/w/550

 

2.美女与男人

作为本章的最后一个题目,我们结合所有学过的知识做一个综合例程,实现美女与男人的游戏的功能代码。


游戏规则如下:

美女和男人各持一枚硬币

两人都出正面时:男人得3块钱

两人都出反面时:男人得1块钱

两人出一正一反时:女人得2块钱

 

3.开发板的实现

我们这样做模拟,程序的开始定义两个全局变量man和woman初始化为30,意为每人各持30块钱用来显示在左右端的两个数码管上,男人的钱显示在左边的数码管,女人的钱显示在右边的数码管。

3.png?imageView2/2/w/550

我们用K13作为给男人加3块钱的同时也给女人减3块的功能。

用K14作为给男人加1块钱的同时也给女人减1块的功能。

用K15作为给男人减2块钱的同时给女人加2块的功能。

三个按键都是不支持连按!

4.png?imageView2/2/w/550

我们规定,谁先达到45块钱及以上时就算谁赢!

比如男人的钱到达或超过45块钱时,女人的钱就不显示了,这两个数码管熄灭,如果是女人的钱到达或超过45块时,男人的钱就不显示了,这是用来表明谁的钱还在显示谁就是赢家的常识。


决出胜负的时候,此时的游戏结束,蜂鸣器就间隔鸣叫,鸣叫的时候所有数码管熄灭,不鸣叫的时候就只有4个数码管亮着,数码管呈现间隔显示,蜂鸣器间隔鸣叫。要想重新开始游戏必须复位开发板重启!

 

4.部分代码改写

初始化LedBuff[]数组的时候第2和第3号元素为0xBF,让数码管2和数码管3显示中间那一杠。


本讲的例程主函数的死循环执行完一次循环的时间比以往的例程要多,所以times的判断我们只需要它超过300即可,而不是像以前一样要超过500才执行功能代码。


因为用上了3个按键,每个按键功能被封装为一个函数了,所以我们定义了一个宏“#define  TIMES  300”,3个按键的函数判断times时,只需书写“if(times>=TIMES&&KEYxx==1)”即可,以后我们写的代码死循环里比这次的例程执行一遍循环的时间还长的话,把宏改为比300还小的数就可以了。


还有如果单独循环“SEG_task();”会使所有数码管显示很暗,这是因为这个函数是这样循环执行的

第一次循环

P0=0xFF;

ADDR2 = 0;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[0];i++;


第二次循环


P0=0xFF;

ADDR2 = 0;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[1];i++;



……

每一次循环里“P0=LedBuff[x];”持续的时间不够多又要开始执行“P0=0xFF;”,所以“P0=0xFF;”的刷新率太高就会使数码管的亮度变暗,要想解决这个问题就必须使“P0=LedBuff[x];”持续的时间多一点再执行“P0=0xFF;”,所以我们在“SEG_task();”后用上短暂的延时。


而为什么以前的例程里“SEG_task();”没有这种现象出现,这个大家回去看一下就知道以前的 “SEG_task();”还要执行下面这些代码

LedBuff[0] = LedChar[cnt%10];   

if(cnt>=10)  LedBuff[1]= LedChar[(cnt/10)%10];  

if(cnt>=100) LedBuff[2]= LedChar[(cnt/100)%10];

if(cnt==0){  LedBuff[1]=0xFF;LedBuff[2]=0XFF; }


这些代码的执行占用了时间,所以给“P0=LedBuff[x];”保持住了一段时间的点亮,避免了长时间被“P0=0xFF;”刷新。


#include

sbit ADDR2 = P1^2;

sbit ADDR1 = P1^1;

sbit ADDR0 = P1^0;

sbit ENLED = P1^4;

sbit ADDR3 = P1^3;

  

sbit BEEP   = P1^6;

sbit KEY13  = P2^4;

sbit KEY14  = P2^5;

sbit KEY15  = P2^6;

#define  TIMES  300   //此例程的主循环里循环一次所要花费的时间比以往的例程要多,所以按键的times判断需要减少到300,不然还是500的话需要我们长按住一段时间才会响应功能代码

unsigned char code LedChar[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};//数码管状态值初始化

unsigned char LedBuff[6]={0xFF, 0xFF, 0xBF, 0xBF, 0xFF, 0xFF};//初始化数码管显示缓存区

unsigned char man=30,woman=30;//初始化男人和女人的钱

  

void UPDATE_LED()//更新数码管显示缓存区

{

    LedBuff[5]=LedChar[man/10]; 

    LedBuff[4]=LedChar[man%10]; 

    LedBuff[1]=LedChar[woman/10]; 

    LedBuff[0]=LedChar[woman%10];

}

  

void SEG_task()//数码管显示函数

{

    static unsigned char i=0;

   

    P0=0xFF;//端口状态全部熄灭数码管里的LED达到刷新作用

    switch(i)

    {

        case 0:

        ADDR2 = 0;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[0];i++;break;

        case 1:

        ADDR2 = 0;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[1];i++;break;     

        case 2:

        ADDR2 = 0;ADDR1 = 1;ADDR0 = 0;P0=LedBuff[2];i++;break;  

        case 3:

        ADDR2 = 0;ADDR1 = 1;ADDR0 = 1;P0=LedBuff[3];i++;break;

        case 4:

        ADDR2 = 1;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[4];i++;break;     

        case 5:

        ADDR2 = 1;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[5];i=0;break; 

    }  

}

  

void KEY13_task()

    static unsigned char key_up=1;

    static unsigned int  times=0; //用来记录进入过按键判断语句的次数 

    if(key_up==0)

    {      

        times++;     

        if(times>=TIMES&&KEY13==1)

        {

            times=0;

            man+=3;      //男人的钱加3块

            woman-=3;    //女人的钱减3块

            UPDATE_LED();//更新数码管显示缓存区

        }

    }

    key_up=KEY13;

}

  

void KEY14_task()

    static unsigned char key_up=1;

    static unsigned int  times=0; //用来记录进入过按键判断语句的次数 

    if(key_up==0)

    {      

        times++;     

        if(times>=TIMES&&KEY14==1)

        {

            times=0;

            man+=1;      //男人的钱加1块

            woman-=1;    //女人的钱减1块

            UPDATE_LED();//更新数码管显示缓存区

        }

    }

    key_up=KEY14;

}

  

void KEY15_task()

    static unsigned char key_up=1;

    static unsigned int  times=0; //用来记录进入过按键判断语句的次数 

    if(key_up==0)

    {      

        times++;     

        if(times>=TIMES&&KEY15==1)

        {

            times=0;

            man-=2;      //男人的钱减2块

            woman+=2;    //女人的钱加2块

            UPDATE_LED();//更新数码管显示缓存区

        }

    }

    key_up=KEY15;

}

  

void BEEP_ON(unsigned char x)

{

    unsigned int i,time;

    for(time=0;time<2000;time++)//“time<2000”决定鸣叫的时间

    {  

        if(x==1)BEEP=!BEEP;

        else BEEP=0;

        for(i=0;i<30;i++);

    }

}

  

void main()

{  

    unsigned int i,x;//做循环和延时用

    ADDR3 = 1;//使能三八译码器

    ENLED = 0;// 

   

    P2 = 0xFE;//让K13,K14,K15能具备有被拉低的条件先

    UPDATE_LED();//更新数码管显示缓存区

    while(1)

    {        

        SEG_task();  //数码管显示函数

        KEY13_task();//K13按键的任务

        KEY14_task();//K14按键的任务

        KEY15_task();//K15按键的任务

    

        if(man>=45 || woman>=45)//只要其中一方的钱到达45块及以上就结束游戏,程序进入死循环

        {

            if(man>=45){LedBuff[1]=0xFF; LedBuff[0]=0xFF;}//不再显示女人的钱

            else  {LedBuff[5]=0xFF; LedBuff[4]=0xFF;}     //不再显示男人的钱  

            while(1)

            {

                P0=0xFF;               //熄灭所有数码管

                BEEP_ON(1);            //蜂鸣器鸣叫一段时间

                for(i=0;i<300;i++)     //让数码管显示一段时间

                {

                    SEG_task();

                    for(x=0;x<200;x++);//加此延时是为了让数码管显示亮一点,不然仅让“SEG_task();”循环,显示就会暗一些

                }

            }  

        }

    }

}


“man+=3;”就是“man= man+3;”的简化书写。


2.感言


我们现在是模块化编程了,在了解了美女与男人的游戏题目后,阅读主函数都清晰明朗很多。


这个题目的要求就像是全国电子设计竞赛一样,需要我们一步一步地完成每个模块功能,包括以后做产品项目,模块化编程是为了灵活运用和增加可读性,以后在做其他项目时遇到相似的要求我们拿来主义即可,维护起来也方便,但大家都需要习惯写很详细的注释才行。


在本讲代码的基础上其实也可以简单地改写成一个篮球简易计分器的功能,如果大家能自己实现的出来,以后去打球拿块开发板去计分也可骗骗一些不懂的同学,认为这是很高大上的玩意。

推荐阅读

史海拾趣

超霸(GP)公司的发展小趣事

2013年,绿索超容在南京江宁区智能电网产业园正式成立。公司自创立之初,就明确了“制造中国可靠性最高的超级电容”的目标,以及“引领超容行业,做绿色能源模范”的使命。这一清晰的发展定位,为绿索超容后续的技术创新和市场拓展奠定了坚实的基础。公司初期虽然面临资金和技术挑战,但通过不懈努力,逐步建立了自己的研发团队和生产体系。

HSMC公司的发展小趣事

HSMC的发展不仅为公司自身带来了显著的经济效益,也为当地社会和经济发展做出了重要贡献。项目全面达产后,预计可实现年产值600亿元,利税60亿元,直接带动就业人口3000人。此外,HSMC还通过技术创新和产业升级,带动了上下游产业链的发展,促进了整个电子行业的繁荣与进步。

以上五个故事共同描绘了HSMC在电子行业中的崛起与发展历程。作为一家充满活力和创新精神的企业,HSMC正以其独特的优势和不懈的努力,向着成为全球领先CIDM晶圆厂的目标不断迈进。

ALSC [Alliance Semiconductor Corporation]公司的发展小趣事

ALSC公司成立于XXXX年,初创期面临着激烈的市场竞争和技术壁垒。然而,创始人凭借对半导体技术的深刻理解和市场需求的敏锐洞察,决定专注于开发高性能、低功耗的半导体产品。经过多次尝试和不断改进,公司成功推出了一款具有竞争力的产品,并逐渐在市场上获得了一席之地。

得力(deli)公司的发展小趣事

得力公司最初以文具制造起家,但在电子科技快速发展的时代,公司意识到必须转型升级以适应市场需求。于是,得力决定进军专业门槛高、技术壁垒深的打印机产业。经过数年的科研攻坚,得力成功研发出首台激光工程机,并在随后几年内,发展成为国内唯一一家同时掌握激光、喷墨打印核心技术研发、生产能力的企业。这一跨越不仅展现了得力公司在科技创新方面的决心和毅力,也为其在电子行业树立了新的里程碑。

Allen Avionics Inc公司的发展小趣事

得力公司在文具和打印机领域取得成功后,并未满足于此,而是继续寻求新的增长点。2016年,得力集团与余姚得力工具有限公司合资成立宁波得力工具有限公司,正式进入电动工具领域。得力凭借其在技术研发和品质控制方面的优势,迅速在电动工具市场占据一席之地。特别是其自主研发的“红芯”系列电动工具,凭借其高品质、高性价比的特点,赢得了用户的广泛好评。

Crouzet公司的发展小趣事

随着业务的不断发展,Crouzet公司于1989年和1992年分别成功兼并了法国Syreles公司及墨西哥Gordos公司。这一系列的兼并活动不仅增强了公司的实力,还进一步扩大了公司的业务范围。此后,Crouzet开始在全球范围内布局,陆续在美国、德国、英国、荷兰、比利时、瑞士、瑞典等国设立分公司,形成了一个覆盖全球的销售网络。

问答坊 | AI 解惑

电子工程师,别拿一分钱不当回事

一分钱,在现在物价飞涨的年代,早已经退出了货币交流的的历史舞台,成为财务意义上的最小计量单位。当年“我在马路边,捡到一分钱”的童谣,不会再发生了,一分钱,已经买不了任何东西。 一分钱,已经真的不值钱了吗?让我们来看年看电子物料的 ...…

查看全部问答>

用Nokia 3310 液晶自制温度计

转自:窗户纸 http://www.getproject.com.cn/post/95.html 想像一下,如果有这么一个“裸体”温度计,就放在自己家里的书柜上,等朋友来了,一定会吸引不少眼光,你也可以借机炫耀一番。 不过放在家里的话,有可能曝光率不够高,那我们就随身携 ...…

查看全部问答>

了解工业传感器的高手请进

    小弟最近在做一个课题,需要了解一些工业传感器,请各位高手列一些传感器型号出来。     具体要求:         1、单个价位在250元以下。         2、工业 ...…

查看全部问答>

有需要JLINK的吗 ?

65元一个 http://item.taobao.com/item_detail.jhtml?item_id=76d334109aebd88799ad63cdbcce7d08&x_id=db2…

查看全部问答>

VC#智能设备应用程序如何能使用vc2005开发的智能设备ocx? 高手指点

VC#智能设备应用程序如何能使用vc2005开发的智能设备ocx? 高手指点…

查看全部问答>

EVC 中选择默认设备下拉菜单选项中只有Emulator没有Device

以前写的程序在PPC 2003中模拟,现在更换了设备,新设备系统是WinCE .net 5.0 ,编译时选择STANDARDSDK ,Win32(WCE ARMV4)Release可是Select default device选项中只有STANDARDSDK Emulator,没有device选择,新设备可以和PC机同步,我想编译后 ...…

查看全部问答>

发个牢骚!107的net管脚配置太分散了

                                 最近想用一下以太网,使用107时发现,107的net管脚配置太分散了,光发送脚就占一个串口,can、spi,幸好接收管脚还 ...…

查看全部问答>

【问TI】cc2500属于zigbee范凑吗,用的那个协议栈,zigbee2006协议栈在其上适不适用

  如题,没什么说的,随便问问,我看ez430用的好像不是zigbee协议栈来的,所以咨询下。…

查看全部问答>

大量闲置书籍,或许有你想要,两块板子。

书籍太多,看不过来,整理一些出掉。[霸王条款:]仅限北京当面交易,到昌平线地铁沙河站取,不快递(1. 书籍太重,2. (即使你买一本)本人懒,没时间发)。 500页以下10元一本,500页以上的15元一本。部分书籍可商议。 买2本430的书籍可送430(f ...…

查看全部问答>

【英雄帖】【急!!】基于msp430g2553+qc12864b串行显示问题

#include #include\"LCD12864P.h\" void main() {         WDTCTL = WDTPW + WDTHOLD;         Ini_Lcd();            lcd_pos(1,0); &n ...…

查看全部问答>