汇编编程驱动LED

  • 基于STM32MP157

汇编版

点亮LED

z80 复制代码
.text
.global _start
_start:
    /* LED1灯的初始化 */
    /* 1. 使能GPIOE外设的时钟源
    RCC_MP_AHB4ENSETR[4] = 0b1 寄存器地址 = 0x50000A28 */
    
    ldr r0, =0x50000A28 @ 准备地址
    ldr r1, [r0] @ 将地址中的数据读到寄存器中
    orr r1, r1, #(0x1 << 4) @ 修改对应的位,保持其他位不变
    str r1, [r0] @ 将修改的结果写回到寄存器中
    
    /* 2. 配置PE10引脚为输出模式
    GPIOE_MODER[21:20] = 0b01 寄存器地址 = 0x50006000 */
    
    ldr r0, =0x50006000
    ldr r1, [r0]
    and r1, r1, #(~(0x3 << 20))
    orr r1, r1, #(0x1 << 20)
    str r1, [r0]
    
    /* 3. 配置PE10引脚为推挽输出
    GPIOE_OTYPER[10] = 0b0 寄存器地址 = 0x50006004 */
    
    ldr r0, =0x50006004
    ldr r1, [r0]
    and r1, r1, #(~(0x3 << 10))
    str r1, [r0]
    
    /* 4. 配置PE10引脚为低速模式
    GPIOE_OSPEEDR[21:20] = 0b00 寄存器地址 = 0x50006008 */
    
    ldr r0, =0x50006008
    ldr r1, [r0]
    bic r1, r1, #(0x3 << 20)
    str r1, [r0]
    
    /* 5. 配置PE10引脚禁止上和核下拉电阻
    GPIOE_PUPDR[21:20] = 0b00 寄存器地址 = 0x5000600C */
    
    ldr r0, =0x5000600C
    ldr r1, [r0]
    and r1, r1, #(~(0x3 << 20))
    str r1, [r0]
    
    /* 裸机开发中,必须有一个死循环,防止程序跑飞 */
loop:
    /* 循环点亮或者熄灭LED灯 */
    /* 1. 配置PE10引脚输出高电平, LED1灯亮
    GPIOE_ODR[10] = 0b1 寄存器地址 = 0x50006014 */
    
    ldr r0, =0x50006014
    ldr r1, [r0]
    orr r1, r1, #(0x1 << 10)
    str r1, [r0]
    bl delay_1s
    
    /* 2. 配置PE10引脚输出低电平, LED1灯灭
    GPIOE_ODR[10] = 0b0 寄存器地址 = 0x50006014 */
    
    ldr r0, =0x50006014
    ldr r1, [r0]
    bic r1, r1, #(0x1 << 10)
    str r1, [r0]
    bl delay_1s
    b loop
    
@ 大概 1s的延时函数
delay_1s:
    mov r3, #0x10000000
    mm:
    cmp r3, #0
    subne r3, r3, #1
    bne mm
    mov pc, lr
.end
  • 编译程序
bash 复制代码
arm-linux-gnueabihf-gcc -c led.s -o led.o
arm-linux-gnueabihf-ld led.o -o led.elf -Ttext=0xC0008000
arm-linux-gnueabihf-objcopy -O binary led.elf led.bin

C语言版

C语言访问特殊功能寄存器

  • 方式一:
c 复制代码
volatile unsigned int *gpioe_moder = (volatile unsigned int *)0x50006000;
*gpioe_moder = *gpioe_moder & (~(0x3 << 20));
  • 方式二:
c 复制代码
#define GPIOE_MODER (*(volatile unsigned int *)0x50006000)
GPIOE_MODER &= (~(0x3 << 20));
  • 方式三:
c 复制代码
#define GPIOA_MODER *(volatile unsigned int *)0x50002000
#define GPIOA_OTYPER *(volatile unsigned int *)0x50002004
#define GPIOA_OSPEEDR *(volatile unsigned int *)0x50002008
#define GPIOA_PUPDR *(volatile unsigned int *)0x5000200C
#define GPIOA_IDR *(volatile unsigned int *)0x50002010
#define GPIOA_ODR *(volatile unsigned int *)0x50002014

#define GPIOF_MODER *(volatile unsigned int *)0x50007000
#define GPIOF_OTYPER *(volatile unsigned int *)0x50007004
#define GPIOF_OSPEEDR *(volatile unsigned int *)0x50007008
#define GPIOF_PUPDR *(volatile unsigned int *)0x5000700C
#define GPIOF_IDR *(volatile unsigned int *)0x50007010
#define GPIOF_ODR *(volatile unsigned int *)0x50007014

--------------------------------------------------------------------------------------

/* 以上宏定义可改为以下形式 */
typedef struct {
    volatile unsigned int MODER;
    volatile unsigned int OTYPER;
    volatile unsigned int OSPEEDR;
    volatile unsigned int PUPDR;
    volatile unsigned int IDR;
    volatile unsigned int ODR;
} gpio_t;

#define GPIOA (*(gpio_t *)0x50002000)
#define GPIOB (*(gpio_t *)0x50003000)
#define GPIOC (*(gpio_t *)0x50004000)
#define GPIOD (*(gpio_t *)0x50005000)
#define GPIOE (*(gpio_t *)0x50006000)
#define GPIOF (*(gpio_t *)0x50007000)

GPIOE.MODER &= (~(0x3 << 20));
GPIOE.MODER |= (0x1 << 20);

点亮LED

c 复制代码
typedef struct{
    volatile unsigned int MODER;
    volatile unsigned int OTYPER;
    volatile unsigned int OSPEEDR;
    volatile unsigned int PUPDR;
    volatile unsigned int IDR;
    volatile unsigned int ODR;
}gpio_t;

#define GPIOE ((gpio_t *)0x50006000)

void delay_ms();
void led_flashing(){
    // 1. 使能GPIOE外设的时钟源 RCC_MP_AHB4ENSETR[4] = 0b1
    RCC_MP_AHB4ENSET |= (0x1 << 4);
    // 2. 设置为输出模式 GPIOE_MODER[21:20] = 0b01
    GPIOE->MODER &= (~(0x3 << 20));
    GPIOE->MODER |= (0x1 << 20);
    //3. 设置PE10引脚为推挽输出 GPIOE_OTYPER[10] = 0b0
    GPIOE->OTYPER &= (~(0x1 << 10));
    //4. 设置PE10引脚为低速模式 GPIOE_OSPEEDR[21:20] = 0b00
    GPIOE->OSPEEDR &= (~(0x3 << 20));
    //5. 设置PE10引脚禁止上下拉电阻 GPIOE_PUPDR[21:20] = 0b00
    GPIOE->PUPDR &= (~(0x3 << 20));
    while(1){
        /*亮*/
        GPIOE->ODR |= (1 << 10);
        delay_ms();
        /*灭*/
        GPIOE->ODR &= ~(1 << 10);
        delay_ms();
    }
}

void delay_ms(unsigned int ms)
{
    int i = 0x10000000;
    while(i--) ;
}
  • 编译
bash 复制代码
arm-linux-gnueabihf-gcc -S led.c -o led.s -marm
arm-linux-gnueabihf-as led.s -o led.o
arm-linux-gnueabihf-ld led.o -o led.elf -Ttext=0xc0008000 -eled_flashing
arm-linux-gnueabihf-objcopy -O binary led.elf led.bin

bash 复制代码
arm-linux-gnueabihf-gcc -c led.c -o led.o -marm
arm-linux-gnueabihf-ld led.o -o led.elf -Ttext=0xc0008000 -eled_flashing
arm-linux-gnueabihf-objcopy -O binary led.elf led.bin
相关推荐
老鱼说AI5 小时前
《深入理解计算机系统》(CSAPP)2.2:整数数据类型与底层机器级表示
开发语言·汇编·算法·c#
kang0x01 天前
汇编基础知识练习题
汇编
leluckys4 天前
swift- Swift中常见的面试题
开发语言·汇编·swift
bcbobo21cn4 天前
学习DOS汇编显示系统日期时间程序
汇编·dos中断21h·2ah功能·2ch功能
职豚求职小程序5 天前
东软集团题库笔试测评系统练习笔试2026新版
大数据·汇编·人工智能
我在人间贩卖青春20 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春20 天前
汇编之伪操作
汇编·伪操作
济61720 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka20 天前
汇编TEST指令
汇编