ARM嵌入式学习(四)--- C语言应用:led、beep、key

目录

一、代码部分

1.汇编部分

2.主函数main.c

3.LED、BEEP、KEY功能代码

(1)led灯

(2)beep蜂鸣器

(3)key按键

二、makefile

[1.Makefile 执行流程](#1.Makefile 执行流程)

[2.Makefile 关键注意事项](#2.Makefile 关键注意事项)

一、代码部分

1.汇编部分

cs 复制代码
.global _start
 
_start:
    ldr pc, =_reset_handler
    ldr pc, =_software_handler
    ldr pc, =_undef_handler
    ldr pc, =_prefetch_abort_handler
    ldr pc, =_data_abort_handler
    nop
    ldr pc, =_irq_handler
    ldr pc, =_fiq_handler
 
_software_handler:
    b _software_handler
 
_undef_handler:
    b _undef_handler
 
_prefetch_abort_handler:
    b _prefetch_abort_handler
 
_data_abort_handler:
    b _data_abort_handler
 
_irq_handler:
    b _irq_handler
 
_fiq_handler:
    b _fiq_handler
 
_reset_handler:
    /*DDR    0x80000000 ~ 0xA0000000*/
    cpsid i             /*disable irq*/
    ldr sp, =0x81000000 /*init system mode  stack  16M   */
    cps #0x12           /*change to irq mode */
  
    ldr sp, =0x82000000 /*init irq mode stack  16M */
 
    cps #0x1f           /* change to system mode */
   
 
    ldr sp, =0x83000000 /*init irq mode stack  16M */
    cpsie i     /* enable  irq */
    bl main
 
 
code_end:
    b code_end

从汇编部分跳转(bl)到main函数

2.主函数main.c

cs 复制代码
#include "MCIMX6Y2.h"
#include "beep.h"
#include "fsl_iomuxc.h"
#include "key.h"
#include "led.h"

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--)
    ;
}

int main(void)
{
  ccm_ccgr_enable();
  led_init();
  beep_init();
  key_init();
  while (1)
  {
    if (key_get_value())
    {
      led_on();
      beep_on();
    }
    else
    {
      led_off();
      beep_off();
    }

    delay(0x80000);
  }

  return 0;
}

注意:在ARM汇编初始化阶段,切换工作模式后一定要初始化栈 ,这是非常关键且必须遵守的规则。因为ARM处理器的不同工作模式(如IRQ模式、系统模式等)各自拥有独立的栈指针SP,互不共享、互不继承。当CPU进入异常或中断时会自动切换到对应模式,如果该模式下的栈指针SP没有预先设置为合法有效的内存地址,CPU在压栈保存现场时就会使用无效或随机地址,直接导致程序跑飞、死机或数据损坏。因此在启动汇编中,每执行一次cps指令切换到新的工作模式,都必须紧跟一条ldr sp,=地址指令,为当前模式设置合法栈空间,保证中断、异常以及C语言运行时的栈操作安全可靠。

3.LED、BEEP、KEY功能代码

(1)led灯

cs 复制代码
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "led.h"

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);
}

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

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

(2)beep蜂鸣器

cs 复制代码
#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);
}

(3)key按键

cs 复制代码
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "key.h"

void key_init(void)
{
    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
    IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0x10b0);

    GPIO1->GDIR &= ~(1 << 18);
}

int key_get_value(void)
{
    if(GPIO1->DR & (1<<18))
        return 0;
    else
        return 1;
}

新知识:BSP、SDK

BSP板级支持包 ,简单来说就是对底层硬件操作进行封装的功能代码集合。它将直接操作寄存器、配置硬件参数等复杂底层逻辑,封装成简洁易用的接口函数,比如 adc_init、i2c_read、led_on 等,让上层程序可以方便地控制 LED、ADC、I2C、UART 等外设,而不用关心具体硬件细节,是衔接上层应用与底层硬件的关键代码层。

SDK**(Software Development Kit,软件开发工具)** 是芯片厂家(如 NXP、ST)官方提供的完整开发资源包,包含已经写好的底层驱动库、寄存器定义头文件、工具、示例代码和驱动 API。它屏蔽了复杂的寄存器操作,让开发者不用研究底层硬件细节,直接调用官方提供的标准化函数就能快速完成开发,是开发芯片的基础软件包,通用性强,适用于同型号的所有芯片。

二、makefile

makefile代码:

cs 复制代码
target = key



cross_compiler = arm-linux-gnueabihf-



cc = $(cross_compiler)gcc

ld = $(cross_compiler)ld

objcopy = $(cross_compiler)objcopy

objdump = $(cross_compiler)objdump



incdirs = bsp sdk

srcdirs = bsp project



include = $(patsubst %, -I%, $(incdirs))



cfiles = $(foreach dir, $(srcdirs), $(wildcard $(dir)/*.c))

sfiles = $(foreach dir, $(srcdirs), $(wildcard $(dir)/*.S))



cfilenodir = $(notdir $(cfiles))

sfilenodir = $(notdir $(sfiles))



cobjs = $(patsubst %, obj/%, $(cfilenodir:.c=.o))

sobjs = $(patsubst %, obj/%, $(sfilenodir:.S=.o))



objs = $(cobjs) $(sobjs)



VPATH = $(srcdirs)



$(target).bin : $(objs)

	$(ld) -Timx6ull.lds -o$(target).elf $^

	$(objcopy) -O binary -S -g $(target).elf $@

	$(objdump) -D $(target).elf > $(target).dis



$(sobjs) : obj/%.o : %.S

	@mkdir -p obj

	$(cc) -Wall -nostdlib -c $(include) -o $@ $<



$(cobjs) : obj/%.o : %.c

	@mkdir -p obj		

	$(cc) -Wall -nostdlib -c $(include) -o $@ $<



.PHONY : clean

clean:

	rm -rf $(objs) $(target).elf $(target).bin $(target).dis



load:

	./imxdownload ./$(target).bin /dev/sdb

1.Makefile 执行流程

  1. 找到所有 .c.S
  2. 编译成 .o 文件(只编译不链接)
  3. 把所有 .o 链接成 .elf
  4. 转成 .bin 可烧录文件
  5. 生成反汇编文件
  6. 可以 clean 清理、load 烧录

2.Makefile 关键注意事项

  1. Makefile 编译时必须生成 .o 文件(只编译不链接),不能直接使用 .c 文件编译,否则会导致重复编译、效率低下,且无法实现按需更新和正确的链接流程。

  2. Makefile 的 OBJ 目标文件列表中,start.o 必须放在最前面,main.o 等文件放在后面。因为程序启动需要先执行汇编启动代码完成硬件初始化、栈设置等工作,若 main.o 在前,链接器会先执行 main 函数,导致程序运行崩溃。

  3. Makefile 内的通配符区分规则:%.s和 %.o中的 %是 Makefile 自带的通配符语法;*.o中的 * 属于 Shell 命令通配符,二者使用场景和规则不同,不能混用。

  • 所有文件先编译成 .o,最后才链接
  • .o 放在 obj 目录,不污染源码
  • 自动找源码,不用手动写文件列表
  • 最终生成 .bin 用于烧录
  • 自动包含头文件路径
相关推荐
Q741_1472 小时前
每日一题 力扣 2751.机器人碰撞 映射 模拟 栈 C++ 题解
算法·leetcode·模拟··映射
源码之家2 小时前
计算机毕业设计:基于Python的二手车数据分析可视化系统 Flask框架 可视化 时间序列预测算法 逻辑回归 requests 爬虫 大数据(建议收藏)✅
大数据·hadoop·python·算法·数据分析·flask·课程设计
以太浮标2 小时前
华为eNSP模拟器 - 设备及技术栈场景全维度解析
运维·网络·网络协议·网络安全·华为·负载均衡·信息与通信
liuyao_xianhui2 小时前
优选算法_岛屿数量_floodfill算法)_bfs_C++
java·开发语言·数据结构·c++·算法·链表·宽度优先
落羽的落羽2 小时前
【Linux系统】入门线程:线程介绍与线程控制
linux·服务器·c++·人工智能·stm32·单片机·机器学习
墨者阳2 小时前
数据库自动化指标采集与智能评分系统实践与构想
运维·数据库·自动化
清平乐的技术专栏2 小时前
Obsidian使用指南
运维
t5y222 小时前
【Linux】进程
linux
羊小蜜.2 小时前
Mysql 04: 子查询——5 大核心用法
数据库·mysql·算法·子查询