历史上的今天
返回首页

历史上的今天

今天是:2025年03月22日(星期六)

2021年03月22日 | 飞思卡尔16位单片机(四)——GPIO输入功能测试

2021-03-22 来源:eefocus

一、介绍

        在这篇文章中,我们以按键作为输入器件对飞思卡尔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”,灯向右移动。

推荐阅读

史海拾趣

First Silicon Co., Ltd公司的发展小趣事

面对日益激烈的市场竞争,First Silicon公司深知供应链管理的重要性。公司投入大量资源,对供应链进行了全面整合和优化。通过建立长期稳定的供应商关系、引入先进的供应链管理软件和提高库存周转率等措施,First Silicon有效降低了原材料成本和库存风险。同时,公司还加强了与下游客户的沟通和合作,确保产品能够及时、准确地送达客户手中。这一系列举措不仅提升了公司的运营效率,还增强了其市场竞争力。

乐鑫(espressif)公司的发展小趣事

乐鑫科技在发展过程中,与百度、亚马逊等全球知名企业建立了紧密的合作关系。通过与这些合作伙伴的共同努力,乐鑫科技成功开发了一系列具有市场影响力的语音框架和物联网解决方案,进一步提升了其品牌影响力和市场竞争力。

ENERGIZER公司的发展小趣事

为了配合全球业务的发展,ENERGIZER在亚太地区设立了8个厂房和18个国家的办事处。其中,劲量(中国)有限公司于1992年开始进驻中国,并在1998年在天津设立了生产工厂。这一举措不仅促进了中国与国际间的技术交流与合作,还为中国的电池制造业带来了新的发展机遇。随着中国市场的不断扩大,ENERGIZER在中国的业务也逐渐壮大,成为了中国电池市场的重要参与者。

富满电子(FM)公司的发展小趣事

近年来,随着智能设备的普及,消费者对电池的需求也日益增长。为了满足这一需求,ENERGIZER不断加大研发投入,推出了一系列高性能的电池产品。其中,高能量锂电池的研发成功,为智能设备的发展提供了强有力的支持。这款电池具有高能量密度、长寿命等优点,广泛应用于智能手机、平板电脑等高端电子设备中。同时,ENERGIZER还不断优化生产工艺,降低成本,为消费者提供更优质、更实惠的电池产品。

这些故事展示了ENERGIZER公司在电子行业发展中的创新力和市场洞察力,也体现了该公司对环保和消费者需求的关注与响应。作为全球领先的电池制造商,ENERGIZER始终保持着技术创新的步伐,为全球电子行业的发展做出了重要贡献。

CalAmp公司的发展小趣事

随着物联网技术的快速发展,车队管理成为了一个重要的应用领域。CalAmp公司凭借其深厚的技术积累和市场洞察力,成功推出了一款车队管理新解决方案。该方案通过直观的用户界面(UI)设计,为企业、政府和建筑机构提供了更为便捷、高效的车队管理工具。用户可以通过该界面轻松获取关键业务数据,如资产位置、驾驶行为和车辆状态等,从而加快智能决策,提高车队运营效率,降低成本并增强安全性。这一创新解决方案的推出,进一步巩固了CalAmp在车队管理领域的领先地位。

Coleman Cable Inc公司的发展小趣事

随着全球环保意识的不断提高,Coleman Cable积极响应绿色发展的号召,将环保理念融入公司的生产和经营中。公司研发出环保型电缆产品,采用环保材料和工艺,减少生产过程中的环境污染。同时,公司还加强废弃电缆的回收和处理工作,推动资源的循环利用,为行业的绿色发展做出了贡献。

问答坊 | AI 解惑

我是新手,请求达人指点。 mcbsp 的 接受FIFO 中断怎么进不去

我用的是2812 ,由于2812自带的AD 是12位的,不满足我的精度要求,所以我外扩了一个AD转换芯片 AD73360 (16位)。 启动AD73360之后按说应该往回传踩到的数据,可是我在调试的时候怎么老进不去多通道缓冲串口的接受中断呢(接受深度我设置的是8)? ...…

查看全部问答>

测距离的转感器 分析

测距离的转感器 分析…

查看全部问答>

最早什么时侯可以从SD卡拷贝文件到windows目录?

需要在开机进入explorer之前把SD卡的几个文件拷到windows目录下。 我不懂驱动,于是瞎试一番。 在sdmemory的sdmemmain.cpp的DllEntry增加拷贝文件函数: 1        extern \"C\" BOOL WINAPI DllEntry(HINSTANCE hInstance, ...…

查看全部问答>

请问,OAL和BOOTLOADER有什么区别?

书上说,“BL用来初始化硬件资源,下载系统镜像,而OAL是系统内核的一部分”?…

查看全部问答>

基于WIN CE与s2410的外部中断的实现

基于WIN CE与s2410的外部中断的实现 断是指在执行程序的过程中,出现了异常情况和特殊请求时,计算机将停止现行程序的运行,转去对这些异常情况或特殊情况进行处理。 一、中断的基本知识 二、wince下关于中断的主要函数及其说明 三、s2410下关 ...…

查看全部问答>

求救!evb下我的RDA连接出错

高手帮帮忙啊!我用RDA执行PULL时出现错误提示:An error was encountered wile running this program. 我的代码: Public Const strInternetURL = \"http://localhost/sscesa20.dll\" Public Const strRemoteConnect = \"Provider=SQLOLEDB.1;P ...…

查看全部问答>

关于FPGA内部各逻辑块之间的延时测量

请问如何测量Spartan-3芯片内部各逻辑块之间的延时时间?…

查看全部问答>

蓄电池极性接反后引起的电路故障

故障现象:一辆五十铃汽车在闭合点火开关后,仪表显示正常,但充电指示灯不亮,且将点火开关置于Ⅱ档(起动档)时起动机无反应。 故障排除:检查充电指示灯,充电指示灯显示正常。因为该车充电指示灯受组合继电器控制,所以又拆下组合继电器 ...…

查看全部问答>

滤波器问题

这是用LTC1068做四阶椭圆滤波器的电路图,可是不明白后面运放芯片的作用,特请高手支招。下面的图是07年电子设计大赛的电路图,望高手支招 [ 本帖最后由 开窍的木偶 于 2011-8-8 10:28 编辑 ]…

查看全部问答>