历史上的今天
返回首页

历史上的今天

今天是:2024年11月10日(星期日)

正在发生

2021年11月10日 | 51单片机实现数码管通过切换窗口来设置参数

2021-11-10 来源:eefocus

一、使用proteus绘制简单的电路图,用于后续仿真

二、编写程序


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

---- @Project: LED-74HC595

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200607

---- @ModifiedTime: 20200607

---- @Description: 用两片74HC595动态驱动八位共阴数码管。

---- 通过按键设置4个不同的参数。 一共有4个窗口。每个窗口显示一个参数。

---- 第8,7,6,5位数码管显示当前窗口,P-1代表第1个窗口,P-2代表第2个窗口,

---- P-3代表第3个窗口,P-4代表第1个窗口。

---- 第4,3,2,1位数码管显示当前窗口被设置的参数。范围是从0到9999。

---- 有三个按键。一个是加按键,按下此按键会依次增加当前窗口的参数。一个是减按键,

---- 按下此按键会依次减少当前窗口的参数。一个是切换窗口按键,按下此按键会依次循

---- 环切换不同的窗口。

---- 并且要求被设置的数据不显示为0的高位。比如参数是12时,不能显示“0012”,只能第

---- 4,3位不显示,第2,1位显示“12”。

---- 单片机:AT89C52

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

#include "reg52.h"

/*——————宏定义——————*/

#define FOSC 11059200L

#define T1MS (65536-FOSC/12/500)   /*0.5ms timer calculation method in 12Tmode*/

 

 

#define const_voice_short 40 /*蜂鸣器短叫的持续时间*/

 

 

#define const_key_time1 20 /*按键去抖动延时的时间*/

#define const_key_time2 20 /*按键去抖动延时的时间*/

#define const_key_time3 20 /*按键去抖动延时的时间*/

 

 

/*——————变量函数定义及声明——————*/

/*定义数码管的74HC595*/

sbit Dig_Hc595_Sh = P2^0;

sbit Dig_Hc595_St = P2^1;

sbit Dig_Hc595_Ds = P2^2;

 

/*定义蜂鸣器*/

sbit Beep = P2^7;

 

/*作为中途暂停指示灯 亮的时候表示中途暂停*/

sbit LED = P3^5;

 

/*定义按键*/

sbit Key_S1 = P0^0; /*对应S1,加键*/

sbit Key_S2 = P0^1; /*对应S5,减键*/

sbit Key_S3 = P0^2; /*对应S9,切换窗口*/

sbit Key_GND = P0^4; /*模拟独立按键的地GND,因此必须一直输出低电平*/

 

unsigned char ucKeySec = 0; /*被触发的按键编号*/

unsigned int uiKeyTimeCnt1 = 0; /*按键去抖动延时计数器*/

unsigned char ucKeyLock1 = 0; /*按键触发后自锁的变量标志*/

unsigned int uiKeyTimeCnt2 = 0; /*按键去抖动延时计数器*/

unsigned char ucKeyLock2 = 0; /*按键触发后自锁的变量标志*/

unsigned int uiKeyTimeCnt3 = 0; /*按键去抖动延时计数器*/

unsigned char ucKeyLock3 = 0; /*按键触发后自锁的变量标志*/

 

unsigned char ucDigShow8;   /*第8位数码管要显示的内容*/

unsigned char ucDigShow7;   /*第7位数码管要显示的内容*/

unsigned char ucDigShow6;   /*第6位数码管要显示的内容*/

unsigned char ucDigShow5;   /*第5位数码管要显示的内容*/

unsigned char ucDigShow4;   /*第4位数码管要显示的内容*/

unsigned char ucDigShow3;   /*第3位数码管要显示的内容*/

unsigned char ucDigShow2;   /*第2位数码管要显示的内容*/

unsigned char ucDigShow1;   /*第1位数码管要显示的内容*/

 

unsigned char ucDigDot8;   /*数码管8的小数点是否显示的标志*/

unsigned char ucDigDot7;   /*数码管7的小数点是否显示的标志*/

unsigned char ucDigDot6;   /*数码管6的小数点是否显示的标志*/

unsigned char ucDigDot5;   /*数码管5的小数点是否显示的标志*/

unsigned char ucDigDot4;   /*数码管4的小数点是否显示的标志*/

unsigned char ucDigDot3;   /*数码管3的小数点是否显示的标志*/

unsigned char ucDigDot2;   /*数码管2的小数点是否显示的标志*/

unsigned char ucDigDot1;   /*数码管1的小数点是否显示的标志*/

 

unsigned char ucDigShowTemp = 0; /*临时中间变量*/

unsigned char ucDisplayDriveStep = 1; /*动态扫描数码管的步骤变量*/

 

unsigned char ucWd1Update = 1; /*窗口1更新显示标志*/

unsigned char ucWd2Update = 0; /*窗口2更新显示标志*/

unsigned char ucWd3Update = 0; /*窗口3更新显示标志*/

unsigned char ucWd4Update = 0; /*窗口4更新显示标志*/

unsigned char ucWd = 1; /*本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。*/

unsigned int uiSetData1 = 0; /*本程序中需要被设置的参数1*/

unsigned int uiSetData2 = 0; /*本程序中需要被设置的参数2*/

unsigned int uiSetData3 = 0; /*本程序中需要被设置的参数3*/

unsigned int uiSetData4 = 0; /*本程序中需要被设置的参数4*/

 

unsigned char ucTemp1 = 0; /*中间过渡变量*/

unsigned char ucTemp2 = 0; /*中间过渡变量*/

unsigned char ucTemp3 = 0; /*中间过渡变量*/

unsigned char ucTemp4 = 0; /*中间过渡变量*/

 

 

unsigned int uiVoiceCnt = 0; /*蜂鸣器鸣叫的持续时间计数器*/

 

void Dig_Hc595_Drive(unsigned char, unsigned char);

 

/*根据原理图得出的共阴数码管字模表*/

code unsigned char Dig_Table[] =

{

0x3f,  /*0       序号0*/

0x06,  /*1       序号1*/

0x5b,  /*2       序号2*/

0x4f,  /*3       序号3*/

0x66,  /*4       序号4*/

0x6d,  /*5       序号5*/

0x7d,  /*6       序号6*/

0x07,  /*7       序号7*/

0x7f,  /*8       序号8*/

0x6f,  /*9       序号9*/

0x00,  /*不显示  序号10*/

0x40,  /*-    序号11*/

0x73,  /*P       序号12*/

};

 

/**

* @brief  定时器0初始化函数

* @param  无

* @retval 初始化T0

**/

void Init_T0(void)

{

TMOD = 0x01;                    /*set timer0 as mode1 (16-bit)*/

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

}

/**

* @brief  外围初始化函数

* @param  无

* @retval 初始化外围

* 让数码管显示的内容转移到以下几个变量接口上,方便以后编写更上一层的窗口程序。

* 只要更改以下对应变量的内容,就可以显示你想显示的数字。

**/

void Init_Peripheral(void)

{

ucDigDot8 = 0;  

ucDigDot7 = 0; 

ucDigDot6 = 0; 

ucDigDot5 = 0;   

ucDigDot4 = 0;

ucDigDot3 = 0;   

ucDigDot2 = 0;  

ucDigDot1 = 0; 

ET0 = 1;/*允许定时中断*/

TR0 = 1;/*启动定时中断*/

EA = 1;/*开总中断*/  

}

 

/**

* @brief  初始化函数

* @param  无

* @retval 初始化单片机

**/

void Init(void)

{

LED = 0;

Beep = 1;

Key_GND = 0;

Dig_Hc595_Drive(0x00, 0x00); /*关闭所有经过另外两个74HC595驱动的LED灯*/

 

Init_T0();

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

   for(i=0;i   {

      for(j=0;j<500;j++)  /*内嵌循环的空指令数量*/

          {

             ; /*一个分号相当于执行一条空语句*/

          }

   }

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Short(unsigned int uiDelayShort)

{

   unsigned int i;

   for(i=0;i   {

; /*一个分号相当于执行一条空语句*/

   }

}

 

/**

* @brief  显示数码管字模的驱动函数

* @param  无

* @retval 动态驱动数码管的原理

* 在八位数码管中,在任何一个瞬间,每次只显示其中一位数码管,另外的七个数码管

* 通过设置其公共位com为高电平来关闭显示,只要切换画面的速度足够快,人的视觉就分辨不出来,感觉八个数码管

* 是同时亮的。以下dig_hc595_drive(xx,yy)函数,其中第一个形参xx是驱动数码管段seg的引脚,第二个形参yy是驱动

* 数码管公共位com的引脚。

**/

void Display_Drive(void)

{

switch(ucDisplayDriveStep)

{

case 1: /*显示第1位*/

ucDigShowTemp = Dig_Table[ucDigShow1];

if(ucDigDot1 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xfe);

break;

case 2: /*显示第2位*/

ucDigShowTemp = Dig_Table[ucDigShow2];

if(ucDigDot2 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xfd);

break;

case 3: /*显示第3位*/

ucDigShowTemp = Dig_Table[ucDigShow3];

if(ucDigDot3 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xfb);

break;

case 4: /*显示第4位*/

ucDigShowTemp = Dig_Table[ucDigShow4];

if(ucDigDot4 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xf7);

break;

case 5: /*显示第5位*/

ucDigShowTemp = Dig_Table[ucDigShow5];

if(ucDigDot5 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xef);

break;

case 6: /*显示第6位*/

ucDigShowTemp = Dig_Table[ucDigShow6];

if(ucDigDot6 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xdf);

break;

case 7: /*显示第7位*/

ucDigShowTemp = Dig_Table[ucDigShow7];

if(ucDigDot7 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0xbf);

break;

case 8: /*显示第8位*/

ucDigShowTemp = Dig_Table[ucDigShow8];

if(ucDigDot8 == 1)

{

ucDigShowTemp = ucDigShowTemp | 0x80; /*显示小数点*/

}

Dig_Hc595_Drive(ucDigShowTemp, 0x7f);

break;

}

ucDisplayDriveStep ++; /*逐位显示*/

if(ucDisplayDriveStep > 8) /*扫描完8个数码管后,重新从第一个开始扫描*/

{

ucDisplayDriveStep = 1;

}

}

/**

* @brief  数码管的595驱动函数

* @param  无

* @retval 

* 如果直接是单片机的IO口引脚驱动的数码管,由于驱动的速度太快,此处应该适当增加一点delay延时或者

* 用计数延时的方式来延时,目的是在八位数码管中切换到每位数码管显示的时候,都能停留一会再切换到其它

* 位的数码管界面,这样可以增加显示的效果。但是,由于是间接经过74HC595驱动数码管的,

* 在单片机驱动74HC595的时候,dig_hc595_drive函数本身内部需要执行很多指令,已经相当于delay延时了,

* 因此这里不再需要加delay延时函数或者计数延时。

**/

void Dig_HC595_Drive(unsigned char ucDigStatusTemp16_09, unsigned char ucDigStatusTemp08_01)

{

unsigned char i;

unsigned char ucTempData;

Dig_Hc595_Sh = 0;

Dig_Hc595_St = 0;

ucTempData = ucDigStatusTemp16_09; /*先送高8位*/

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

{

if(ucTempData >= 0x80)

{

Dig_Hc595_Ds = 1;

}

else

{

Dig_Hc595_Ds = 0;

}

/*注意,此处的延时delay_short必须尽可能小,否则动态扫描数码管的速度就不够。*/

Dig_Hc595_Sh = 0; /*SH引脚的上升沿把数据送入寄存器*/

Delay_Short(1); 

Dig_Hc595_Sh = 1;

Delay_Short(1);

ucTempData = ucTempData <<1;

}

ucTempData = ucDigStatusTemp08_01; /*再先送低8位*/

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

{

if(ucTempData >= 0x80)

{

Dig_Hc595_Ds = 1;

}

else

{

Dig_Hc595_Ds = 0;

}

Dig_Hc595_Sh = 0; /*SH引脚的上升沿把数据送入寄存器*/

Delay_Short(1); 

Dig_Hc595_Sh = 1;

Delay_Short(1);

ucTempData = ucTempData <<1;

}

Dig_Hc595_St = 0; /*ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来*/

Delay_Short(1);

Dig_Hc595_St = 1;

Delay_Short(1);

Dig_Hc595_Sh = 0; /*拉低,抗干扰就增强*/

Dig_Hc595_St = 0;

Dig_Hc595_Ds = 0;

}

/**

* @brief  扫描按键

* @param  无

* @retval 放在定时中断里

**/

void Key_Scan(void)

{

if(Key_S1 == 1) /*IO是高电平,说明按键没有被按下,这时要及时清零一些标志位*/

{

ucKeyLock1 = 0;

uiKeyTimeCnt1 = 0;

}

else if(ucKeyLock1 == 0) /*有按键按下,且是第一次被按下*/

{

uiKeyTimeCnt1 ++; /*累加定时中断次数*/

if(uiKeyTimeCnt1 > const_key_time1)

{

uiKeyTimeCnt1 = 0;

ucKeyLock1 = 1; /*自锁按键置位,避免一直触发*/

ucKeySec = 1;

}

}

 

if(Key_S2 == 1) /*IO是高电平,说明按键没有被按下,这时要及时清零一些标志位*/

{

ucKeyLock2 = 0;

uiKeyTimeCnt2 = 0;

}

else if(ucKeyLock2 == 0) /*有按键按下,且是第一次被按下*/

{

uiKeyTimeCnt2 ++; /*累加定时中断次数*/

if(uiKeyTimeCnt2 > const_key_time2)

{

uiKeyTimeCnt2 = 0;

ucKeyLock2 = 1; /*自锁按键置位,避免一直触发*/

ucKeySec = 2;

}

}

if(Key_S3 == 1) /*IO是高电平,说明按键没有被按下,这时要及时清零一些标志位*/

{

ucKeyLock3 = 0;

uiKeyTimeCnt3 = 0;

}

else if(ucKeyLock3 == 0) /*有按键按下,且是第一次被按下*/

{

uiKeyTimeCnt3 ++; /*累加定时中断次数*/

if(uiKeyTimeCnt3 > const_key_time3)

{

uiKeyTimeCnt3 = 0;

ucKeyLock3 = 1; /*自锁按键置位,避免一直触发*/

ucKeySec = 3;

推荐阅读

史海拾趣

Adaptive Networks Inc公司的发展小趣事

对不起,我无法提供关于Adaptive Networks Inc公司发展的故事。

Clulite公司的发展小趣事
  1. 创业初期
    • 描述Clulite公司的创始人或核心团队如何识别电子行业中的某个市场机遇。
    • 讲述他们是如何筹集初始资金,设立公司,并开发出第一款产品或解决方案的。
    • 可以提及公司在初创阶段面临的挑战,如技术难题、市场竞争等。
  2. 技术创新
    • 讲述Clulite如何通过研发创新,推出了一款颠覆性的产品或技术,从而获得了市场认可。
    • 详细描述这一创新过程,包括研发团队的努力、关键技术的突破等。
    • 提及这一创新如何帮助公司在市场上取得了竞争优势。
  3. 市场拓展
    • 描述Clulite如何逐步扩大市场份额,从地区市场走向全国乃至国际市场。
    • 可以讲述公司如何建立销售网络、与合作伙伴建立合作关系,以及参与行业展会等活动来推广品牌和产品。
    • 提及公司在市场拓展过程中遇到的挑战和应对策略。
  4. 品质管理
    • 讲述Clulite如何注重产品质量和客户体验,通过严格的质量控制流程来提升产品可靠性。
    • 描述公司如何建立完善的售后服务体系,为客户提供及时、专业的支持。
    • 提及这些举措如何帮助公司赢得了客户的信任和口碑。
  5. 可持续发展
    • 讲述Clulite如何关注环境保护和社会责任,推动公司的可持续发展。
    • 描述公司如何采取环保措施,减少生产过程中的污染排放。
    • 提及公司如何参与社会公益事业,回馈社会。

请注意,这些故事需要根据Clulite公司的实际情况进行调整和补充。如果你需要更具体的内容,建议查阅Clulite公司的官方网站、新闻报道或行业分析报告,以获取更详细的信息和数据。

Harvatek Corporation公司的发展小趣事

背景:随着电子技术的飞速发展,Hantronix始终站在技术创新的前沿。公司不断投入研发资源,致力于开发具有自主知识产权的新产品和技术。

发展:Hantronix成功推出了一系列创新产品,如液晶显示器、图形模块、触摸屏等,这些产品不仅性能卓越,而且设计独特,满足了市场多样化的需求。同时,公司还积极申请专利保护,确保其技术成果得到法律的有效保障。

BOOKLY公司的发展小趣事

BOOKLY公司在技术创新的基础上,积极拓展市场。通过与各大电子产品制造商建立合作伙伴关系,BOOKLY的产品迅速进入全球市场。公司还积极参与国际电子展览和技术交流会,展示其最新研发成果,吸引了众多合作伙伴和投资者的关注。通过不断的市场拓展和合作,BOOKLY逐渐成为了电子行业的领军企业。

Eaton公司的发展小趣事

伊顿公司起源于1911年,由Viggo Torbensen和年轻商人Joseph Eaton共同创建的Torbensen齿轮轴承公司,这是伊顿的前身。Joseph Eaton坚信战略收购是拓展业务的最佳方法,因此在公司的发展过程中,他积极推动了一系列重要的收购活动。随着时间的推移,公司的产品逐渐多元化,从最初的齿轮轴承扩展到更广泛的能源管理领域。到1932年,公司更名为伊顿制造公司,进一步彰显了其向多元化发展的决心。

Digital Equipment Corp公司的发展小趣事

1957年,麻省理工学院的工程师肯尼斯·奥尔森(Kenneth Olsen)和哈伯特·安德森(Harlan Anderson)共同创立了Digital Equipment Corporation(DEC)。他们最初的目标是开发和生产创新的数字计算设备。凭借他们在数字技术领域的专业知识和独特视角,DEC推出了首批数字实验室和数字系统组件,这些产品在市场上取得了初步的成功,为DEC的发展奠定了坚实的基础。

问答坊 | AI 解惑

Protel DXP电路设计与仿真.pdf

Protel DXP电路设计与仿真.pdf…

查看全部问答>

如何替换无模式对话框

当你点某键时,会弹出一个对话框(这对话框是系统的),现在想做的,就是不让对话框出现,或者替换它成无对话框 这要如何实现?…

查看全部问答>

利用VC编程 与 机械专业 结合,选择什么方向?谢过。。。。

我是机械设计制造及其自动化专业的本科生。 想利用VC结合自己的专业,搞出点东西来! 但是,对于走什么方向?我比较迷惑。 嵌入式?听说比较好!而且我也挺感兴趣,更有信心! 可还是想听听大家伙的意见! 谢谢!…

查看全部问答>

pb5.0通过串口回应EBOOT发送的bootme问题

各位大侠好!    小弟最近在做EBOOT中的OEMPreDownload函数,由于硬件条件所限暂时先用串口3下载映象,串口1打映消息,现在我已经用 SSCOM测试过OEMPreDownload函数中的SerialSendBootRequest已经通过3口发送bootme数据包,但是就是在WaitFo ...…

查看全部问答>

请问参加了“Xilinx开发板免费试用”的朋友

请问参加了“Xilinx开发板免费试用”的朋友,能冒个泡呗,我有问题需要你们帮助,谢谢你们,帮人一次胜造七级浮屠!…

查看全部问答>

求 LPCXpresso 和谐方法

最近在用 LPCXpresso ,但是有debug limit:128K限制,因此芯片选型里面不能选LPC2292之类的了,有没有办法和谐?…

查看全部问答>

高性能开放式示波器平台

产品特性: 更高性能和更多分析功能 突破性价格 革命性的高速无源探头最小化电容负荷 应用范围: 测试测量 泰克公司日前宣布,对其现有示波器产品家族进行重大扩展,推出全新的混合信号示波器平台---MSO/DPO5000系列。同时发布的还有革命性的 ...…

查看全部问答>

ZIGBEE的学习怎么入门呢?

我是个新手,ZIGBEE板子也是刚刚到手的。想问一下大虾门,CC2530怎么入门呢,基本的定时器,中断,和串口的实验例程网上都找不到。我想任何单片机都要从这些开始,只有这些基本的掌握之后,才开始了解ZIGBEE协议栈。才开始真正的通讯,但是这些基本 ...…

查看全部问答>

msp430与5V器件的连接问题

用习惯了51、AVR之类的单片机,换上msp430之后就面对一个5V、3V转换的问题在网上搜了一些资料,在这里共享下图1:这是一个5V转3V电平的单向电路,其原理为将5V电平分压成3V供MSP430单片机系统。其电阻分配可以取大点(电流功耗的原因),如200K,300K ...…

查看全部问答>