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

嵌入式学习(2) - LED、BEEP、KEY及中断实验

目录

LED实验

LED初始化

LED点亮/熄灭

蜂鸣器实验

KEY & 中断

1.中断

2.中断处理的基本流程

3.通用中断控制器GIC (管理中断)

GIC核心组件

4.中断实验


开始记录具体的不同模块的裸机开发学习,以下实验都是基于C语言开发,同时要参考IMX6ULL的手册

LED实验

1.在原理图找到连接关系,确认寄存器引脚为GPIO1_IO03

2.引脚方向

GPIO1->GDIR置1为输出模式

IOMUXC_SetPinMux为实验板自带头文件里定义的函数,作用为定义复用功能

IOMUXC_SetPinConfig作用为定义电气特性

LED初始化

void led_init(void) { IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0); IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10b0); // IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x05; // IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10b0; GPIO1->GDIR |= (1 << 3); GPIO1->DR |= (1 << 3); }

LED点亮/熄灭

void led_on(void) { GPIO1->DR &= ~(1 << 3); } void led_off(void) { GPIO1->DR |= (1 << 3); }

蜂鸣器实验

常用的蜂鸣器有两种:有源蜂鸣器和无源蜂鸣器,这里的有“源”不是电源,而是震荡源,有源蜂鸣器内部带有震荡源,所以有 源蜂鸣器只要通电就会叫。无源蜂鸣器内部不带震荡源,直接用直流电是驱动不起来的,需要 2K-5K 的方波去驱动。I.MX6U-Mini 开发板使用的是有源蜂鸣器,因此只要给其供电就会工作。
通过查找底板原理图不难看出,三极管的基极连接在SNVS_TAMPER1引脚上,由此写出相关beep.c代码。
#include "MCIMX6Y2.h" #include "fsl_iomuxc.h" #include "beep.h" void beep_init(void) { IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0); IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0x10b0); //IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = 0x05; //IOMUXC_SNVS_SW_PAD_CTL_PAD_SNVS_TAMPER1 = 0x10b0; GPIO5->GDIR |= (1 << 1); GPIO5->DR |= (1 << 1); } void beep_on(void) { GPIO5->DR &= ~(1 << 1); } void beep_off(void) { GPIO5->DR |= (1 << 1); }

KEY & 中断

1.中断

CPU打断当前正在进行的工作,去处理更为紧急的任务,并且在处理完中断任务后还能回到原先的地方进行工作。

2.中断处理的基本流程

(1)中断请求:由外设(中断源)主动向CPU发出请求。

(2)中断响应条件判断:CPU检查是否允许响应此中断,以及该中断是否被屏蔽。

(3)中断优先级裁决:若同时有多个中断请求,CPU根据预设优先级决定处理顺序。

(4)保护现场:将当前任务的执行环境(如寄存器值)保存起来,以便后续恢复。

(5)执行中断服务函数:执行处理该紧急事件的特定程序代码。

(6)恢复现场:将之前保存的执行环境恢复,使原任务得以继续执行。

3.通用中断控制器GIC (管理中断)

arm中,片内外设控制器给内核(A7)发送通知,此称之为中断,这个过程中间需要经历GIC。

GIC核心组件
  • 分发器 (Distributor)

    • 负责接收所有中断源(SGI, PPI, SPI)的信号。

    • 对中断进行使能/禁用优先级划分路由分发(决定将中断发送给哪个CPU Interface)等全局管理。

  • CPU接口 (CPU Interface)

    • 每个CPU核心都有一个独立的接口。

    • 负责向连接的CPU核心提交中断请求

    • 接收CPU发出的中断响应确认处理完成信号。

4.中断实验

main.c函数

void ccm_ccgr_enable(void) { CCM->CCGR0 = 0xffffffff; CCM->CCGR1 = 0xffffffff; CCM->CCGR2 = 0xffffffff; CCM->CCGR3 = 0xffffffff; CCM->CCGR4 = 0xffffffff; CCM->CCGR5 = 0xffffffff; CCM->CCGR6 = 0xffffffff; } static void delay(unsigned int num) { while (num--) ; } void gpio1_io18_handler(void) { led_on(); beep_on(); } int main(void) { system_irq_init(); ccm_ccgr_enable(); led_init(); beep_init(); key_irq_init(); while (1) { while (1) { if (key_get_status() == 0) { led_on(); beep_on(); } else { led_off(); beep_off(); } } delay(0x80000); } return 0; }

如果是 GPIO1_Combined_16_31_IRQn(按键中断):
检查 GPIO1->ISR寄存器,确认是否是第18引脚触发。
若是,则从 irq_gpio_handler_array数组中取出并执行之前注册的 gpio1_io18_handler函数。
清除该引脚的中断标志(GPIO1->ISR |= (1 << 18))。

//初始化中断系统 void system_irq_init(void) { _set_VBAR(0x87800000); GIC_Init(); } //当GPIO1_IO18中断发生时 中断服务函数 void system_irq_handler(IRQn_Type irq_num) { switch (irq_num) { case GPI01_Combined_0_15_IRQn: case GPIO1_Combined_16_31_IRQn: { if (GPIO1->ISR & (1 << 18)) //判断是否是 GPIO1_IO18产生的中断。 { irq_gpio_handler_array[GPIO1_HANDLER_BASE + 18](); //向中断状态寄存器(ISR)的对应位写1,清除中断标志,告知硬件本次中断已处理完毕 GPIO1->ISR |= (1 << 18); } } break; default: if (irq_handler_array[irq_num]) { irq_handler_array[irq_num](); break; } } }

中断注册阶段 (request_irq函数逻辑)

这是向系统注册中断的接口。main.c通过它“预约”中断服务。

int request_irq(int irq_num, irq_handler_t handler) { if ((irq_num < IOMUXC_IRQn) || (irq_num > GPIO_IRQ_MAX)) { return -1; } if (!handler) { return -1; } switch (irq_num) { // case IOMUXC_IRQn ... PMU_IRQ2_IRQn: case GPIO1_IO0_IRQ ... GPIO1_IO15_IRQ: GIC_EnableIRQ(GPIO1_Combined_0_15_IRQn); GIC_SetPriority(GPIO1_Combined_0_15_IRQn, 0); irq_gpio_handler_array[irq_num - GPIO_IRQ_BASE - 1] = handler; break; case GPIO1_IO16_IRQ ... GPIO1_IO31_IRQ: GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); GIC_SetPriority(GPIO1_Combined_16_31_IRQn, 0); irq_gpio_handler_array[irq_num - GPIO_IRQ_BASE - 1] = handler; break; default: GIC_EnableIRQ(irq_num); GIC_SetPriority(irq_num, 0); irq_handler_array[irq_num] = handler; break; } return 0; }
http://www.cnnetsun.cn/news/1555937.html

相关文章:

  • Mapbox GL JS 3.9.1 项目实战:从注册账号到地图加载,手把手搞定 Access Token 配置
  • C++ 模板类型推断机制剖析
  • NEURAL MASK 交互设计提升:优化用户上传与结果展示界面的前端技术细节
  • AI 模型训练与推理的资源隔离
  • 终极指南:Kilo Code - 你的AI编程助手如何彻底改变开发工作流
  • 5步攻克!Open Interpreter全系统环境部署全攻略
  • TortoiseGit与GitHub高效同步:从零开始的完整指南
  • Nginx配置虚拟主机
  • 别再傻傻分不清!光纤通信里的‘传播常数β’和‘波数k’到底啥区别?
  • 【专栏二:深度学习08】-【一张图讲清楚:为什么 ReLU 也不是完美的?什么是死亡 ReLU?】
  • 3大策略精准调优OpenAI Assistant推理强度:提升AI决策质量300%
  • 【机密架构文档流出】某头部AIGC平台内部Python MCP服务基座模板(含MCP-Server v1.3.2合规认证适配层)
  • C盘清理与AI模型存储优化:管理万象熔炉·丹青幻境缓存与产出
  • 利用Zookeeper保障大数据领域的分布式系统安全
  • 超760万元奖金悬赏,谁能重构 DeepSeek 与 Kimi 的性能底层?
  • 第3.3章:StarRocks数据导入——Stream Load实战:从CSV到实时分析的完整链路
  • 告别手写C库!用Buddy-MLIR一键编译PyTorch模型到Gemmini加速器(实战避坑)
  • 如何快速搭建免费开源的机器翻译API:LibreTranslate完整指南
  • 终极指南:使用SMUDebugTool解锁AMD Ryzen处理器的隐藏性能潜力
  • s2-pro效果展示:高语速新闻播报(220字/分钟)清晰度实测
  • 腾讯优图4B模型实战:一键部署,轻松实现图片内容分析
  • 别再只会让小车跑直线了!用Arduino UNO + TB6612 + 四路循迹传感器,实现复杂路况的精准控制
  • BERT实践指南:从理论到应用的自然语言处理技术
  • Pixel Dream Workshop 创意爆发:十组高级提示词(Prompt)与生成作品赏析
  • 7个革新性的REFramework应用技巧:游戏开发者的效率提升指南
  • PCB文件查看工具探索:OpenBoardView如何突破电路分析效率瓶颈
  • Clawdbot汉化版实战落地:跨境电商团队WhatsApp多语种客服系统
  • 南北阁Nanbeige 4.1-3B入门必看:软件测试用例的智能生成与评审
  • Arduino离线安装esp32/esp8266:一键式解决方案与版本避坑指南
  • opencode单元测试生成:Python/JS/C++覆盖率对比