历史上的今天
返回首页

历史上的今天

今天是:2025年04月13日(星期日)

正在发生

2018年04月13日 | STM8S---外部中断应用之长按键识别

2018-04-13 来源:eefocus

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寄存器中断位:12

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

EXTI_CR1:12

  配置促发方式;


#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 */

推荐阅读

史海拾趣

Emhiser Research Inc公司的发展小趣事

随着业务的不断发展,Emhiser Research开始实施国际化战略。公司首先在欧洲设立了研发中心和销售机构,随后又在美国和亚洲等地建立了分公司。这些分支机构不仅帮助公司更好地了解当地市场需求,也为公司拓展国际市场提供了有力支持。通过国际化战略的实施,Emhiser Research的产品逐渐打入了全球电子市场。

ECLIPTEK公司的发展小趣事

随着全球对环保问题的日益关注,ECLIPTEK公司积极响应环保号召,将绿色环保理念融入其产品研发和生产过程中。公司采用环保材料和清洁能源,减少生产过程中的废弃物和污染物排放。同时,ECLIPTEK还积极参与环保公益活动,推动电子行业的可持续发展。

磁联达(CND-tek)公司的发展小趣事

磁联达(CND-tek)公司成立于2002年,正值中国电子行业的蓬勃发展期。创始人王雪霞凭借对市场敏锐的洞察力和对技术的深厚理解,决定专注于网络通讯类变压器和滤波器的研发与生产。初创时期,公司面临着资金短缺、技术积累不足和市场竞争激烈等多重挑战。然而,王雪霞带领团队坚持不懈地研发新产品,不断优化生产工艺,逐渐在市场上赢得了客户的认可。

FDI [Future Designs , Inc.]公司的发展小趣事

在电子行业的早期,FDI(Future Designs, Inc.)还只是一家名不见经传的小公司。创始人李明,凭借其对电子技术的热爱和敏锐的商业洞察力,带领团队研发出了一款具有革命性的电子芯片。这款芯片不仅性能卓越,而且成本较低,迅速在市场上获得了认可。正是这款产品,为FDI公司赢得了第一桶金,也为公司后续的发展奠定了坚实的基础。

Allianc公司的发展小趣事

在XXXX年,Allianc公司迎来了一次重大的技术突破。公司研发团队成功开发出了一款具有领先性能的新型电子产品,该产品不仅具有更高的性能和更低的能耗,还具备更好的用户体验。这一技术突破使得Allianc公司在市场上迅速脱颖而出,赢得了大量客户的青睐。随着产品销量的不断攀升,公司的知名度和影响力也逐渐扩大。

Axiomtek公司的发展小趣事

在XXXX年,Allianc公司迎来了一次重大的技术突破。公司研发团队成功开发出了一款具有领先性能的新型电子产品,该产品不仅具有更高的性能和更低的能耗,还具备更好的用户体验。这一技术突破使得Allianc公司在市场上迅速脱颖而出,赢得了大量客户的青睐。随着产品销量的不断攀升,公司的知名度和影响力也逐渐扩大。

问答坊 | AI 解惑

为了上班,买车值得吗?

今天去车市上看了一下,发现车市依然火暴,车还没降价格。因此,在想一个问题,比如我们电工,为了上班,买车值得吗?…

查看全部问答>

DIY示波器V2.0 最新进展-04.21

使用了一段时间altera 提供的cyclone开发板,觉得板子上的存储器资源特别充足。 存储器 256-Mbit DDR SDRAM 1-Mbyte同步 SRAM 16-Mbytes闪存 但是外设比较少,比较难进行前期的学习,为了能在示波器开发之前熟悉开发板,我们决定先进行显 ...…

查看全部问答>

Spartan6上原来还有光纤模块接口

        如题纯粹跑来感慨一下,我一直就好奇板子上一段小铁管是什么,原来是光纤模块接口 ,一顿晕眩!这咱可玩不了,希望下个试用者可以考虑做点这方面通讯实验,呵呵…

查看全部问答>

如何设计avr分析声音频率?

想让avr能够即时得到 通过mic采集到的周围环境的声音频率 各位大侠有什么思路没 请赐教…

查看全部问答>

国家二级字库汉字/字符地址??

大家好,我下了个国家二级字库,可是我不知字符或者汉字的地址从哪开始啊?说“啊”是汉字库存的第一个字,可是我实在找不到它的点阵是从哪个地址开始,?? 就差个地址了,还有就是这个字库 汉字是24*24点阵  字符是24*16点阵的吗? 字 ...…

查看全部问答>

大电阻测定

不知各位,有没有做过大电阻测定的电路,电阻在10兆欧以上。…

查看全部问答>

STTIME3问题

Error[Pe020]: identifier "TIM3" is undefined C:\\Users\\shenghua\\Desktop\\LCDDemo(lcd+led+buttom)\\LCDDemo\\project\\main.c 378 为什么  TIM3  没有定义啊?…

查看全部问答>

STM32无刷电机驱动

我的驱动电路是L6390D+STGP10NC60KD,现在用显示波器量LIN,HIN输入正常,现在问题是LVG输出15伏的波型正常,HVG只输出不正常的波形,7-8伏.有没有解答?ST的技术支持,都不知那里找. 下载 (49.45 KB) 2010-6-7 10:30 …

查看全部问答>

【MSP430共享】iar_msp430教程

IAR嵌入式工作平台Embedded Workbench为开发不同的目标处理器的项目提供强有力的开发环境,并为每一种目标处理器提供工具的选择。本章给出嵌入式工作平台的Embedded Workbench使用的项目模式简要讨论,并说明用户怎样用它来开发典型的应用程序。 [ ...…

查看全部问答>