历史上的今天
返回首页

历史上的今天

今天是:2024年12月23日(星期一)

正在发生

2020年12月23日 | 天嵌开发板 TQ210 S5PV210 中断方式按键实现

2020-12-23 来源:eefocus

中断在裸机开发中是非常重要的一项学习内容,之前学习过STM32的中断实现,是参考正点原子的代码,通过库函数的方式实现的,为了进一步深度理解其中的道理,此次通过天嵌的TQ210开发板实现中断方式。


具体功能为,LED正常闪烁,当按键被按下的时候,通过串口打印信息,提示按键被按下,此过程不影响LED正常闪烁。中断执行过程具体如下图:

根据示意图,可知道当有中断请求时,首先进行保护现场,然后跳到中断处理函数,执行中断处理函数当中的程序,最后进行恢复现场,程序继续运行。


通过查询开发板原理图得知,按键连接的为外部中断XEINT0,连接的芯片引脚为GPH0,具体细节如下图。


知道了硬件连接就可以进行代码编写了,具体流程如下:


配置GPH0引脚为为外部中断模式

配置中断触发方式(此处设置为下降沿触发)

中断屏蔽配置

使能外部中断

通过以上流程中断基本已经完成初始化准备工作。

其中提到了中断屏蔽,此处引用百度百科进行简单的介绍下:

什么叫屏蔽中断?允许中断?怎样实现?

按照是否可以被屏蔽,可将中断分为两大类:不可屏蔽中断(又叫非屏蔽中断)和可屏蔽中断。不可屏蔽中断源一旦提出请求,CPU必须无条件响应,而对可屏蔽中断源的请求,CPU可以响应,也可以不响应。CPU一般设置两根中断请求输入线:可屏蔽中断请求INTR(Interrupt Require)和不可屏蔽中断请求NMI(NonMaskable Interrupt)。对于可屏蔽中断,除了受本身的屏蔽位控制外,还都要受一个总的控制,即CPU标志寄存器中的中断允许标志位IF(Interrupt Flag)的控制,IF位为1,可以得到CPU的响应,否则,得不到响应。IF位可以由用户控制,指令STI或Turbo c的Enable()函数,将IF位置1(开中断),指令CLI或Turbo_c 的Disable()函数,将IF位清0(关中断)。


此外,还需配置中断向量表、优先级、控制等具体配置过程中涉及的中断控制器如下图所示:

具体程序文件由key.h、key.c main.c start.S等文件组成,具体目录结构如下图:
在这里插入图片描述

gpio.h 内容如下图


#ifndef _ASM_ARCH_GPIO_H

#define _ASM_ARCH_GPIO_H


struct s5pc1xx_gpio_bank{

        unsigned int con;

        unsigned int dat;

        unsigned int pull;

        unsigned int drv;

        unsigned int pdn_con;

        unsigned int pdn_pull;

        unsigned char res1[8];  

};

struct s5pv210_gpio{

        struct s5pc1xx_gpio_bank gpio_a0;

        struct s5pc1xx_gpio_bank gpio_a1;

        struct s5pc1xx_gpio_bank gpio_b;

        struct s5pc1xx_gpio_bank gpio_c0;

        struct s5pc1xx_gpio_bank gpio_c1;

        struct s5pc1xx_gpio_bank gpio_d0;

        struct s5pc1xx_gpio_bank gpio_d1;

        struct s5pc1xx_gpio_bank gpio_e0;

        struct s5pc1xx_gpio_bank gpio_e1;

        struct s5pc1xx_gpio_bank gpio_f0;

        struct s5pc1xx_gpio_bank gpio_f1;

        struct s5pc1xx_gpio_bank gpio_f2;

        struct s5pc1xx_gpio_bank gpio_f3;

        struct s5pc1xx_gpio_bank gpio_g0;

        struct s5pc1xx_gpio_bank gpio_g1;

        struct s5pc1xx_gpio_bank gpio_g2;

        struct s5pc1xx_gpio_bank gpio_g3;

        struct s5pc1xx_gpio_bank gpio_i;

        struct s5pc1xx_gpio_bank gpio_j0;

        struct s5pc1xx_gpio_bank gpio_j1;

        struct s5pc1xx_gpio_bank gpio_j2;

        struct s5pc1xx_gpio_bank gpio_j3;

        struct s5pc1xx_gpio_bank gpio_j4;

};

#define S5PV210_GPIO_BASE (0xE0200000)


struct s5pv210_gph_bank{

        unsigned int con;

        unsigned int dat;

        unsigned int pull;

        unsigned int drv;

};

#define S5PV210_GPH0_BASE (0xE0200C00)  //GPH0 基地址


#endif 


uart.h内容如下图



#ifndef UART_H

#define UART_H


struct s5pv2xx_uart

{


        unsigned int   ulcon;

        unsigned int   ucon;

        unsigned int   ufcon;

        unsigned int   umcon;

        unsigned int   utrstat;

        unsigned int   uerstat;

        unsigned int   ufstat;

        unsigned int   umstat;

        unsigned char  utxh;

        unsigned char  resl[3];

        unsigned char  urxh;

        unsigned char  res2[3];

        unsigned int   ubrdiv;

        unsigned short udivslot;

        unsigned char  res3[2];

        unsigned char  res4[0x3d0];

};


#define S5PV210_UART_BASE (0xE2900000)

void uart_init(void);

void myputc(char c); 

void myputs(const char *str);

#endif


关键的是key.h 其中的地址一定要正确


#ifndef KEY_H

#define KEY_H


#define pEXECPTION_IRQ  (*(volatile unsigned int*)(0xD0037400+0X18))


#define EXT_INT_0_CON   (*(volatile unsigned int*)(0xE0200E00)) //外部中断0 控制寄存器

#define EXT_INT_0_MASK  (*(volatile unsigned int*)(0xE0200F00)) //外部中断0 mask(屏蔽控制)寄存器

#define EXT_INT_0_PEND  (*(volatile unsigned int*)(0xE0200F40)) //外部中断0 pend 阻塞 挂起控制器


#define VIC0INTENABLE   (*(volatile unsigned int*)(0xF2000010))//VICO  中断使能控制器

#define VIC0ADDRESS     (*(volatile unsigned int*)(0xF2000F00))//VICO  中断地址控制器

#define VIC0VECTADDR0   (*(volatile unsigned int*)(0xF2000100))//VICO  地址O清除寄存器



void key_init(void);

void irq_init(void);

void key1_handler(void);

void irp_c_handler(void);


#endif


key.c文件内容如下图:


#include "cpu_io.h"

#include "gpio.h"

#include "key.h"

#include "uart.h"


extern void asm_irq(void);

void irq_init()

{

        pEXECPTION_IRQ=(unsigned int )asm_irq;

}

void irq_c_handler(void)

{

          void  (*handler)(void)=0x0;

          myputs("in irq c handler....n");

          handler =(void (*) (void)) VIC0ADDRESS;

          if(handler) handler();


}

void key1_handler(void)

{

        myputs("key1 down!!!n");

        EXT_INT_0_PEND |= (0x1<<0);

        VIC0ADDRESS=0X0;

}

void key_init(void)

{

        struct s5pv210_gph_bank *gph0_base=(struct s5pv210_gph_bank*) S5PV210_GPH0_BASE;

        unsigned int var;

    

        /**外部引脚进行功能选择,EINT***/

        var =readl(&gph0_base->con);

        var|=0xf<<0; //功能选择 0xf 表示配置GPHO引脚为外部中断0

        writel(var,&gph0_base->con);

        /****配置ENIT功能***************/

        EXT_INT_0_CON &= ~(0X7<<0); //低三位清零 为以后配置中断触发方式做准备

        EXT_INT_0_CON |=(0x2<<0);   //低三位配置为010 即为下降沿触发方式

    

        EXT_INT_0_MASK &= ~(0x1<<0);//使能中断屏蔽

        /*****配置主中断控制器**********/

        VIC0INTENABLE |= (0X1<<0);  //使能中断

        VIC0VECTADDR0=(unsigned int)key1_handler;

}


uart.c 文件内容如下图:


#include "cpu_io.h"

#include "uart.h"

#include "gpio.h"

void uart_init(void)

{

        struct s5pv210_gpio *gpio_base=(struct s5pv210_gpio *)S5PV210_GPIO_BASE;

        struct s5pv2xx_uart *uart_base=(struct s5pv2xx_uart *)S5PV210_UART_BASE;

        unsigned int var;

        var=readl(&gpio_base->gpio_a0.con);

        var &= ~(0xff<<0);

        var |=  (0x22<<0);

        writel(var,&gpio_base->gpio_a0.con);

        _REG(&uart_base->ulcon)=0x3; //8 bit 1stop non-even

        _REG(&uart_base->ucon) =0x5; //

        _REG(&uart_base->ubrdiv)=35;

        _REG(&uart_base->udivslot)=0x80;

    

}

void myputc(char c)

{

    

        struct s5pv2xx_uart *uart_base=(struct s5pv2xx_uart *)S5PV210_UART_BASE;

         //判断缓冲区是否为空,再发送数据

        while(!(_REG(&uart_base->utrstat)&(0x1<<2)));   

        _REG(&uart_base->utxh)=c;



}

void myputs(const char *str)

{

        while(*str)

        {   

                myputc(*str);

                str++;

        }   

}


main.c函数内容比较少 ,完成闪烁LED和初始化工作:


//main.c 

#include "led.h"

#include "cpu_io.h"

#include "uart.h"

#include "key.h"

static void mydelay()

{

        volatile unsigned int i=0xfffff;

        while(i--);


}

void led_test()

{


      led_init();

      while(1)

      {   

         led_blink(1);

         mydelay();

         led_blink(0);

         mydelay();

      }   

}


int main()

{

        irq_init();

        uart_init();

        key_init();

        myputs("hello world!n");

        led_test();

        return 0;

}


start.S内容如下 ,主要完成中断跳转和保护现场等;



.global _start

.global main

.global irq_c_handler

.global asm_irq

_start :

     bl   main

loop:

     b loop


irq_handler:

        stmfd sp!,{r0-r3,lr}

        bl    irq_c_handler

        ldmfd sp!,{r0-r3,lr}

        subs  pc,lr,#4

asm_irq:

        b irq_handler

.end



最后还需要注意的是,下载的时候应该选择SD卡下载,不要选择Dram下载。以上内容仅供参考,如有问题还请指出。


推荐阅读

史海拾趣

EFC [Electronic Film Capacitors, Inc.]公司的发展小趣事

随着公司规模的扩大和实力的增强,EFC公司开始将目光投向国际市场。他们积极参加各种国际展会和交流活动,与全球各地的客户和合作伙伴建立了广泛的联系。同时,EFC还根据不同国家和地区的市场需求,推出定制化的产品和服务。这种灵活多变的市场策略使EFC在国际市场上迅速崛起。

Eris Technology Corp公司的发展小趣事

面对日益激烈的国际竞争,Eris Tech开始实施全球化战略。公司通过在海外设立研发中心、生产基地和销售网络,加强与国际市场的联系和合作。同时,Eris Tech还积极参与国际标准的制定和技术交流活动,提高了公司的国际影响力和竞争力。随着全球化战略的深入实施,Eris Tech的产品已经远销全球多个国家和地区。

Cobham Semiconductor Solutions公司的发展小趣事

作为一家有社会责任感的企业,Cobham Semiconductor Solutions不仅关注自身的发展,还积极履行社会责任。公司积极参与公益事业,为社区提供支持和帮助。同时,公司还注重环保和可持续发展,采取多项措施降低生产过程中的能耗和排放。这种积极履行社会责任的态度,使得Cobham在社会各界赢得了广泛赞誉。

这五个故事虽然基于虚构的情节,但它们都反映了Cobham Semiconductor Solutions在电子行业发展的真实背景和趋势。这些故事展示了公司在技术创新、市场扩张、品质管理、人才战略和社会责任等方面的努力和成就。希望这些故事能够为您提供一个关于Cobham Semiconductor Solutions发展起来的有趣而全面的视角。

AB Connectors Ltd公司的发展小趣事

在快速发展的过程中,AB Connectors Ltd始终将品质管理放在首位。公司建立了完善的质量管理体系,从原材料采购、生产加工到产品出厂检验等各个环节都实行严格的质量控制。此外,公司还引进了先进的生产设备和检测技术,不断提高产品的精度和稳定性。这些措施有效提升了产品的品质水平,赢得了客户的信任和好评。

GSG公司的发展小趣事
检查通信接口是否连接正确,通信协议是否匹配,以及通信线路是否受到干扰或损坏。
捷茂微(GATEMODE)公司的发展小趣事
检查电源是否正常,传感器是否损坏,信号调理电路是否有问题,以及微处理器或DSP是否工作正常。

问答坊 | AI 解惑

电子电路设计与实践

初学者可以拿去参考参考…

查看全部问答>

protelDXP2004原理图修改元件参数有什么快速方法

protelDXP2004原理图修改元件参数有什么快速方法呀。一个一个改好麻烦呀。:L…

查看全部问答>

基于MSP430 单片机高精度温度测量的补偿方法

用MSP430P315 单片机的A/D 转换器,实现阻性温度传感器的电阻检测;用查表和线性插值结合的方法,简化标度变换的算法结构。对电池电压的降低进行补偿的同时分析补偿电阻的精度对温度检测的影响。 …

查看全部问答>

软件工程师的职位规划

/************************************************ *技术直接转销售还是先转技术支持再转销售好呢? ************************************************/ 我是09年毕业的,毕业的时候,是在一家医疗器材公司工作。 最近换了一家公司,是搞 ...…

查看全部问答>

请教一点关于并口驱动开发的问题

老师让做一个dsp和pc通过并口epp通信的东西,在xp下对并口操作是不是要写个驱动?老板让我用WinDriver,我想问问关于并口开发要怎样调试呢?以前没有做过关于并口通信东西,所以想请问各位老大,希望能给指点一下…

查看全部问答>

请问一下

我的程序 无法进入中断程序 可能是什么原因? 我是用的下降沿有效啊…

查看全部问答>

请教evc中如何快速移动图片

在Wince中添加一个较大的位图,设想有一个相对较小的取景框,当这个框快速移动时,我想显示屏幕上位图移动的动画效果。我在evc中代码如下:          CBitmap m_bitmap;         BITMAP bm; ...…

查看全部问答>

帮我下一个外文文献

Kaiser, J.F., Nonrecursive digital filter design using the I0-sinh window function, Proceedings of the 1974 IEEE International Symposium on Circuits and Systems (1974) 请发送邮件到donghongyong@live.cn …

查看全部问答>

uboot怎样向kenerl传递一个物理地址

现在uboot中有个物理需要传到kernel中! 我该在uboot怎样做?请各位大虾指点下!!谢谢…

查看全部问答>

(北京)迎接Linux时代的到来

4月21日(周六)东方标准特邀请嵌入式软件仿真开源(SkyEye)项目核心成员、AKA 嵌入式小组成员康烁,为大家做《利用SkyEye进行操作系统分析及SkyEye的最新进展》的讲座。 康烁--作为自由软件爱好者,精通嵌入式系统移植,驱动开发,多年嵌入式开发 ...…

查看全部问答>