当前位置: 首页 > news >正文

ARM 实操 流水灯 按键控制 day53

五:异常处理

ARM 有两级外部中断 FIQ,IRQ.

可是大多数的基于ARM 的系统有有>2个的中断源,因此需要一个中断控制器

ps:通常中断处理程序总是应该包含清除中断源的代码

为什么:外设或事件(比如定时器溢出、GPIO 变化、串口接收)会设置一个中断挂起标志位(pending flag)。CPU 检测到这个标志后,进入中断服务程序(ISR)。如果这个标志位不被清除,那么:ISR 执行结束时,CPU 发现中断源还在挂起 → 马上再次进入 ISR。程序就可能死在中断里,永远不回到主程序。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中保存返回地址到LR ,软中断pc会默认跳到8

看图的右边偏移量对应就是每种异常pc默认回到的地址

返回时,需要手动:恢复spsr

一:异常规范函数

	preserve8area reset, code, readonlycode32entry
;这里就是异常向量表   预设b start   	; resetnop       	; undefb deal_swi	; swinop			; prefetch abortnop			; data abortnop			; reservednop			; irqnop			; fiqdeal_swi	;预设stmfd sp!, {r4-r12, lr}	  sub r0,lr,#4 	;获取软中断的地址,是中断返回下一个 - 4ldr r1,[r0]		;把r0内存空间的数据放入r1,[]类似于*运算,看地址拿数据,这样swi #5,的机器码5就能取出来bic rl, r1,#(0xff << 24)	;清高8位ldmfd sp!, {r4-r12, pc}^	;^异常处理专用的带模式切换   startldr sp, =0x40001000	  mrs r0, cpsrbic r0, r0, #0x1forr r0, r0, #0x10msr cpsr_c, r0	   ldr sp, =0x40000C00	   swi #5	 ;软中断 范围:0~0xffffff  6个fmov r0, #1mov r1, #2import c_add	bl c_add	 nop     b startexport asm_add	   
asm_addstmfd sp!, {r4-r12, lr}	  add r0, r0, r1ldmfd sp!, {r4-r12, pc}  end	
1.1实现switch,借助C程序
void c_deal_swi(unsigned char swi_num)
{switch(swi_num){case 1: break;case 5:break;default:break;}
}
deal_swi	stmfd sp!, {r4-r12, lr}	  sub r0,lr,#4 	ldr r1,[r0]		bic r0, r1,#(0xff << 24)	;寄存器一开始放在r0import c_deal_swibl c_deal_swildmfd sp!, {r4-r12, pc}^	

六:输入/输出

一:端口控制描述

端口配置寄存器(GPACON至GPJCON)/ 配直引脚功能

​ S3C2440A 中,大多数端白为复用引脚。因此要决定每个引脚选择哪项功能。PnCON(引脚控制寄存器)决定了每个引脚使用哪项功能。如果在掉电模式中PE0至PE7用于唤醒信号,这些端口必须配置为输入模式。

端口数据寄存器(GPADAT至GPJDAT)/读(采集)写(控制)数据(电平)

​ 如果端口配置为输出端口,可以写入数据到PnDAT的相应位。如果端口配置为输入端口,可以从PnDAT的相应位读取数据。

二:点亮LED1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

//C编程给地址赋值
int a = 10;                // a 的地址假设为 0x1000
int *p = &a;               // p 的值 = 0x1000
unsigned int b = (unsigned int)p; // b = 0x1000(p 的地址值被复制给 b)
*(unsigned int*)b = 200;    // 通过 b 修改 0x1000 地址的值
	preserve8area reset, code, readonlycode32entryb start   	; resetnop       	; undefb deal_swi	; swinop			; prefetch abortnop			; data abortnop			; reservednop			; irqnop			; fiqdeal_swistmfd sp!, {r4-r12, lr}	  ;保护现场sub r0, lr, #4ldr r1, [r0]bic r0, r1, #(0xff << 24)import c_deal_swibl c_deal_swildmfd sp!, {r4-r12, pc}^   ;恢复现场startldr sp, =0x40001000	   ;初始化SVC模式的栈mrs r0, cpsrbic r0, r0, #0x1forr r0, r0, #0x10msr cpsr_c, r0	   	;设置工作模式位userldr sp, =0x40000C00	   ;初始化user模式的栈;swi #5	 ;软中断指令; 函数的调用规则; 前四个参数使用r0-r3传递,剩余参数使用栈传递; 返回值存放在r0中mov r0, #1mov r1, #2import main	;声明一个外部符号供本文件使用bl main	  ;带链接返回的跳转   自动保存返回地址到lr nop      ;空转1个机器周期b startend 
#define GPBCON (*(volatile unsigned long * )0x56000010UL)
#define GPBDAT (*(volatile unsigned long * )0x56000014UL)int main(void)
{// 1. 配置GPB5为输出模式(假设bit10-11控制GPB5)GPBCON = (GPBCON & ~(0x03 << 10)) | (0x01 << 10);// 2. 持续输出低电平(仅影响GPB5)while(1){GPBDAT &= ~(1 << 5);  // GPB5=0// 如果需要高电平:GPBDAT |= (1 << 5);}return 0;
}
一:volatile 易失性修饰符(写透)

每次读取值的时候,都操作的是内存,

这样就会在缓冲区操作后,立马写入内存的值,写在内存

二:移位

配置1bit一步完成配置多个bit两步完成先清0再置1配置GPB5引脚功能为输出

三:代码
#ifndef __LED_H
#define __LED_H#define GPBCON (*(volatile unsigned long * )0x56000010UL)
#define GPBDAT (*(volatile unsigned long * )0x56000014UL)void led_init(void);
void led_on(unsigned int num);
void led_off(unsigned int num);
void Delay_ms(unsigned int num);#endif#include "led.h"void Delay_ms(unsigned int num)		
{unsigned char i, j;while(num--){i = 2;j = 199;do{while (--j);} while (--i);}
}void led_init(void)
{GPBCON = (GPBCON & ~(0x03 << 10)) | (0x01 << 10);GPBCON = (GPBCON & ~(0x03 << 12)) | (0x01 << 12);GPBCON = (GPBCON & ~(0x03 << 14)) | (0x01 << 14);GPBCON = (GPBCON & ~(0x03 << 16)) | (0x01 << 16);GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);	}void led_on(unsigned int num)
{GPBDAT &= ~(1 << (num+4));		}void led_off(unsigned int num)
{GPBDAT |= (1 << (num+4));		//¹ØµÆ	}
#include "led.h"int main(void)
{unsigned char i;led_init();while(1){for(i=1; i<=4; i++){led_on(i);              // µãÁÁµ±Ç°LEDDelay_ms(200);          // ±£³ÖµãÁÁled_off(i);             // ¹Ø±Õµ±Ç°LED     }}return 0;
}

三:按键k1控制LED1

#ifndef __KEY1_H
#define __KEY1_H#define GPGCON (*(volatile unsigned long * )0x56000060UL)
#define GPGDAT (*(volatile unsigned long * )0x56000064UL)void key_init(void);
unsigned char key_on(void);#endif#include "key1.h"void key_init(void)
{GPGCON = GPGCON & ~0x03;}unsigned char key_on(void)
{return (GPGDAT & 0x01) ? 0 : 1;	
}
int main(void)
{led_init();key_init();while(1){if(1 == key_on()){led_on(1);}else{led_off(1);}}return 0;
}
http://www.xdnf.cn/news/1292995.html

相关文章:

  • 部署 Docker 应用详解(MySQL + Tomcat + Nginx + Redis)
  • SQL详细语法教程(二)--DML(数据操作语言)和DQL(数据查询语言)
  • 【IntelliJ IDEA】如何在pom.xml中去除maven中未使用的依赖
  • 存量竞争下的破局之道:品牌与IP的双引擎策略|创客匠人
  • LeetCode 分类刷题:1004. 最大连续1的个数 III
  • PHP imagick扩展安装以及应用
  • 机器学习-Cluster
  • Java项目中地图功能如何创建
  • 机器学习阶段性总结:对深度学习本质的回顾 20250813
  • csp知识基础——贪心算法
  • 类和对象(中下)
  • 图像分类-动手学计算机视觉10
  • JDK17下载与安装图文教程(保姆级教程)
  • 基于DDPG的车辆纵向速度控制优化:兼顾速度与乘坐舒适性
  • 《Python学习之基础语法1:从零开始的编程之旅》
  • k8s资源管理
  • GPT-o3回归Plus用户,GPT5拆分三种模式,对标Grok
  • 什么是HTTP的无状态(举例详解)
  • 【C++详解】用红黑树封装模拟实现mymap、myset
  • 【C++】哈希的应用:位图和布隆过滤器
  • Query通过自注意力机制更新(如Transformer解码器的自回归生成)的理解
  • 【Java web】HTTP 与 Web 基础教程
  • 最新去水印小程序系统 前端+后端全套源码 多套模版 免授权
  • 弹性扩展新范式:分布式LLM计算的FastMCP解决方案
  • 可视化调试LangChain SQLChatMessageHistory:SQLite数据库查看全攻略
  • 6 ABP 框架中的事件总线与分布式事件
  • 服务器安全检测与防御技术总结
  • 比特币与区块链:去中心化的技术革命
  • Java毕业设计选题推荐 |基于SpringBoot的水产养殖管理系统 智能水产养殖监测系统 水产养殖小程序
  • TensorFlow实现回归分析详解