STM8学习笔记---外部中断实现

利用按键做为中断触发,按键按下一次,LED灯翻转一次。
首先初始化IO口,按键接在PC4口,默认情况下高电平,按键按下后为低电平。
初始化代码如下:

void EXTI_GPIO_Init( void )
{
    PC_DDR &= ~( 1 << 4 );        //PC4 输入
    PC_CR1 |= ( 1 << 4 );         //带上拉电阻输入
    PC_CR2 |= ( 1 << 4 );         //允许外部中断
}

将PC4口设置为输入口,选择上拉电阻输入,让IO口默认情况下为高电平。由于要使用中断功能,所以允许外部中断。
下来看看中断相关寄存器:
在这里插入图片描述
通过中断映射表可以看到STM8的IO口中断,一个IO口只有一个中断源,也就是说按键的PC4口中断源为 端口C外部中断。在看看中断设置寄存器:

在这里插入图片描述
中断相关寄存器有5个,因为只有一个按键中断,所以不需要设置优先级,只设置中断控制寄存器就行。
在这里插入图片描述
要设置PC口为低电平触发,所以要将寄存器的4、5位设置为0。
中断设置只需要设置一个寄存器就可以了,中断初始化代码如下:

void EXTI_Init( void )
{
    EXTI_GPIO_Init();			
    EXTI_CR1 &= ~( 3 << 4 );        //4 5 位清零   01是PA,23是PB,45是PC,67是PD引脚
    EXTI_CR1 |= ( 0 << 4 );         //PC上升沿触发   00是下降沿触发  01 上升沿 10 下降沿 11 上升沿和下降沿
}

为了在主程序中调用方便,将IO口初始化和中断寄存器初始化放在一个函数中。
首先调用IO口初始化,IO口初始化完成后设置外部中断控制寄存器1,按键在PC4口,所以先将PC口设置位清0,然后设置触发方式,我们是低电平触发,所以4、位设置为0。
初始化结束后,下来就是中断程序的编写,由于PC4口没有单独的中断入口,用的是PC口中断源,也就是说PC口任何一个口出现低电平或者下降沿都会触发PC中断源,所以当中断发生时还要在中断函数中判断一下PC4口的电平,确认是PC4口触发的中断。
中断代码如下:

#pragma vector = 7                  // IAR中的中断号,要在STVD中的中断号上加2
__interrupt void EXTI_PORTC_Handle( void )
{
    if( EX_INT == 0 )
    {
       LED = !LED;
    }
}

中断中PC4口使用了位操作,定义在头文件中:

#ifndef __EXTI_H
#define __EXTI_H
#include "iostm8s103F3.h"    
#define  EX_INT   PC_IDR_IDR4            //定义PC4为 中断输入      
void EXTI_GPIO_Init( void );
void EXTI_Init( void );    
#endif

进入PC中断服务程序中,若此时PC4口的电平为0时,说明是按键按下了,于是对LED灯状态取反。
按键时手会抖动,那么中断可能会被多次触发,为了避免这种情况可以在按键IO口增加一个滤波电容来滤除掉按键时毛刺的产生。
那么能不能像按键实验中给按键添加延时功能一样,也在中断中若PC4口为低电平,延时一段时间再判断PC4口的电平?这样做也可以,但是一般不建议这样做。因为中断程序执行越快越好,若中断中加延时,会影响主程序执行速度。若中断频繁发生,那么程序就会多一半在延时中等待,会严重影响程序执行效率。若进入中断后在等待延时的过程中又发生了中断,那么就会继续触发中断,形成中断嵌套。每次中断单片机就要开辟堆栈空间,若中断嵌套过多,就要开辟更多的堆栈空间,有可能导致单片机内部空间不足,引发程序异常。所以一般情况下中断函数中代码越少越好,代码执行速度越快越好。
中断服务程序是中断发生后自动执行的,所以主程序中只需要初始化就行。主程序代码如下:

#include "iostm8s103F3.h"
#include "led.h"
#include "exti.h"

void SysClkInit( void )
{
    CLK_SWR = 0xe1;       //HSI为主时钟源  16MHz CPU时钟频率
    CLK_CKDIVR = 0x00;    //CPU时钟0分频,系统时钟0分频
}
void main( void )
{
    SysClkInit();                         //时钟初始化
    __asm( "sim" );                       //禁止中断
    LED_GPIO_Init();                      //LED 初始化
    EXTI_Init();                          //外部中断初始化
    __asm( "rim" );                       //开启中断
    LED = 0;
    while( 1 )
    {
       
    }
}

由于STM8单片机一组IO口只有一个中断入口,所以如果外部有多个中断源的话最好分别设置在不同组的IO口,这样程序处理起来会比较方便。

发布了76 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_20222919/article/details/100014543
今日推荐