按键处理程序 C语言 单片机
自己写的按键单片机程序

自己写的按键单片机程序用4个按键来控制数码管显示的内容#include#define duan P0//段选#define wei P2//位选unsigned char code wei1[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选控制查表的方法控制unsigned char code duan1[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0 x71};//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码unsigned char ge,shi,bai,a,b;sbit key1=P1;sbit key2=P1 ;sbit key3=P1 ;sbit key4=P1 ;void keys();//按键函数void s(unsigned char xms);//延时函数void DigDisplay(); //动态显示函数void init(); //初始化函数void main(void){init(); while(1){DigDisplay();keys();} }void DigDisplay(){unsigned char i;unsigned int j;bai=a/100;shi=a%100/10;ge=a%10;i=0;wei = wei1[i];//发送位选duan = duan1[bai]; //发送段码j = 10;//扫描间隔时间设定while(j--);duan = 0x00; //消隐i++;wei = wei1[i];//发送位选duan = duan1[shi]; //发送段码j = 10;//扫描间隔时间设定while(j--);duan = 0x00; //消隐i++;wei = wei1[i];//发送位选duan = duan1[ge]; //发送段码j = 10;//扫描间隔时间设定while(j--);duan = 0x00; //消隐}void init() {key1=1;key2=1;key3=1;key4=1;TMOD=0X01;TH0=(65536-45872)/256;TL0=(65536-45872)%256;EA=1;ET0=1;}void s(unsigned char xms){unsigned char x,y;for(x=xms;x>0;x--)for(y=110;y>0;y--);}void times() interrupt 1{TH0=(65536-45872)/256;TL0=(65536-45872)%256;b++;if(b==20){b=0;a++;if(a==256){a=0;}}}voidkeys(){if(key1==0){s(10);if(key1==0){a++;TR0=0;if(a==256)a=0;while(!key1)Dig Display();}}if(key2==0){s(10);if(key2==0){TR0=0;if(a==0)a=256;a--。
从单片机初学者迈向单片机工程师----按键处理

从单片机初学者迈向单片机工程师----按键处理2009-11-24 11:25前些日子把自己以前下载的一些按键的资料好好看了下。
发现万变不离其中。
无非就是把以前延时消抖动改变为对按键进行计数,或者是状态的变化的判断。
这样的好处不言而喻,释放了MCU,能够有更多时间去处理其它任务。
而单片机初学者最容易犯的错误就是在这里。
按键按下?----> YES ----> 延时20MS ----> 按键按下?----> YES ----> 返回键值| N O | NO| |退出退出这是一个比较经典的处理模式,为什么这样说呢,因为大部分的单片机教材上面都是这样写的。
以至于很多初学者以为按键处理就是这个模式。
不得不说,现在的单片机教材优秀的太少,大部分都是抄来抄去。
最终受害的还是我们学习者。
可能要很久以后才会发现,原来自己走了这么长的时间的弯路。
下面贴一个很久以前在网上收集到的按键处理的资料。
理解了其中的精髓就会一通百通。
状态机是一个有向图形,由一组节点和一组相应的转移函数组成。
状态机通过响应一系列事件而“运行”。
每个事件都在属于“当前”节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。
函数返回“下一个”(也许是同一个)节点。
这些节点中至少有一个必须是终态。
当到达终态,状态机停止。
这一段抽象的数学定义,或许会晕倒一片人,但是我们能不能换一个说法来更好的理解状态机呢,学习方法中,我最推崇“类比", 因为天地一大宇宙,人身一小宇宙,天地间一切可类比。
就像电流与水流,电学与力学一样。
在此表弟我不才,也想对状态机类比一下。
其实在我看来,有限状态机就是一个人的悲喜剧,生命不息,状态不止。
在父母面前,他是一个好的儿子,他所做的事就是孝敬父母,在妻子面前他是一个好丈夫,呵护着自己的老婆,支撑着这个家,在儿女面前,他是一个好爸爸淳淳教导着自己的子女,在老板面前,他是一个好职员,他所做的是为公司的明天而打拼. 如此环环不息,直至生命的终结,没有人是不死的,状态机也一样(在此不考虑无限状态机). 此类比中的"好儿子“,"好丈夫","好爸爸" 就是一个人的不同的自我,在扮演着不同的角色,演绎着不同的故事,可以称之为“状态”,而“孝敬父母”“呵护老婆”“教导子女”则是在不同状态下的行为。
单片机按键程序(汇编)

;P0.0为键盘,P2.0为LED指示,按下LED亮,再按0.5秒,LED灭;00h为识别LED状态的标志位,当00H为1时LED亮,当00H为0时,LED灭。
初始化00H为0LED_OFF BIT P2.0K0 BIT P0.0LED_STATE EQU 00HORG 0000HSJMP MAINORG 0030HMAIN: CLR LED_STA TE ;清标志位START:JNB K0,LOOPSJMP START ;判断K0状态,若KO不为0,则继续检测K0状态,若k0为0,则跳到loopLOOP:CLR LED_OFFSETB LED_STATE ;点亮LED以及置标志位,CHECK1:LCALL DELAYJNB K0,CHECK1 ;若开关未弹起,则一直循环,直至开关弹起。
CHECK_LED_ON:LCALL DELAYJB K0,CHECK_LED_ON ;检查开关是否被按下,若未被按下则一直循环,若被按下,则判断标志位MOV C,LED_STATEJC CHECK_LED_OFF ;若标志位为1,则跳转到CHECK_LED_OFFCLR LED_OFFSETB LED_STATE ;若标志位为0,则点亮LED,同时置标志位为1CHECK2:LCALL DELAYJNB K0,CHECK2 ;检查开关是否被弹起,一直循环JMP CHECK_LED_ON ;开关弹起后,跳到CHECK_LED_ON,检查开关是否被按下CHECK_LED_OFF:JB K0,CHECK_LED_ONLCALL DELAYJB K0,CHECK_LED_ONLCALL DELAYJB K0,CHECK_LED_ONLCALL DELAYJB K0,CHECK_LED_ONLCALL DELAYJB K0,CHECK_LED_ONLCALL DELAYJB K0,CHECK_LED_ONLCALL DELAYJB K0,CHECK_LED_ON ;检查开关是否被按下0.5s,若中途弹起则跳转到CHECK_LED_ON。
单片机按键程序设计

单片机按键程序设计单片机按键的基本原理其实并不复杂。
通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。
在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。
在实际的按键程序设计中,有多种方式可以实现按键检测。
其中一种常见的方法是查询法。
这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。
以下是一个简单的查询法示例代码:```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void main(){while(1) //无限循环{if(key == 0) //如果按键按下,引脚为低电平{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;while(key == 0);//等待按键松开}}}```上述代码中,我们首先定义了按键连接的引脚`key`,然后在主函数的无限循环中不断检测按键引脚的状态。
当检测到按键按下时,执行相应的操作,并通过`while(key == 0)`等待按键松开。
除了查询法,还有中断法可以用于按键检测。
中断法的优点是能够及时响应按键动作,不会因为程序的其他操作而导致按键响应延迟。
```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void int0_init()//中断初始化函数{IT0 = 1; //下降沿触发中断EX0 = 1; //使能外部中断 0EA = 1; //开总中断}void int0() interrupt 0 //外部中断 0 服务函数{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;}void main(){int0_init();//初始化中断while(1);//无限循环,保持程序运行}```在上述代码中,我们首先在`int0_init` 函数中对中断进行了初始化设置,然后在`int0` 函数中编写了按键按下时的处理代码。
我的51单片机之 按键 的 C语言与汇编的编程

P1=0xFF; P3=0xFF; while(1) {
if(KINT0==0) {
LD1=0; } if(KINT1==0) {
LD2=0; } if(KT0==0) {
LD3=0; } if(KT1==0) {
LD4=0; } if(KA2==0) {
LD5=0;
} if(KA1==0) {
KINT0 EQU P3.2; KINT1 EQU P3.3; KT0 EQU P3.4; KT1 EQU P3.5; KA2 EQU P3.6; KA1 EQU P3.7; LD1 EQU P1.0; LD2 EQU P1.1; LD3 EQU P1.2; LD4 EQU P1.3; LD5 EQU P1.4; LD6 EQU P1.5;
LD6=0; } } }
四、独立按键汇编程序: ;**************************************************************** ;每个独立铵键用一只指示灯指示;按复位键可熄灭,made by luqichao ;**************************************************************** ORG 0000H AJMP MAIN ORG 0030H
//字形码:0--f 及小数点
unsigned char code AscLed[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
//
{ 0 , 1, 2 , 3 , 4 , 5, 6, 7, 8, 9 }
void main() {
start: LED2=0; //亮数码管 P3=0xFF; KH1=0; if(KL1==0){LEDCODE=AscLed[1];goto start;};//k1 if(KL2==0){LEDCODE=AscLed[2];goto start;};//k2 if(KL3==0){LEDCODE=AscLed[5];goto start;};//k5 KH2=0; if(KL1==0){LEDCODE=AscLed[3];goto start;};//k3 if(KL2==0){LEDCODE=AscLed[4];goto start;};//k4 if(KL3==0){LEDCODE=AscLed[6];goto start;};//k6 KH3=0; if(KL1==0){LEDCODE=AscLed[7];goto start;};//k7 if(KL2==0){LEDCODE=AscLed[8];goto start;};//k8 if(KL3==0){LEDCODE=AscLed[9];goto start;};//k9
按键处理程序C语言单片机

按键处理程序C语言单片机分享一种按键处理程序(用C)//头文件定义:Ustruct KEY{Uchar Val;#define Key_Model_C 0 //按键1值#define Key_AddVal_C 1 //按键2值Uint ScanOnTime;Uchar LongKeyState;Uchar LongKeyRestState;Uchar SetInRn;Uchar Model; //按键状态(模式)#define Off_C 0 //之前未按下#define On_C 1 //现按下#define Delay_C 2 //按键处理后标志}Key;//----------------定义两个IO输入口为按键入口--------------------//#define KeyMo_Bin (GPIOB->IDR.Bit.B5)#define KeyAdd_Bin (GPIOB->IDR.Bit.B6)/*===================================== ==========================*/GPIO_Init(GPIO_Pin_5|GPIO_Pin_6,GPIO_Mode_In_PU_No_IT); //初始化为上拉输入无中断/*===================================== ==========================*///主程序大循环中每1毫秒扫描1次void KeyScan(void){if(Key.LongKeyRestState == 1) //长按键标志(复位处理长按键){if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1)) //当两按键均抬起{if(++Key.ScanOnTime >= 130) //延时后复位{Key.LongKeyRestState=0;Key.Model=Delay_C;}}elseKey.ScanOnTime=0;return;}if(Key.Model == Off_C) //如果当前按键状态为未按下“Off_C”{if((KeyMo_Bin == 0) || (KeyAdd_Bin == 0))//按键1或按键2已按下(低有效){if(++Key.ScanOnTime >= 10) //当按下后自加1,加够10次即1ms*10=10ms去抖动{Key.ScanOnTime=0;if(KeyMo_Bin == 0) //如果按键1为0即按下{Key.Val=Key_Model_C; //付当键1值(看头文件定义)Key.Model=On_C; //置按键已按下标志}else if(KeyAdd_Bin == 0) //如果按键2为0即按下{Key.Val=Key_AddVal_C; //付当键2值(看头文件定义)Key.Model=On_C; //置按键已按下标志}BellOn(200); //蜂鸣器响}}elseKey.ScanOnTime=0; //清去抖延时计数值}else if(Key.Model == Delay_C) //如果当前按键状态为已按下且已处理“Delay_C”{if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1))//如果两按键均抬起{if(++Key.ScanOnTime >= 100) //延时100ms后复位按键状态为“Off_C”{Key.SetInRn=0;Key.ScanOnTime=0;Key.Model=Off_C;}}else //如果按键没有被抬起,对应上面if{if(++Key.ScanOnTime >= 1000) //延时1000ms后再复位按键状态为“Off_C”(为长按处理){Key.ScanOnTime=0;Key.Model=Off_C;}}}}//===================================== ========================================= ========void LoadCheckKeyRest(void){Key.LongKeyRestState=1;Key.ScanOnTime=0;}//===================================== ========================================= ========//处理相应按键(可250ms才调用一次)长按if(Key.Model == On_C) //按键状态为已按下{if(Key.Val == Key_Model_C) //是键1按下(看头文件定义){if(++Key.SetInRn >= 3) //连计3次数3秒后为长按键(对应上面,如果按下未抬起的话会延时1000ms){Key.SetInRn=0;LoadCheckKeyRest(); //调清长按处理BellOn(600); //蜂鸣器响//-----------长按需处理的内容-----下-----------//WorkStateBit.Bit.SettingMo=1;SetOverTime=0;SetMoRn=0;SetBak[0]=Rtc_InitDate.RTC_Year;SetBak[1]=Rtc_InitDate.RTC_Month;SetBak[2]=Rtc_InitDate.RTC_Date;SetBak[3]=Rtc_InitDate.RTC_WeekDay;SetBak[4]=Rtc_InitTime.RTC_Hours;SetBak[5]=Rtc_InitTime.RTC_Minutes;//-----------长按需处理的内容------上----------//Key.Model=Delay_C; //置按键模式为:已处理按键(看头文件定义)return;}}elseKey.SetInRn=0;Key.Model=Delay_C;}。
单片机c语言程序设计---矩阵式键盘实验报告

单片机c语言程序设计---矩阵式键盘实验报告课程名称:单片机c语言设计实验类型:设计型实验实验项目名称:矩阵式键盘实验一、实验目的和要求1.掌握矩阵式键盘结构2.掌握矩阵式键盘工作原理3.掌握矩阵式键盘的两种常用编程方法,即扫描法和反转法二、实验内容和原理实验1.矩阵式键盘实验功能:用数码管显示4*4矩阵式键盘的按键值,当K1按下后,数码管显示数字0,当K2按下后,显示为1,以此类推,当按下K16,显示F。
(1)硬件设计电路原理图如下仿真所需元器件(2)proteus仿真通过Keil编译后,利用protues软件进行仿真。
在protues ISIS 编译环境中绘制仿真电路图,将编译好的“xxx.hex”文件加入AT89C51。
启动仿真,观察仿真结果。
操作方完成矩阵式键盘实验。
具体包括绘制仿真电路图、编写c源程序(反转法和扫描法)、进行仿真并观察仿真结果,需要保存原理图截图,保存c源程序,总结观察的仿真结果。
完成思考题。
三、实验方法与实验步骤1.按照硬件设计在protues上按照所给硬件设计绘制电路图。
2.在keil上进行编译后生成“xxx.hex”文件。
3.编译好的“xxx.hex”文件加入AT89C51。
启动仿真,观察仿真结果。
四、实验结果与分析void Scan_line()//扫描行{Delay(10);//消抖switch ( P1 ){case 0x0e: i=1;break;case 0x0d: i=2;break;case 0x0b: i=3;break;case 0x07: i=4;break;default: i=0;//未按下break;}}void Scan_list()//扫描列{Delay(10);//消抖switch ( P1 ){case 0x70: j=1;break;case 0xb0: j=2;break;case 0xd0: j=3;break;case 0xe0: j=4;break;default: j=0;//未按下break;}}void Show_Key(){if( i != 0 && j != 0 ) P0=table[ ( i - 1 ) * 4 + j - 1 ];else P0=0xff;}五、讨论和心得。
极其简单好用的按键扫描程序C语言

极其简单好用的按键扫描程序(C语言)不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。
我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为C语言强大的可移植性。
同时,这里面用到了一些分层的思想,在单片机当中也是相当有用的,也是本文的另外一个重点。
对于老鸟,我建议直接看那两个表达式,然后自己想想就会懂的了,也不需要听我后面的自吹自擂了,我可没有班门弄斧的意思,hoho~~但是对于新手,我建议将全文看完。
因为这是实际项目中总结出来的经验,学校里面学不到的东西。
以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。
当然,我自己也是在多个项目用过,效果非常好的。
好了,工程人员的习惯,废话就应该少说,开始吧。
以下我以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。
用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。
核心算法:unsigned char Trg;unsigned char Cont;void KeyRead( void ){unsigned char ReadData = PINB^0xff; // 1Trg = ReadData & (ReadData ^ Cont); // 2Cont = ReadData; // 3}完了。
有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!!下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。
1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。
2:算法1,用来计算触发变量的。
一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Uchar Model; //按键状态(模式)
#defineOff_C0 //之前未按下
#defineOn_C1 //现按下
#defineDelay_C 2 //按键处理后标志
}Key;
//----------------定义两个IO输入口为按键入口--------------------//
SetBak[0]=Rtc_InitDate.RTC_Year;
SetBak[1]=Rtc_InitDate.RTC_Month;
SetBak[2]=Rtc_InitDate.RTC_Date;
SetBak[3]=Rtc_InitDate.RTC_WeekDay;
SetBak[4]=Rtc_InitTime.RTC_Hours;
}
SetBak[5]=Rtc_InitTime.RTC_Minutes;
//-----------长按需处理的内容------上----------//
Key.Model=Delay_C; //置按键模式为:已处理按键(看头文件定义)
return;
}
}
else
Key.SetInRn=0;
Key.Model=Delay_C;
//处理相应按键(可250ms才调用一次)长按
if(Key.Model == On_C) //按键状态为已按下
{
if(Key.Val == Key_Model_C) //是键1按下(看头文件定义)
{
if(++Key.SetInRn >= 3) //连计3次数3秒后为长按键(对应上面,如果按下未抬起的话会延时1000ms)
{
Key.ScanOnTime=0;
if(KeyMo_Bin == 0) //如果按键1为0即按下
{
Key.Val=Key_Model_C; //付当键1值(看头文件定义)
Key.Model=On_C; //置按键已按下标志
}
else if(KeyAdd_Bin == 0) //如果按键2为0即按下
分享一种按键处理程序(用C)
//头文件定义:
Ustruct KEY
{
Uchar Val;
#defineKey_Model_C0 //按键1值
#defineKey_AddVal_C 1 //按键2值
Uint ScanOnTime;
Uchar LongKeyState;
Uchar LongKeyRestState;
/*===============================================================*/
//主程序大循环中每1毫秒扫描1次
void KeyScan(void)
{
if(Key.LongKeyRestState == 1) //长按键标志(复位处理长按键)
{
void LoadCheckKeyRest(void)
{
Key.LongKeyRestState=1;
Key.ScanOnTime=0;
}
//======================================================================================
return;
}
if(Key.Model == Off_C) //如果当前按键状态为未按下“Off_C”
{
if((KeyMo_Bin == 0) || (KeyAdd_Bin == 0))//按键1或按键2已按下(低有效)
{
if(++Key.ScanOnTime >= 10) //当按下后自加1,加够10次即1ms*10=10ms去抖动
#define KeyMo_Bin(GPIOB->IDR.Bit.B5)
#define KeyAdd_Bin(GPIOB->IDR.Bit.B6)
/*===============================================================*/
GPIO_Init(GPIO_Pin_5|GPIO_Pin_6,GPIO_Mode_In_PU_No_IT); //初始化为上拉输入无中断
{
Key.SetInRn=0;
LoadCheckKeyRest(); //调清长按处理
BellOn(600); //蜂鸣器响
//-----------长按需处理的内容-----下-----------//
WorkStateBit.Bit.SettingMo=1;
SetOverTime=0;
SetMoRn=0;
if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1)) //当两按键均抬起
{
if(++Key.ScanOnTime >= 130) //延时后复位
{
Key.LongKeyRestState=0;
Key.Model=Delay_C;
}
}
else
Key.ScanOnTime=0;
{
if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1))//如果两按键均抬起
{
if(++Key.ScanOnTime >= 100) //延时100ms后复位按键状态为“Off_C”
{
Key.SetInRn=0;
Key.ScanOnTime=0;
Key.Model=Off_C;
}Байду номын сангаас
}
else //如果按键没有被抬起,对应上面if
{
if(++Key.ScanOnTime >= 1000) //延时1000ms后再复位按键状态为“Off_C”(为长按处理)
{
Key.ScanOnTime=0;
Key.Model=Off_C;
}
}
}
}
//======================================================================================
{
Key.Val=Key_AddVal_C; //付当键2值(看头文件定义)
Key.Model=On_C; //置按键已按下标志
}
BellOn(200); //蜂鸣器响
}
}
else
Key.ScanOnTime=0; //清去抖延时计数值
}
else if(Key.Model == Delay_C) //如果当前按键状态为已按下且已处理“Delay_C”