汇编编程驱动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
相关推荐
我在人间贩卖青春2 小时前
汇编和C编程相互调用
汇编·混合编程
myloveasuka1 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子1 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka1 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春2 天前
汇编之分支跳转指令
汇编·arm·分支跳转
我在人间贩卖青春2 天前
汇编之加载存储指令
汇编·arm·寄存器加载存储
我在人间贩卖青春2 天前
汇编之状态寄存器访问指令
汇编·arm·状态寄存器
我在人间贩卖青春2 天前
汇编之软中断指令和协处理指令
汇编·arm·软中断·协处理
我在人间贩卖青春2 天前
汇编之数据处理指令
汇编·arm·数据处理指令