汇编编程驱动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
相关推荐
枷锁—sha1 小时前
【CTFshow-pwn系列】03_栈溢出【pwn 073】详解:静态编译下的自动化 ROP 链构建
网络·汇编·笔记·安全·网络安全·自动化
wechatbot8881 天前
极客互动企业微信聚合聊天与接口能力全景展示
汇编·微信·企业微信·ipad
枷锁—sha2 天前
【CTFshow-pwn系列】03_栈溢出【pwn 072】详解:无字符串环境下的多级 Ret2Syscall 与 BSS 段注入
服务器·网络·汇编·笔记·安全·网络安全
iCxhust4 天前
8088汇编测试程序 (MASM/TASM) — 显示 “HELLO 8088!“ + “LCD1602 OK“
汇编·单片机·嵌入式硬件·51单片机·微机原理
lhbian5 天前
AI编程革命:Codex让脚本开发提速10倍
开发语言·汇编·jvm·c#
wechatbot8886 天前
企业微信全场景消息发送接口开发实现及接口调用
java·汇编·微信·企业微信
wechatbot8886 天前
企业微信 iPad 协议接口全功能开发实战
汇编·人工智能·ios·微信·企业微信·ipad
techdashen7 天前
Rust 1.88 终于稳定了裸函数:写汇编不再需要那堆样板代码
汇编·rust
So_shine8 天前
stm32f103汇编-1:LED点灯
汇编·stm32·单片机·led
北漂Zachary9 天前
四大编程语言终极对决:汇编/C#/Go/Java谁更强
汇编·golang·c#