一、介绍
在这篇文章中,我们以按键作为输入器件对飞思卡尔XEP100单片机的GPIO的输入功能进行测试。对应的硬件电路如下图所示。
当按键未按下时,由于有上拉电阻R39~R312的作用,单片机检测到的电平为高电平;当按键按下时,单片机引脚与地短接,单片机检测到引脚为低电平。
当按键按下时,按键输出端的原始电平如下图所示:
由图中可以看出,在按键按下和松开时,按键的电平信号存在波动,一般为10~15ms,这样有可能导致误判。为了消除抖动,可行的方法有:硬件去抖和软件去抖两种方法。本文的电路上使用的方法为硬件去抖,即在按键的两端加了一个去抖电容。软件去抖的方法是在检测到按键按下后,延时10~15ms,跳过抖动的这段信号,再进行检测,如果是低电平则判断按键按下。
本文的硬件电路的按键与单片机引脚的连接关系如下:
PTH3——KEY1
PTH2——KEY2
PTH1——KEY3
PTH0——KEY4
单片机的PH口是有中断功能的I/O口,因此对按键状态的读入有查询和中断两种方式。
所谓查询方式是指,单片机以一定的时间间隔按时对输入口的电平进行读取。中断是指计算机在执行程序的过程中,当出现异常情况或特殊请求时,计算机停止现在执行的程序,转向对这些异常情况或特殊请求的处理,处理结束后再返回之前的程序的间断处,继续执行原程序。中断时单片机实时处理内部事件或外部事件的一种机制,当某种内部事件或外部事件发生时,单片机的中断系统将迫使CPU暂停正在执行的程序转而去执行中断事件,中断事件处理完毕后,再返回被中断的程序处,继续执行下去。中断机制如下图所示。
在程序中使用中断具有以下优点:
(1)提高了CPU的效率。CPU与外围设备的工作方式有查询和中断两种方式,查询方法是无论外围设备是否需要服务,CPU每隔一段时间都要依次查询一遍,这种方法CPU需要花费时间做查询工作。而中断则是在外围设备需要服务时主动告诉CPU,CPU则停下当前的工作去处理中断程序,从而可以提高CPU的效率。
(2)可以实现实时处理。外围设备任何时刻都可以发出请求中断信号,CPU接到请求后及时处理,以满足实时的需求。
(3)可以及时处理故障。单片机系统运行过程中难免会出现故障,有许多事情是无法预料到的。如:电源掉电、存储器出错、外围设备工作不正常等,这时可以通过中断系统向CPU发送中断请求,由CPU及时转到相应的出错处理程序,从而提高了系统的可靠性。
产生中断时,中断服务程序执行完毕后恢复单片机状态,单片机从被中断打断的地方继续执行。当某一中断事件发生,与该事件相对应的标志将被置位。如果该中断未使能,那么单片机不会对该中断作出反应。CCR寄存器中的全局中断屏蔽位I在复位之后为1,屏蔽掉所有中断事件。在用户程序完成堆栈指针和其他设置之后,清除I,允许单片机响应中断事件,程序中的 “EnableInterrupts;”语句就是实现使能中断的功能。当单片机接收到一个有效的中断请求,在响应之前,它会执行完当前运行的指令,然后逐周期执行以下过程:
保存CPU寄存器到堆栈中
设置CCR寄存器中的I=1,禁止全局中断
获取当前所有挂起的待处理中断事件中最高优先级中断向量
预取中断向量的地址排列到指令队列中
当单片机响应中断后,I自动置为1,避免中断嵌套。通常,ISR执行完毕后,I恢复为0(CCR从堆栈弹出)。如果在ISR中,清除I(即设置I=0),那么MCU有可能在当前中断事件未完成之前响应其他中断事件,即中断嵌套。中断嵌套可能对用户程序调试带来麻烦。
当ISR执行到RTI指令,CCR,A,X,PC从堆栈恢复。
用户可在自己的中断服务程序一开始将I清零,从而使能全局中断。那么当前运行的中断服务程序可以被其他中断打断,MCU运行新的中断服务程序,从而形成中断嵌套。用户在使用中断嵌套时会对调试带来不便,故建议避免使用中断嵌套。在中断服务程序的开始,用户程序应清掉产生该中断的标志位,其目的是同一中断源产生另外一个中断事件能够被记录,并在完成当前中断服务程序之后能够得到MCU的响应。
每一个中断对应一个中断向量。这个向量指向这个中断的服务程序。用CodeWarrior编程时,在工程的“Project SettingsLinker Files”文件夹下的“Project.prm”文件中设置相应中断的中断向量。
二、查询方式读取按键
在这个实验中,我们采用查询方式对按键的状态进行读取,主要代码如下,(完整代码可以从本文的资源中下载)
void main(void) {
DisableInterrupts;
init_led_key();
EnableInterrupts;
for(;;)
{
delay();
data=data<<1; //左移一位
if(data==0)
data=0x01;
if(KEY1==0&&KEY1_last==1) //按键F1按下
mode=1;
if(KEY2==0&&KEY2_last==1) //按键F2按下
mode=2;
KEY1_last=KEY1; //保存F1的状态
KEY2_last=KEY2; //保存F2的状态
if(mode==1)
LED = ~data;
else
LED = data;
}
}
在这段代码中,发光二极管以流水灯的方式进行闪烁,每个周期经过delay();函数延时之后,读取KEY1和KEY2的状态,并且与上个周期的转态进行比较,如果上个周期为1(没有按下),这个周期为0(按键按下),则改变灯闪的模式,如果按下按键“KEY2”,则8个灯中只有一个熄灭,并且熄灭的灯循环向右移动。按下按键“KEY1”,则8个灯中只有一个点亮,并且点亮的灯循环向右移动。
三、中断方式读取按键
在这个实验中,我们通过中断来进行按键的读取,为了使能中断功能,首先要对按键进行初始化,代码如下所示。
void init_key(void)
{
KEY1_dir =0; //设置为输入
KEY2_dir=0;
KEY3_dir=0;
KEY4_dir=0;
PPSH = 0x00; //极性选择寄存器,选择下降沿;
PIFH = 0x0f; //对PIFH的每一位写1来清除标志位;
PIEH = 0x0f; //中断使能寄存器;
}
在这段代码中,首先将每个按键的方向寄存器设置为输入状态,然后通过PPSH寄存器设置PH0~PH3的输入极性为下降沿触发中断。PIFH = 0x0f; 将标志位清除,PIEH=0x0f; 将中断功能使能。
这个程序的主函数代码如下所示。
void main(void) {
DisableInterrupts;
init_led();
init_key();
EnableInterrupts;
for(;;)
{
delay(time);
if(direction==1)
{
data=data<<1; //左移一位
if(data==0)
data=0x01;
}
else
{
data=data>>1; //右移一位
if(data==0)
data=0x80;
}
LED = ~data;
}
}
这段代码中,初始化了按键和LED,然后主循环中控制LED闪烁,LED的状态根据time和direction进行变化,time决定了延时的长短,进而影响闪烁的快慢,direction影响灯闪烁的方向。
中断的处理函数如下所示
interrupt void PTH_inter(void)
{
if(PIFH != 0) //判断中断标志
{
PIFH = 0xff; //清除中断标志
if(KEY1 == 0) //按键1按下
{
time-=1;
if(time==0)
time=1;
}
if(KEY2 == 0)
{
time+=1;
if(time>10)
time=10;
}
if(KEY3 == 0)
direction=0;
if(KEY4 == 0)
direction=1;
}
}
由于中断设置的是下降沿触发中断,当有按键按下时,会进入中断函数,在中断函数中,首先确认标志位,判断是否确实有中断发生,然后判断是哪个按键按下,用KEY1和KEY2来改变time的值,用KEY3和KEY4来改变direction的值。
需要注意的是,要设置中断向量,在工程的“Project SettingsLinker Files”文件夹下的“Project.prm”文件中设置,如下所示,
VECTOR ADDRESS 0xffcc PTH_inter
这个实验的现象是,8个LED灯中有一个点亮,并且点亮的灯循环向右移动。按下按键“KEY1”,灯移动的速度加快;按下按键“KEY2”,灯移动的速度减慢;按下按键“KEY3”,灯向左移动;按下按键“KEY4”,灯向右移动。
上一篇:飞思卡尔16位单片机(五)——ADC模数转换模块测试
下一篇:飞思卡尔16位单片机(三)——GPIO输出功能测试
推荐阅读最新更新时间:2024-11-06 15:31
设计资源 培训 开发板 精华推荐
- 【物联网】【物联网】鸿蒙智能WIFI开关+:4226836A
- NCV5662 低输出电压、超快速 2.0 A 低压差线性稳压器的典型应用,支持可调输出
- EVAL-AD7150EBZM,评估 AD7150 电容数字转换器的评估板
- 6位手持开源万用表
- STC8G1K08-8P系统
- 【立创开发板】梁山派平衡小车(欢迎观看我稳如老狗小车)
- 自平衡莱洛三角形V2电机无货的解决方案
- 使用 Analog Devices 的 REF198GRUZ-REEL 的参考设计
- EVAL-ADF4113EBZ2,用于评估 ADF4113 PLL 频率合成器的评估板
- SX1508 全球最低电压电平转换 GPIO 的典型应用,带 LED 驱动器和键盘引擎