STM8S---外部中断应用之长按键识别

发布者:数字梦想最新更新时间:2018-07-24 来源: eefocus关键字:STM8S  外部中断  长按键识别 手机看文章 扫描二维码
随时随地手机看文章

STM8常用中断指令

  • 开总中断 

    • _asm(“rim”);

  • 禁止中断 

    • _asm(“sim”);

  • 进入停机模式 

    • _asm(“halt”);

  • 中断返回 

    • _asm(“iret”);

  • 等待中断 

    • _asm(“wfi”);

  • 软件中断 

    • _asm(“trap”);

STM8S常用中断映射

中断映射表

如使用中断函数时,可以通过在上图中查找相对应的中断向量号,而中断函数的名字可以自定义

/*  BASIC INTERRUPT VECTOR TABLE FOR STM8 devices

 *  Copyright (c) 2007 STMicroelectronics

 */


typedef void @far (*interrupt_handler_t)(void);


struct interrupt_vector {

    unsigned char interrupt_instruction;

    interrupt_handler_t interrupt_handler;

};


@far @interrupt void NonHandledInterrupt (void)

{

    /* in order to detect unexpected events during development, 

       it is recommended to set a breakpoint on the following instruction

    */

    return;

}


extern void _stext();     /* startup routine */

extern @far @interrupt void EXTI2_Hand_Fun(void);

extern @far @interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void);



struct interrupt_vector const _vectab[] = {

    {0x82, (interrupt_handler_t)_stext}, /* reset */

    {0x82, NonHandledInterrupt}, /* trap  */

    {0x82, NonHandledInterrupt}, /* irq0  */

    {0x82, NonHandledInterrupt}, /* irq1  */

    {0x82, NonHandledInterrupt}, /* irq2  */

    {0x82, NonHandledInterrupt}, /* irq3  */

    {0x82, NonHandledInterrupt}, /* irq4  */

    {0x82, EXTI2_Hand_Fun}, /* irq5  */

    {0x82, NonHandledInterrupt}, /* irq6  */

    {0x82, NonHandledInterrupt}, /* irq7  */

    {0x82, NonHandledInterrupt}, /* irq8  */

    {0x82, NonHandledInterrupt}, /* irq9  */

    {0x82, NonHandledInterrupt}, /* irq10 */

    {0x82, TIM1_UPD_OVF_TRG_BRK_IRQHandler}, /* irq11 */

    {0x82, NonHandledInterrupt}, /* irq12 */

    {0x82, NonHandledInterrupt}, /* irq13 */

    {0x82, NonHandledInterrupt}, /* irq14 */

    {0x82, NonHandledInterrupt}, /* irq15 */

    {0x82, NonHandledInterrupt}, /* irq16 */

    {0x82, NonHandledInterrupt}, /* irq17 */

    {0x82, NonHandledInterrupt}, /* irq18 */

    {0x82, NonHandledInterrupt}, /* irq19 */

    {0x82, NonHandledInterrupt}, /* irq20 */

    {0x82, NonHandledInterrupt}, /* irq21 */

    {0x82, NonHandledInterrupt}, /* irq22 */

    {0x82, NonHandledInterrupt}, /* irq23 */

    {0x82, NonHandledInterrupt}, /* irq24 */

    {0x82, NonHandledInterrupt}, /* irq25 */

    {0x82, NonHandledInterrupt}, /* irq26 */

    {0x82, NonHandledInterrupt}, /* irq27 */

    {0x82, NonHandledInterrupt}, /* irq28 */

    {0x82, 



NonHandledInterrupt}, /* irq29 */

};


外部中断长按键识别相关配置


  STM8S为外部中断事件专门分配了五个中断向量:


PortA 口的5个引脚:PA[6:2]

PortB 口的8个引脚:PB[7:0]

PortC 口的8个引脚:PC[7:0]

PortD 口的7个引脚:PD[6:0]

PortE口的8个引脚:PE[7:0]

  PD7是最高优先级的中断源(TLI);


中断IO设置


  这里选用EXTI2(端口C外部中断)。那么需要将中断促发的IO(PC5)设置为上拉输入或中断上拉输入,悬浮输入的话很容易受干扰。


/*PC5设置为上拉输入*/

void Init_EXTI2_GPIO(void)

{

    PC_DDR &= 0XDF; 

    PC_CR1 &= 0XDF;

    PC_CR2 |= 0x20;

}


外部中断寄存器配置


CPU CC寄存器中断位:


  I1 I0不能直接写,只能通过开中断或关中断来写,上电默认是11;当用指令开中断时( _asm(“rim\n”);),为00;当发生中断时,由当前中断(ITC_SPRx)载入I[1:0],主要用于做中断优先级;退出中断自动清0;因此在写EXTI_CR1,需将ITC_SPRx配置成11,或加入禁中断指令 。


EXTI_CR1:


  配置促发方式;


测试代码


#include


char keyFlag;       

char keyPressStatus = 1;

unsigned int keyCount;      


/*Output Pin*/

_Bool PD2 @PD_ODR:2;

_Bool PC7 @PC_ODR:7;

_Bool PC6 @PC_ODR:6;

_Bool PC3 @PC_ODR:3;

/*Input Pin*/

_Bool PC5   @PC_IDR:5;


/*电量指示灯*/

#define LED1 PD2

#define LED2 PC7

#define LED3 PC6

#define LED4 PC3

/*按键*/

#define KEY     PC5



/*主时钟频率为8Mhz*/

void Init_CLK(void)

{

    CLK_ICKR |= 0X01;           //使能内部高速时钟 HSI

    CLK_CKDIVR = 0x08;          //16M内部RC经2分频后系统时钟为8M

    while(!(CLK_ICKR&0x02));    //HSI准备就绪 

    CLK_SWR=0xE1;               //HSI为主时钟源 

}


void Init_LED(void)

{

    /*LED 配置为推挽输出*/

    PD_DDR |= 0X04;   //PD2输出模式,0为输入模式

    PD_CR1 |= 0X04;   //PD2模拟开漏输出

    PD_CR2 &= 0XFB;   //PD2输出速度最大为2MHZ,CR1/CR2悬浮输入


    PC_DDR |= 0XC8;

    PC_CR1 |= 0XC8;

    PC_CR2 &= 0X27;

}


/*PC5设置为上拉输入*/

void Init_EXTI2_GPIO(void)

{


    PC_DDR &= 0XDF; 

    PC_CR1 &= 0XDF;

    PC_CR2 |= 0X20;

}


void Init_EXTI2(void)

{

    EXTI_CR1 |= 0x30;       //上升沿和下降沿促发

}



void Init_TIM1(void)

{

    TIM1_IER = 0x00;

    TIM1_CR1 = 0x00;


    TIM1_EGR |= 0x01;

    TIM1_PSCRH = 199/256; // 8M系统时钟经预分频f=fck/(PSCR+1) TIM1 为16位分频器 

    TIM1_PSCRL = 199%256; // PSCR=0x1F3F,f=8M/(200)=40000Hz,每个计数周期1/40000ms


    TIM1_CNTRH = 0x00;

    TIM1_CNTRL = 0x00;      


    TIM1_ARRH = 400/256;  // 自动重载寄存器ARR=400

    TIM1_ARRL = 400%256;  // 每记数400次产生一次中断,即10ms


    TIM1_CR1 |= 0x81;

    TIM1_IER |= 0x01;

}


unsigned int Key_Scan_Test(void)

{

    unsigned int count = 0;

    unsigned char keyMode;


    if(0 == keyPressStatus)

    {

        keyFlag = 1;

        while(!keyPressStatus);

        keyFlag = 0;

        count = keyCount;

        keyCount = 0;

    }

    else

    {

        count = 0;

    }

    /*10ms * 150 = 1.5s*/

    if(count >= 150)keyMode = 2;        //长按

    else if(count >= 4)keyMode = 1;     //短按

    else keyMode = 0;                   //抖动


    return keyMode;

}


main()

{  

    char keynum = 0;


    _asm("sim");

    Init_CLK();

    Init_LED();

    Init_EXTI2_GPIO();

    Init_EXTI2();

    Init_TIM1();

    _asm("rim");

    while (1)

    {

        keynum = Key_Scan_Test();

        if(1 == keynum)LED3 = ~LED3;

        if(2 == keynum)LED4 = ~LED4;

    }

}


@far @interrupt void EXTI2_Hand_Fun(void)

{

    keyPressStatus = !keyPressStatus;

    LED1 = ~LED1;

}


@far @interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void)

{

    static unsigned int i = 0;


    TIM1_SR1 &= ~(0X01);


    ++i;

    if(50 == i)

    {

        LED2 = ~LED2;

        i = 0;

    }


    /*Within Key Press Hand*/

    if(1 == keyFlag)

    {

        ++keyCount;

    }

}


注意:

中断向量需声明,在stm8_interrupt_vector.c中加入:

extern @far @interrupt void EXTI2_Hand_Fun(void);

extern @far @interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void);

{0x82, EXTI2_Hand_Fun}, /* irq5  */

{0x82, TIM1_UPD_OVF_TRG_BRK_IRQHandler}, /* irq11 */


  另参见不用外部中断长按键识别:不用外部中断识别长按键


关键字:STM8S  外部中断  长按键识别 引用地址:STM8S---外部中断应用之长按键识别

上一篇:STM8S关于TIM最高频率设置的坑
下一篇:STM8S定时器基本中断定时

推荐阅读最新更新时间:2024-03-16 16:10

STM32L552开发板——外部中断
上回向大家介绍了如何使用GPIO口的输出功能点亮一盏LED灯,以及使用GPIO口的输入功能读取按键的状态控制LED的闪烁频率,然鹅,获取按键的状态采用的是主循环查询的方法,这有一个弊端,试想当主循环的循环周期非常长的时候,比如夸张点说要1秒,那就得一直按着按键等到程序扫描到按键的输入引脚后才能放开,这个等待时间最长需要1秒,这是很糟糕的,我可没有这个耐心去等,比如在将一个数从1调节到100的时候,那后果是可想而知的。为此,就有必要引入一个叫中断的神奇东西,程序中的中断,会把正在运行的普通程序或者低级的中断服务程序打断,先运行本中断服务函数内的程序,就好比我们日常生活中的突发事件,你正在洗衣服,突然快递小哥到你家门口了,你得放下手上
[单片机]
STM32L552开发板——<font color='red'>外部中断</font>
STM32F103C8T6使用外部中断法和输入捕获法进行编码器测速
01 前言 如果我们想对 电机 进行速度或者转角的精确控制,需要使用到很多 算法 ,比如非常经典的 PI D控制算法,或者一些只能算法,但这些算法都需要 传感器 来提供转速或转角的反馈值,对于电机来说, 编码器 是非常流行并且实用的电机配套传感器,本文使用 STM32 F103C8T6+L298N+MG513P30电机进行直流电机的编码器测速。 02 编码器原理 1.分类 光电 式编码器的精准度比霍尔式要高,但是由于它需要 红外 线发生器和 接收器 ,相对来说造价要贵一些。现在我们比较常用的是霍尔式增量编码器,有很多电机都会自带编码器。 2.测速方法分类 (1)M法测速 编码器输出的脉冲个数代表了位置,那么单位时间里的
[单片机]
STM32F103C8T6使用<font color='red'>外部中断</font>法和输入捕获法进行编码器测速
基于MSP430G2553的IO外部中断配置说明
这一篇文章将说明MSP430G2553的IO中断配置,整个P1的IO都可以配置IO中断,但中断处理函数只有一个,MSP430和大多数MCU一样提供上升沿、下降沿选择。 在Launchpad上有按键S2,接在P1.3口,当按下后P1.3将接入高电平,从而触发中断。 在实例代码中,配置了P1.3和P1.6的LED灯,当按下P1.3的按键产生中断,LED灯将切换点亮 1.按键的中断配置 要配置按键中断,需要先设置P1.3口为输入,并且设置上拉电阻以保障稳定性, P1DIR &= ~BIT3;//设置P1.3为输入 P1REN |= BIT3;//启用P1.3电阻 在启用电阻后,由P1OUT来配置下拉还是上拉 P1OUT |=
[单片机]
基于MSP430G2553的IO<font color='red'>外部中断</font>配置说明
MCS51单片机的外部中断触发方式
51单片机的外部中断有两种触发方式可选:电平触发和边沿触发。选择电平触发时,单片机在每个机器周期检查中断源口线,检测到低电平,即置位中断请求标志,向CPU请求中断。选择边沿触发方式时,单片机在上一个机器周期检测到中断源口线为高电平,下一个机器周期检测到低电平,即置位中断标志,请求中断。 这个原理很好理解。但应用时需要特别注意的几点: 1)电平触发方式时,中断标志寄存器不锁存中断请求信号。也就是说,单片机把每个机器周期的S5P2采样到的外部中断源口线的电平逻辑直接赋值到中断标志寄存器。标志寄存器对于请求信号来说是透明的。这样当中断请求被阻塞而没有得到及时响应时,将被丢失。换句话说,要使电平触发的中断被CPU响应并执行,必须保证外
[单片机]
stm8s串口奇偶校验学习笔记
以前用过stm32的串口,不过用的时候一般都是调用库函数,设置波特率,8位数据位,无校验,1位停止位。传输过程中也没有遇到过太多的问题,最近用stm8s,需要用到奇偶校验(至于什么是奇偶校验,网上资料很多),用了之后发现还是有些地方多需要注意的,下面把遇到的问题记录下来。 一、了解串口数据帧格式 二、了解stm8s的串口 查看stm8s参考手册: 可以看出,在STM8S中M位所定义是帧长度,而不是数据位的长度!也就是说M位所定位的长度为“数据位+奇偶校验位”个数的总和。当数据位为8位时,不使用奇偶校验的时候,M的长度为8位;而要使用奇偶校验的时候,M的长度应该为9位!所以编写程序的时候不能简单的只改变校验位的设置; 三、程
[单片机]
<font color='red'>stm8s</font>串口奇偶校验学习笔记
msp430外部中断程序
中断在我们生活中无处不在,51单片机外部中断只有两个,而强大的msp430有很多,比如P1、P2口全部是 其驱动程序如下: int main( void ) { WDTCTL = WDTPW + WDTHOLD; P2IE |=0x01; //下降沿触发 P2IES |=0x01; P2IE |=0x02; P2IES |=0x02; P2IFG &=~0x03; _BIS_SR(GIE); } #pragma vector =PORT2_VECTOR __interrupt void Port_1(void) { if((P2IFG | 0xfe)
[单片机]
关于STM32外部中断
以下总结参考原子STM32开发指南 STM32F103 的中断控制器支持 19 个外部中断/事件请求。STM32F103 的19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断。 线 16:连接到 PVD 输出。 线 17:连接到 RTC 闹钟事件。 线 18:连接到 USB 唤醒事件。 每个中断线对应了最多 7 个 IO 口,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、 GPIOF.0、 GPIOG.0。 在库函数中,配置 GPIO 与中断线的映射关系的函数 GPIO_EXTILineConfig()来实现的: void GPIO_EXTILine
[单片机]
STM8S提示错误信息的原因及解决办法
把产品样板连上 STM8S-DISCOVERY 开始全速运行,发现先后弹出两个错误提示框: 第一个:Error:swim error : comm timeout 点击确定后,继续全速运行,弹出第二个错误。 第二个错误:Error: gdi-error : flash memory not accessible while core is running 经过反复研究,发现,是VACAP引脚的电容焊错了,焊成了 10nF 的电容了,修改为 1uF 的电容后,一切正常,错误全部消失。看起来,就是这个电容的缘故导致了上述错误。
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved