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

《嵌入式硬件(九):基于IMX6ULL的蜂鸣器操作》

一、链接脚本

内存段(Memory Segments)总结

1 .bss段

         用于存放未初始化或初始化为0的数据

         在运行时会被自动清零

 典型例子:

static int bss_var;           // 静态变量(全局或局部)int explicit_var = 0;         // 显式初始化为0的全局变量

2. COMMON段

        用于存放未初始化的非静态全局变量

        链接时才确定最终大小和位置

        允许多个目标文件定义同名符号

典型例子:

int common_var;               // 未初始化的非静态全局变量

3. data段

        用于存放已初始化的全局变量和静态变量(非零值)

        需要在程序文件中保存实际的初始值

典型例子:

int global_var = 100;         // 初始化为非零值int global_array[] = {1,2,3}; // 初始化为非零数组

4.rodata段(只读数据段)

        存放程序的只读数据

        运行时受保护,不可修改

包含的数据类型:

  1) 字符串常量

  2)const修饰的全局变量

  3) 全局只读数组

  4) switch跳转表

  5) 浮点数常量

 典型例子:

const int MAX_VALUE = 100;    // const全局变量char* str = "Hello World";    // 字符串常量const int lookup[] = {1,2,3}; // 只读数组

各段的特点比较

段名初始化运行时可写链接特性
.bss自动清零可写编译时确定大小
COMMON自动清零可写链接时确定大小
.data需要初始值可写编译时确定大小
.rodata需要初始值只读编译时确定大小

关于段名中的通配符说明

在链接脚本中,经常会看到类似*(.rodata*)这样的写法,这里包含两个*通配符,它们有不同的含义:

1. 第一个`*`:

   - 表示收集所有输入文件中的相关段

   - 如果不加这个`*`,就只会收集特定文件的段

2. 第二个`*`(如`rodata*`中的`*`):

   - 用于匹配所有以`.rodata`开头的段名

   - 实际编译时会产生多种rodata相关的段,例如:

     - `.rodata`:基本的只读数据段

     - `.rodata.str1.1`:长度为1字节对齐的字符串常量

     - `.rodata.str1.4`:长度为4字节对齐的字符串常量

     - `.rodata.cst8`:8字节常量(如double类型的常量)

     - `.rodata.cst4`:4字节常量(如float类型的常量)

如果只写`*(.rodata)`而不是`*(.rodata*)`:

- 只会收集严格命名为`.rodata`的段

- 其他相关的只读数据段(如`.rodata.str1.1`等)会被遗漏

- 这些被遗漏的数据可能导致程序无法正常工作

这种通配符的使用是链接脚本中的常见做法,类似的还有:

- `*(.text*)`:收集所有代码相关的段

- `*(.data*)`:收集所有数据相关的段

脚本代码

SECTIONS    
{. = 0X87800000;.text :{obj/start.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : {*(.data)}. = ALIGN(4) ;__bss_start = .;.bss ALIGN(4) : {*(.bss) *(COMMON)}__bss_end = .; 
}

.为定位计数器,当前位置;ALIGN(4),四字节对齐; __bss_start = .和__bss_end = .保存bss段的地址,对他进行清零; 

二、蜂鸣器原理

        1.底板原理图

                有源蜂鸣器:有震荡源,通过电流就响

                低电平导通,响

                需要把它的默认属性改为GPIO,要把他当外设

        2.功能复用

        3.电气属性

        4.输入输出方向

        5.数据寄存器

三、步骤

                1)初始化时钟

                2)设置引脚功能复用(GPIO)

                3)引脚电气属性(功率、电阻)

                4)设置外设引脚的输入输出方向

                5)设置数据寄存器拉低/拉高电平

四、代码

        1.结构

        2.bsp

            1)beep.c   
#include "beep.h"
#include "fsl_iomuxc.h"void init_beep(void)
{IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0);IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0x10B0);GPIO5->GDIR |= (1 << 1);
}void beep_on(void)
{GPIO5->DR &= ~(1 << 1);
}void beep_off(void)
{GPIO5->DR |= (1 << 1);
}void beep_nor(void)
{GPIO5->DR ^= (1 << 1);
}
 2)beep.h
#ifndef _BEEP_H_
#define _BEEP_H_extern void init_beep(void);
extern void beep_on(void);
extern void beep_off(void);
extern void beep_nor(void);#endif
        3)led.c
        4)led.h

        3.project

        1)main.c
#include "led.h"
#include "beep.h"
#include "MCIMX6Y2.h"void enable_clocks(void)
{CCM->CCGR0 = 0xFFFFFFFF;CCM->CCGR1 = 0xFFFFFFFF;CCM->CCGR2 = 0xFFFFFFFF;CCM->CCGR3 = 0xFFFFFFFF;        CCM->CCGR4 = 0xFFFFFFFF;CCM->CCGR5 = 0xFFFFFFFF;CCM->CCGR6 = 0xFFFFFFFF;  
}void delay(unsigned int n)
{while(n--);
}int main(void)
{enable_clocks();init_led();init_beep();while(1){led_nor();beep_nor();delay(0xFFFFF);}return 0;
}
        2)start.S
.global _start_start:ldr pc, =_reset_handlerldr pc, =_undefine_handlerldr pc, =_svc_handlerldr pc, =_prefetch_abort_handlerldr pc, =_data_abort_handlerldr pc, =_reserved_handlerldr pc, =_irq_handlerldr pc, =_fiq_handler_undefine_handler:ldr pc, =_undefine_handler_svc_handler:ldr pc, =_svc_handler_prefetch_abort_handler:ldr pc, =_prefetch_abort_handler_data_abort_handler:ldr pc, =_data_abort_handler_reserved_handler:ldr pc, =_reserved_handler_irq_handler:ldr pc, =_irq_handler_fiq_handler:ldr pc, =_fiq_handler_reset_handler:mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x12   //irqmsr cpsr, r0ldr sp, =0x80600000mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x1F   //systemmsr cpsr, r0   ldr sp, =0x80400000bl _bss_clearb main_bss_clear:ldr r0, =__bss_startldr r2, =__bss_end
loop:mov r1, #0str r1, [r0]add r0, r0, #4cmp r0, r2blt loopbx lrfinished:b finished


文章转载自:

http://vcLTsN2i.qbfwb.cn
http://FwPR2iw5.qbfwb.cn
http://Wrh7MBeQ.qbfwb.cn
http://Tt6kpAiN.qbfwb.cn
http://yBOpCqaD.qbfwb.cn
http://3b7wwFBV.qbfwb.cn
http://K67cKFUn.qbfwb.cn
http://yBK6nPAt.qbfwb.cn
http://HBe1B8vy.qbfwb.cn
http://5kICR5L5.qbfwb.cn
http://2biHYhoz.qbfwb.cn
http://qPwyW7jM.qbfwb.cn
http://FoBVwE2Y.qbfwb.cn
http://SzmSzZc4.qbfwb.cn
http://FVOHGk0l.qbfwb.cn
http://ZHfp17oq.qbfwb.cn
http://8AztnCsr.qbfwb.cn
http://ORZeVo4I.qbfwb.cn
http://mwFKyXWX.qbfwb.cn
http://XPMgnStT.qbfwb.cn
http://MlyvTiZ0.qbfwb.cn
http://ZJl2NRqT.qbfwb.cn
http://OHobZXcz.qbfwb.cn
http://ljp6HqW4.qbfwb.cn
http://wYS1YpEC.qbfwb.cn
http://b9fwmUih.qbfwb.cn
http://07yy3dp5.qbfwb.cn
http://Y0FewtAb.qbfwb.cn
http://bg9sSR88.qbfwb.cn
http://ftfy00uH.qbfwb.cn
http://www.dtcms.com/a/383191.html

相关文章:

  • 《嵌入式硬件(十二):基于IMX6ULL的时钟操作》
  • Redis最佳实践——性能优化技巧之监控与告警详解
  • PySpark基础例题(包含map、reduceByKey、filter、sortBy等算子)
  • 导购APP佣金模式的分布式锁实现:基于Redis的并发控制策略
  • 运维自动化工具Ansible大总结20250914
  • Linux 库开发入门:静态库与动态库的 2 种构建方式 + 5 个编译差异 + 3 个加载技巧,新手速看
  • Effective Python 第28条:Python列表推导式的简洁与复杂性管理
  • 【MySQL】从零开始学习MySQL:基础与安装指南
  • 基于STM32的病人监护系统
  • Python与Go结合
  • AI大师系列——杰夫·辛顿(深度学习)
  • Unity核心概念⑨:Screen
  • 《MLB美职棒大联盟》专业运动员标准·棒球1号位
  • reversed()方法
  • Altium Designer(AD24)另存为功能介绍
  • OD C卷 - 计算三叉搜索树的高度
  • 导购返利APP的数据库性能优化:索引设计与查询调优实践
  • pretrain-Alignment范式的强大与极限——李宏毅大模型2025第五讲笔记
  • CSP集训错题集 第一周
  • MCU软件驱动分离
  • 浏览器中javascript时间线,从加载到执行
  • SP‘24 SSRFuzz论文学习
  • 【算法】day2 双指针+滑动窗口
  • 拆解 AI 大模型 “思考” 逻辑:从数据训练到推理输出的完整链路
  • Axios在鸿蒙应用开发中的使用
  • Go高性能双端队列Deque实战指南
  • StringBuilder 深度解析:数据结构与扩容机制的底层细节
  • Altium Designer(AD24)自学资源介绍
  • cs144 lab0学习总结
  • Playwright MCP浏览器自动化指南