一、使用proteus绘制简单的电路图,用于后续仿真
二、编写程序
/********************************************************************************************************************
---- @Project: Independent-KEY
---- @File: main.c
---- @Edit: ZHQ
---- @Version: V1.0
---- @CreationTime: 20200508
---- @ModifiedTime: 20200508
---- @Description: 两个独立按键S1和S2,S1键作为加键。S2键做为减键。每按一次S1键则被设置参数uiSetNumber自加1。如果按住S1键不松手超过1秒钟,被设置参数uiSetNumber以不断变快的时间间隔往上自加1,这个称为加速触发的功能,直到到达极限值,则以固定的速度加1,这个过程叫匀速。S2作为减法按键,每触发一次,uiSetNumber就减1,其加速和匀速触发功能跟S1按键一样。当被设置参数uiSetNumber小于500的时候,LED灯灭;当大于或者等于500的时候,LED灯亮。需要注意的是:
---- 第一步:每次按下去触发一次单击按键,如果按下去到松手的时间不超过1秒,则不会进入连续加速触发模式。
---- 第二步:如果按下去不松手的时间超过1秒,则进入连续加速触发模式。按键触发节奏不断加快,蜂鸣器鸣叫的节奏也不断加快。直到它们都到达一个极限值,然后以此极限值间隔匀速触发。在刚开始加速的时候,按键触发与蜂鸣器触发的步骤是一致的,等它们任意一个达到极限值的时候,急促的声音跟按键的触发不一致,并不是蜂鸣器每叫一次,按键就触发一次。实际上加速到最后,按键触发的速度远远比蜂鸣器的触发速度快。
---- 单片机:AT89C52
********************************************************************************************************************/
#include "reg52.h"
/*——————宏定义——————*/
#define FOSC 11059200L
#define T1MS (65536-FOSC/12/1000) /*1ms timer calculation method in 12Tmode*/
#define const_voice_short 80 /*蜂鸣器短叫的持续时间*/
#define const_key_time1 60 /*按键去抖动延时的时间*/
#define const_key_time2 60 /*按键去抖动延时的时间*/
#define const_time_1s 800 /*1秒钟的时间需要的定时中断次数*/
#define const_initial_set 480 /*连续触发模式的时候,按键刚开始的间隔触发时间*/
#define const_min_level 90 /*连续触发模式的时候,按键经过加速后,如果一旦发现小于这个值,则直接变到最后的间隔触发时间*/
#define const_sub_dt 30 /*按键的"加速度",相当于按键间隔时间每次的变化量*/
#define const_last_min_set 15 /*连续触发模式的时候,按键经过加速后,最后的间隔触发时间*/
#define const_syn_min_level 90 /*产生同步声音的最小阀值 这个时间必须要比蜂鸣器的时间略长一点。*/
/*——————变量函数定义及声明——————*/
/*定义按键S1*/
sbit Key_S1 = P0^0;
/*定义按键S2*/
sbit Key_S2 = P0^1;
/*定义蜂鸣器*/
sbit BUZZER = P2^7;
/*定义LED*/
sbit LED = P3^5;
unsigned char ucKeySec = 0; /*被触发的按键编号*/
unsigned int uiKeyTimeCnt1 = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock1 = 0; /*按键触发后自锁的变量标志*/
unsigned int uiKeyCtntyCnt1 = 0; /*按键连续触发的间隔延时计数器*/
unsigned int uiSynCtntyCnt1 = 0; /*产生按键同步声音的计数器*/
unsigned int uiCtntyTimeSet1 = const_initial_set; /*按键每次触发的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned int uiCtntySynSet1 = const_initial_set;/*同步声音的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned char ucCtntyFlag1 = 0; /*是否处于连续加速触发模式的标志位*/
unsigned int uiKeyTimeCnt2 = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock2 = 0; /*按键触发后自锁的变量标志*/
unsigned int uiKeyCtntyCnt2 = 0; /*按键连续触发的间隔延时计数器*/
unsigned int uiSynCtntyCnt2 = 0; /*产生按键同步声音的计数器*/
unsigned int uiCtntyTimeSet2 = const_initial_set; /*按键每次触发的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned int uiCtntySynSet2 = const_initial_set;/*同步声音的时间间隔,这数值不断变小,导致速度不断加快*/
unsigned char ucCtntyFlag2 = 0; /*是否处于连续加速触发模式的标志位*/
unsigned int uiVoiceCnt = 0; /*蜂鸣器鸣叫的持续时间计数器*/
unsigned int uiSetNumber = 0; /*设置的数据*/
/**
* @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)
{
ET0 = 1;/*允许定时中断*/
TR0 = 1;/*启动定时中断*/
EA = 1;/*开总中断*/
}
/**
* @brief 初始化函数
* @param 无
* @retval 初始化单片机
**/
void Init(void)
{
BUZZER = 1;
LED = 0;
Init_T0();
}
/**
* @brief 扫描按键函数
* @param 无
* @retval 独立按键连续加速扫描的过程:
* 第一步:每次按下去触发一次单击按键,如果按下去到松手的时间不超过1秒,则不会进入连续加速触发模式。
* 第二步:如果按下去不松手的时间超过1秒,则进入连续加速触发模式。按键触发节奏不断加快,蜂鸣器鸣叫的节奏
* 也不断加快。直到它们都到达一个极限值,然后以此极限值间隔匀速触发。在刚开始加速的时候,按键触发与
* 蜂鸣器触发的步骤是一致的,等它们任意一个达到极限值的时候,急促的声音跟按键的触发不一致,并不是
* 蜂鸣器每叫一次,按键就触发一次。实际上加速到最后,按键触发的速度远远比蜂鸣器的触发速度快。
**/
void Key_Scan(void)
{
/*扫描S1*/
if(Key_S1 == 1) /*如果按键没有被按下(高电平),将一些标志位及时清零*/
{
ucKeyLock1 = 0;/*自锁标志位清0*/
uiKeyTimeCnt1 = 0;/*按键去抖动延时计数器清零*/
uiKeyCtntyCnt1 = 0; /*按键连续加速的时间间隔延时计数器清零*/
uiSynCtntyCnt1 = 0; /*蜂鸣器连续加速的时间间隔延时计数器清零*/
uiCtntyTimeSet1 = const_initial_set; /*按键每次触发的时间间隔初始值,这数值不断变小,导致速度不断加快*/
uiCtntySynSet1 = const_initial_set; /*同步声音的时间间隔初始值,这数值不断变小,导致鸣叫的节奏不断加快*/
}
else if(ucKeyLock1 == 0) /*如果有按键按下,且是第一次按下*/
{
uiKeyTimeCnt1 ++;
if(uiKeyTimeCnt1 > const_key_time1)/*判定按下*/
{
uiKeyTimeCnt1 = 0;
ucKeyLock1 = 1;
ucCtntyFlag1 = 0; /*连续加速触发模式标志位 0代表单击 1代表连续加速触发*/
ucKeySec = 1; /*触发S1*/
}
}
else if(uiKeyTimeCnt1 < const_time_1s)/*按键已按下,按键去抖动延时计数器自增到1s*/
{
uiKeyTimeCnt1 ++;
}
else/*按住累加到1秒后仍然不放手,这个时候进入有节奏的连续触发*/
{
uiKeyCtntyCnt1 ++;/*连续触发延时计数器累加*/
if(uiKeyCtntyCnt1 > uiCtntyTimeSet1)/*按住没松手,每隔一段uiCtntyTimeSet1时间按键就触发一次,而且uiCtntyTimeSet1不断减小,速度就越来越快*/
{
if(uiCtntyTimeSet1 > const_min_level)
{
/*uiCtntyTimeSet1不断减小,速度就越来越快*/
uiCtntyTimeSet1 = uiCtntyTimeSet1 - const_sub_dt;
}
else
{
/*达到极限值,则稳定为固定值*/
uiCtntyTimeSet1 = const_last_min_set;
}
uiKeyCtntyCnt1 = 0;
ucCtntyFlag1 = 1; /*进入连续加速触发模式*/
ucKeySec = 1; /*触发S1*/
}
uiSynCtntyCnt1 ++; /*蜂鸣器连续触发延时计数器累加*/
if(uiSynCtntyCnt1 > uiCtntySynSet1) /*按住没松手,每隔一段uiCtntySynSet1时间蜂鸣器就触发一次,而且uiCtntySynSet1不断减小,鸣叫的节奏就越来越快*/
{
uiCtntySynSet1 = uiCtntySynSet1 - const_sub_dt;
if(uiCtntySynSet1 < const_syn_min_level)
{
uiCtntySynSet1 = const_syn_min_level;
}
uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/
uiSynCtntyCnt1 = 0;
}
}
/*扫描S2*/
if(Key_S2 == 1) /*如果按键没有被按下(高电平),将一些标志位及时清零*/
{
ucKeyLock2 = 0;/*自锁标志位清0*/
uiKeyTimeCnt2 = 0;/*按键去抖动延时计数器清零*/
uiKeyCtntyCnt2 = 0; /*按键连续加速的时间间隔延时计数器清零*/
uiSynCtntyCnt2 = 0; /*蜂鸣器连续加速的时间间隔延时计数器清零*/
uiCtntyTimeSet2 = const_initial_set; /*按键每次触发的时间间隔初始值,这数值不断变小,导致速度不断加快*/
uiCtntySynSet2 = const_initial_set; /*同步声音的时间间隔初始值,这数值不断变小,导致鸣叫的节奏不断加快*/
}
else if(ucKeyLock2 == 0) /*如果有按键按下,且是第一次按下*/
{
uiKeyTimeCnt2 ++;
if(uiKeyTimeCnt2 > const_key_time2)/*判定按下*/
{
uiKeyTimeCnt2 = 0;
ucKeyLock2 = 1;
ucCtntyFlag2 = 0; /*连续加速触发模式标志位 0代表单击 1代表连续加速触发*/
ucKeySec = 2; /*触发S2*/
}
}
else if(uiKeyTimeCnt2 < const_time_1s)/*按键已按下,按键去抖动延时计数器自增到1s*/
{
uiKeyTimeCnt2 ++;
}
else/*按住累加到1秒后仍然不放手,这个时候进入有节奏的连续触发*/
{
uiKeyCtntyCnt2 ++;/*连续触发延时计数器累加*/
if(uiKeyCtntyCnt2 > uiCtntyTimeSet2)/*按住没松手,每隔一段uiCtntyTimeSet1时间按键就触发一次,而且uiCtntyTimeSet2不断减小,速度就越来越快*/
{
if(uiCtntyTimeSet2 > const_min_level)
{
/*uiCtntyTimeSet1不断减小,速度就越来越快*/
uiCtntyTimeSet2 = uiCtntyTimeSet2 - const_sub_dt;
}
else
{
/*达到极限值,则稳定为固定值*/
uiCtntyTimeSet2 = const_last_min_set;
}
uiKeyCtntyCnt2 = 0;
ucCtntyFlag2 = 1; /*进入连续加速触发模式*/
ucKeySec = 2; /*触发S2*/
}
uiSynCtntyCnt2 ++; /*蜂鸣器连续触发延时计数器累加*/
if(uiSynCtntyCnt2 > uiCtntySynSet2) /*按住没松手,每隔一段uiCtntySynSet2时间蜂鸣器就触发一次,而且uiCtntySynSet2不断减小,鸣叫的节奏就越来越快*/
{
uiCtntySynSet2 = uiCtntySynSet2 - const_sub_dt;
if(uiCtntySynSet2 < const_syn_min_level)
{
uiCtntySynSet2 = const_syn_min_level;
}
uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/
uiSynCtntyCnt2 = 0;
}
}
}
/**
* @brief 按键服务函数
* @param 无
* @retval 根据扫描得到的值,进行数据处理
**/
void key_Service(void)
{
switch(ucKeySec)
{
case 1: /*S1,连续加*/
uiSetNumber++;/*被设置的参数连续往上加*/
if(uiSetNumber > 1000)/*最大1000*/
{
uiSetNumber = 1000;
}
if(ucCtntyFlag1 == 0) /*如果是在单击按键的情况下,则蜂鸣器鸣叫,否则蜂鸣器在按键扫描key_scan里鸣叫*/
{
uiVoiceCnt = const_voice_short; /*蜂鸣器短叫*/
}
ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/
break;
case 2: /*S2,连续减*/
uiSetNumber--;/*被设置的参数连续往下减*/
if(uiSetNumber > 1000)/*最小0,0 - 1 = 0xff > 1000*/
{
uiSetNumber = 0;
}
if(ucCtntyFlag2 == 0) /*如果是在单击按键的情况下,则蜂鸣器鸣叫,否则蜂鸣器在按键扫描key_scan里鸣叫*/
{
uiVoiceCnt = const_voice_short; /*蜂鸣器短叫*/
}
ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/
break;
}
}
/**
* @brief LED函数
* @param 无
* @retval 控制LED亮灭
**/
void Led_Run(void) /*led灯的应用程序*/
{
if(uiSetNumber < 500) /*如果被设置的参数uiSetNumber小于500,LED灯则灭。否则亮。*/
{
LED = 0; /*灭*/
}
else
{
LED = 1; /*亮*/
}
}
/**
* @brief 定时器0中断函数
* @param 无
* @retval 无
**/
void ISR_T0(void) interrupt 1
{
TF0 = 0; /*清除中断标志*/
TR0 = 0; /*关中断*/
/*扫描按键*/
Key_Scan();
if(0 != uiVoiceCnt)
{
uiVoiceCnt --;
BUZZER = 0;
}
else
{
BUZZER = 1;
}
TL0 = T1MS; /*initial timer0 low byte*/
TH0 = T1MS >> 8; /*initial timer0 high byte*/
TR0 = 1; /*开中断*/
}
/**
* @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 实现LED灯闪烁 **/ void main() { /*单片机初始化*/ Init(); /*延时,延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定*/ Delay_Long(100); /*单片机外围初始化*/ Init_Peripheral(); while(1) { /*按键服务函数*/ key_Service(); /*LED函数*/ Led_Run(); } } 注:编程过程中遇到个小插曲,有个“>”写成了“<”。这种问题编译器不会报错,但现象就是不对,很多这种小细节,往往能影响到大局。 三、仿真实现
上一篇:51单片机实现矩阵键盘的单个触发
下一篇:51单片机实现按住一个独立按键不松手的连续步进触发
推荐阅读
史海拾趣
为了进一步扩大市场份额,Edcon Components Netherlands Cv开始积极拓展国际市场。公司通过对不同国家和地区的市场进行深入分析,制定了精准的市场拓展策略。通过与当地经销商建立合作关系,Edcon的产品逐渐进入国际市场,并在多个国家和地区取得了成功。国际市场的拓展不仅为公司带来了更多的商机,也提升了公司的品牌影响力。
品质是ABECO的生命线。公司始终坚持严格的质量管理体系,从原材料的采购到生产过程的控制,再到产品的检测和包装,每一个环节都严格把关。此外,公司还定期举行质量培训活动,提高员工的质量意识。这种对品质的执着追求,使得ABECO的产品在市场上始终保持着良好的口碑和竞争力。
随着公司规模的扩大和市场份额的提升,Bce Sud开始实施国际化战略。公司先后在多个国家和地区设立了研发中心和销售网络,进一步扩大了市场份额。通过与国际知名企业的合作与交流,Bce Sud不断提升自身的技术水平和国际竞争力。
在快速发展的同时,Bce Sud始终关注企业社会责任和可持续发展。公司积极参与环保、公益等活动,致力于为社会做出贡献。同时,公司还注重员工的培训与发展,为员工提供良好的工作环境和职业发展机会。这些举措不仅提升了公司的社会形象,也为公司的长远发展奠定了坚实基础。
这些故事基于一般的电子行业公司成长经历构建,旨在展示一个虚构的电子行业公司如何从初创走向成功的过程。虽然故事中的公司名称和具体细节是虚构的,但其中的发展逻辑和经验教训对于现实中的电子行业公司来说仍具有一定的参考价值。
随着全球电子市场的不断扩大,Alpha (Taiwan)公司积极寻求国际合作,拓宽市场渠道。公司与多家国际知名电子企业建立了战略合作关系,共同研发新产品,开拓新市场。此外,公司还积极参加国际电子展会,展示公司的最新技术和产品,吸引更多的潜在客户。这些国际合作的开展,不仅提升了公司的国际影响力,也为公司的长远发展注入了新的动力。
在电子产品市场竞争激烈的背景下,Alpha (Taiwan)公司始终坚持品质至上的原则。公司建立了严格的质量管理体系,从原材料采购到生产流程,再到产品出厂,每一个环节都进行严格把控。同时,公司还定期对员工进行品质意识培训,确保每一位员工都能充分认识到品质对于公司发展的重要性。正是凭借这种对品质的执着追求,Alpha (Taiwan)公司的电子产品在市场上赢得了良好的口碑,赢得了众多客户的信赖。
DCDC的意思是直流变(到)直流(不同直流电源值的转换),只要符合这个定义都可以叫DCDC转换器,包括LDO。但是一般的说法是把直流变(到)直流由开关方式实现的器件叫DCDC。 LDO是低压降的意思,这有一段说明:低压降(LDO ...… 查看全部问答∨ |
|
本人搜集到的一篇很好的文章,因此转载给各位大虾,希望对工程师们有所帮助: 何靠与电打交道来谋生的人很快都会对任何“带电”的物体生出理性的敬意,哪怕是“带电”的机会很小。然而,需要按时完成一项工作或者使某个关键设备恢复联机的紧迫压力 ...… 查看全部问答∨ |
|
error C2065: \'GetRunningObjectTable\' : undeclared identifier error C2065: \'CreateItemMoniker\' : undeclared identifier 我用的是EVC 4.0+SP4… 查看全部问答∨ |
|
STM32的驱动库好用吗?效率高吗?优化的吗?准备上STM32 N多年没买过开发板了,也没用过仿真器了。都是用软件编译调试好,直接ISP,然后通过串口命令开启调试信息的输出。 昨天买了块STM32F103全功能型开发板,他们的办事效率真低(深圳到广州通常当 ...… 查看全部问答∨ |
求IAR Embedded Workbench for MCS-51 完整版 各位高手,小弟求IAR Embedded Workbench for MCS-51完整版,有哪位高人有,能否分享一下。我的邮箱jinghongchen@126.com… 查看全部问答∨ |