| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> stm32 按键外部中断开发代码 可对照database理解,汇编代码看中文注释即可 -> 正文阅读 |
|
[嵌入式]stm32 按键外部中断开发代码 可对照database理解,汇编代码看中文注释即可 |
#include?<stm32mp1xx_gpio.h> #include?<stm32mp1xx_exti.h> #include?<stm32mp1xx_gic.h> #include?<stm32mp1xx_rcc.h> void?hal_gpio_init(void); void?hal_exti_init(void); void?hal_gicd_init(void); void?hal_gicc_init(void); extern?void?printf(const?char?*fmt,?...);
void?mydelay_ms(int?ms) { ????int?i,?j; ????while(ms--) ????{ ????????for?(i?=?0;?i?<?10000;?i++) ????????????for?(j?=?0;?j?<?10000;?j++); ????} }
void?do_irq(void) { ????unsigned?int?irq_num; ????irq_num?=?GICC.IAR?&?(0x3FF); ????switch(irq_num) ????{ ????????case?38: ????????????//?中断处理程序,此处只打印一条语句 ????????????printf("put?on?\n"); ????????????EXTI.FPR1?|=?(0x1?<<?0);??????????//下降边沿挂起寄存器??写0防止一直进入 ????????????GICD.ICPENDR[1]?|=?(0x1?<<?6);??????//?清除GICD层中断?挂起清除 ????????????break; ????????case?39: ????????????break; ????} ????//?清除GICC层中断?将38号写进去结束 ????GICC.EOIR?=?(GICC.EOIR?&?(~0x3FF))?|?irq_num; }
void?hal_gpio_init(void) { ????//?使能GPIOA组的时钟使能,?在??RCC_MP_AHB4ENSETR ????RCC.MP_AHB4ENSETR?|=?(0x1?<<?0); ????GPIOA->MODER?&=?(~0x3?<<?0);???????????????????//按键配置??????输入功能 ????GPIOA->PUPDR?&=?~(0x3?<<?0);???????????????????//无上、下拉 } /* ?*?PA0引脚对应的外部中断事件是EXTI[0] ?*?对应着Event?Input?0 ?*?具体的外设和EXTI对应的关系在21.3章节 ?*?按键中断设置为下降沿触发中断事件的检测 ?*?*/ void?hal_exti_init(void) { ????//?设置为下降沿触发选择寄存器 ????EXTI.FTSR1?|=?(0x1?<<?0); ????//?设置外部中断选择寄存器?连接到PA0上 ????EXTI.EXTICR1?&=?(~(0xff?<<?0)); ????//?设置EXTI?CPU1唤醒中断屏蔽寄存器 ????EXTI.C1IMR1?|=?(0x1?<<?0); ????//?设置EXTI?CPU1唤醒事件屏蔽寄存器 //??EXTI.C1EMR1?|=?(0x1?<<?0); } /* ?*?PA0引脚属于EXTI0 ?*?EXTI0?对应的中断ID为?38 ?*?对应关系在芯片手册的21.2章节 ?*?*/ void?hal_gicd_init(void) { ????GICD.ISENABLER[1]?|=?(0x1?<<?6);????????????????????????????????????????????????//中断号为38??GICD中断使能 ????GICD.IPRIORITYR[9]?&=?~(0x1f?<<?19); ????GICD.IPRIORITYR[9]?|=??(0x10?<<?19);????????????????????????????????????????????//中断优先级,设置为16 ????GICD.ITARGETSR[9]?|=?(0x3?<<?16);?????//选择处理器处理控制器转发的中断??但是为啥写0x3??????????????????????????????????????????//中断处理器目标寄存器 ????GICD.CTLR?|=?(0x1?<<?0);????????????????????????????????????????????????????????//全局使能 ????//由于默认38号外部中断用group?0?处理所以这里不用设置组别 } void?hal_gicc_init(void) { ????GICC.CTLR?|=?(0x1?<<?0);????????//?设置GICC层?中断全局使能寄存器??enable?group?0?interrupts ????GICC.PMR?|=?(0x1f?<<?3);????????//?设置GICC层?中断屏蔽寄存器? }
int?main() { ????hal_gpio_init(); ????hal_gicc_init(); ????hal_gicd_init(); ????hal_exti_init();
????while(1) ????{ ????} ????return?0; } 汇编代码: .text .global?_start _start: ????????b???????reset ????????ldr?????pc,_undefined_instruction ????????ldr?????pc,_software_interrupt ????????ldr?????pc,_prefetch_abort ????????ldr?????pc,_data_abort ????????ldr?????pc,_not_used ????????ldr?????pc,_irq?//跳转到_irq标志处 ????????ldr?????pc,_fiq _undefined_instruction:?.word??_undefined_instruction _software_interrupt:????.word??_software_interrupt _prefetch_abort:????????.word??_prefetch_abort _data_abort:????????????.word??_data_abort _not_used:??????????????.word??_not_used _irq:???????????????????.word??irq_handler??//跳转到irq_handler标志处 _fiq:???????????????????.word??_fiq //????mrc?p15,0,r0,c1,c1,2 //??movw??????r1,?#0x3fff //??movt??????r1,?#0x0004 //??orr??r0,r0,r1 //????mcr??p15,0,r0,c1,c1,2 reset: ????ldr?r0,=?_start ????mcr?p15,0,r0,c12,c0,0???????//?通过协处理器将中断向量表地址定向到最前面的_start,如果一有IRQ发生,就跳到_start寻找irq异常 ????????mrs?????r0,cpsr ????????bic?????r0,r0,#0x1f ????????orr?????r0,r0,#0xd3 ????????msr?????cpsr,r0????????//??Enable?svc?mode?of?cpu
init_stack: ????????ldr?????r0,stacktop?????????/*get?stack?top?pointer*/ ????/********svc?mode?stack********/ ????????mov?????sp,r0 ????????sub?????r0,#128*4??????????/*512?byte??for?irq?mode?of?stack*/ ????/****irq?mode?stack**/ ????????msr?????cpsr,#0xd2 ????????mov?????sp,r0 ????????sub?????r0,#128*4??????????/*512?byte??for?irq?mode?of?stack*/ ????/***fiq?mode?stack***/ ????????msr?????cpsr,#0xd1 ????????mov?????sp,r0 ????????sub?????r0,#0 ????/***abort?mode?stack***/ ????????msr?????cpsr,#0xd7 ????????mov?????sp,r0 ????????sub?????r0,#0 ????/***undefine?mode?stack***/ ????????msr?????cpsr,#0xdb ????????mov?????sp,r0 ????????sub?????r0,#0 ???/***?sys?mode?and?usr?mode?stack?***/ ????????msr?????cpsr,#0x10 ????????mov?????sp,r0?????????????/*1024?byte??for?user?mode?of?stack*/
????bl?main ????.align??4 ????/****??swi_interrupt?handler??****/
????/****??irq_handler??****/ irq_handler: ????sub??lr,lr,#4???//因为三级流水线的原因,中断模式lr保存的地址的下下条指令的地址,如果我们从中断回来后想跳到下一条指令,那么这里需要人为的 ????//对lr进行-4操作 ????stmfd?sp!,{r0-r12,lr}//对r0-r12寄存器为IRQ和user模式的共有寄存器,转到IRQ模式之后需要将她们压栈保护现场,对lr进行压栈防止在下面指令中lr被修改就回不去中断之前的地方了 ????.weak?do_irq ????bl??do_irq??//跳到中断处理函数中??这个处理函数是用c语言写的 ????ldmfd?sp!,{r0-r12,pc}^?//1.将r0-r12出栈?2.将lr直接压到PC返回中断前的位置?3.^符号是将spsr寄存器中存好的中断之前的cpsr状态 ????//给到user模式中的cpsr寄存器 stacktop:????.word??????stack+4*512 .data stack:???.space??4*512 loop: ????b?loop ????.end
|
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 1:35:18- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |