文章目录
- 一、特殊功能控制寄存器
- (一)GPIOx_MODER寄存器
- (二)GPIOx_OTYPER寄存器
- (三)GPIOx_OSPEEDR寄存器
- (四)GPIOx_PUPDR寄存器
- (五)GPIOx_IDR寄存器
- (六)GPIOx_ODR寄存器
- (七)GPIOx_BSRR寄存器
- 二、 查看外设控制器对应的特殊功能寄存器的基地址
- 三、RCC
- 四、代码实现
- (一)汇编版本
- (二)C语言版本
一、特殊功能控制寄存器
控制寄存器:
数据寄存器:
因此,控制LED1,需要配置GPIOE控制器模式:
1> 配置GPIOE_MODER寄存器,配置PE10引脚为输出的模式
2> 配置GPIOE_OTYPER寄存器,配置PE10引脚为推挽输出
3> 配置GPIOE_OSPEEDR寄存器,配置PE10引脚为低速模式
4> 配置GPIOE_PUPDR寄存器,配置PE10引脚禁止上下拉电阻
5> 配置GPIOE_ODR寄存器,配置PE10引脚输出高低电平
(一)GPIOx_MODER寄存器
配置PE10引脚为输出模式,即配置GPIOE_MODER寄存器的第[20:21]位为01
(二)GPIOx_OTYPER寄存器
GPIO端口输出类型寄存器
配置PE10引脚为推挽输出模式,即配置GPIOE_OTYPER寄存器的第[10]位为0
(三)GPIOx_OSPEEDR寄存器
GPIO端口输出速度寄存器
配置PE10引脚为低速模式,即配置GPIOE_OSPEEDR寄存器的第[21:20]位为00
(四)GPIOx_PUPDR寄存器
GPIO上下拉电阻寄存器
配置PE10引脚为禁用上下拉模式,即配置GPIOE_PUPDR寄存器的第[21:20]位为00
注:11: Reserved保留
(五)GPIOx_IDR寄存器
- 注:IDR寄存器是只读寄存器
(六)GPIOx_ODR寄存器
点亮LED1,就需要PE10输出高电平,即第[10]位输出1;
熄灭LED1,就需要PE10输出低电平,即第[10]位输出0;
(七)GPIOx_BSRR寄存器
二、 查看外设控制器对应的特殊功能寄存器的基地址
三、RCC
四、代码实现
实现LED1~3交替闪烁
(一)汇编版本
/*LED1灯---PE10引脚,对应的总线为AHB4LED2---PF10,总线AHB4LED3---PE8
*/
.text
.global _start_start:/* 1. LED灯的初始化 *//* 1.1 使能GPIOE和GPIOF外设控制器的时钟源 RCC_MP_AHB4ENSETR[5:4] = 0b3 0x50000A28*/@ 使能GPIOE和GPIOF的时钟源ldr r0, =0x50000A28 @ 准备地址ldr r1, [r0] @ 读取地址中的数据orr r1, r1, #(0x3 << 4); @ 修改数据str r1, [r0] @ 写数据到地址中/* 1.2 配置PE8,PE10,PF10引脚为输出模式 GPIOE_MODER[21:20][17:16] = 0b01 0x50006000GPIOF_MODER[21:20] = 0b01 0x50007000*/@PE8和PE10ldr r0, =0x50006000ldr r1, [r0]bic r1, r1, #(0x3 << 20)orr r1, r1, #(0x1 << 20)bic r1, r1, #(0x3 << 16)orr r1, r1, #(0x1 << 16)str r1, [r0]@PF10ldr r0, =0x50007000ldr r1, [r0]bic r1, r1, #(0x3 << 20)orr r1, r1, #(0x1 << 20)str r1, [r0]/* 1.3 配置PE8,PE10,PF10引脚为推挽输出 GPIOE_OTYPER[10] = 0b0 0x50006004*/@PE10,PE8ldr r0, =0x50006004ldr r1, [r0]bic r1, r1, #(0x1 << 8)bic r1, r1, #(0x1 << 10)str r1, [r0]@PF10ldr r0, =0x50007004ldr r1, [r0]bic r1, r1, #(0x1 << 10)/* 1.4 配置PE10,PE8,PF10引脚为低速模式 GPIOE_OSPEEDR[21:20] = 0b00 0x50006008*/@PE10,PE8ldr r0, =0x50006008ldr r1, [r0]bic r1, r1, #(0x3 << 20)bic r1, r1, #(0x3 << 16)str r1, [r0]@PF10ldr r0, =0x50007008ldr r1, [r0]bic r1, r1, #(0x3 << 20)str r1, [r0]/* 1.5 配置PE10引脚禁止上下拉电阻GPIOE_PUPDR[21:20][17:16] = 0b00 0x5000600C*/ @PE8,PE10ldr r0, =0x5000600Cldr r1, [r0]bic r1, r1, #(0x3 << 20)bic r1, r1, #(0x3 << 16)str r1, [r0]@PF10ldr r0, =0x5000700Cldr r1, [r0]bic r1, r1, #(0x3 << 20)str r1, [r0]/* 2. 实现led1灯闪烁的逻辑 */stop:/* 2.1 配置PE10引脚输出高电平 GPIOE_ODR[10] = 0b1 0x50006014GPIOE_BSRR[10] = 0b1 0x50006018*/@LED1亮,LED3灭ldr r0, =0x50006018mov r1, #(0x1 << 10)orr r1, r1, #(0x1 << 24) str r1, [r0]@LED2灭ldr r0, =0x50007018mov r1,#(0x1 << 26) @LED2灭str r1, [r0]@延时1sbl delay_1s@LED1,3灭,2亮ldr r0, =0x50006018mov r1, #(0x1 << 26)orr r1, r1, #(0x1 << 24)str r1, [r0]ldr r0, =0x50007018mov r1, #(0x1 << 10)str r1, [r0]@延时1sbl delay_1s/* 2. 配置PE10引进输出低电平 GPIOE_ODR[10] = 0b0 0x50006014GPIOE_BSRR[26] = 0b1 0x50006018*/@LED1/2灭,3亮ldr r0, =0x50006018mov r1, #(0x1 << 26)orr r1, r1, #(0x1 << 8) @LED3亮str r1, [r0]@LED2灭ldr r0, =0x50007018mov r1,#(0x1 << 26) @LED2灭str r1, [r0]@延时1sbl delay_1sb stop@ 大概 1s的延时函数
delay_1s:mov r3, #0x10000000mm:cmp r3, #0subne r3, r3, #1bne mmmov pc, lr.end
(二)C语言版本
led.h
#ifndef __LED_H__
#define __LED_H__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;volatile unsigned int BSRR;
} gpio_t;#define GPIOE (*((gpio_t *)0x50006000))
#define GPIOF (*((gpio_t *)0x50007000))#define RCC_AHB4 (*((unsigned int *)0x50000A28))typedef enum{LED1 = 1,LED2,LED3
}leds_t;void led_init(void);
void led_turn_on(leds_t led);
void led_turn_off(leds_t led);#endif
led.c
#include "../include/led.h"/**** 功能:LED1~3初始化;* LED1---PE10* LED2---PF10* LED3---PE8
***/
void led_init(void){//使能GPIOE和GPIOF的时钟,[5:4]置1RCC_AHB4 |= 0x3 << 4;//GPIOx_MODER寄存器,输出模式01//PE8GPIOE.MODER &= ~(0x3 << 16);GPIOE.MODER |= 0x1 << 16;//PE10GPIOE.MODER &= ~(0x3 << 20);GPIOE.MODER |= 0x1 << 20;//PF10GPIOF.MODER &= ~(0x3 << 20);GPIOF.MODER |= 0x1 << 20;//GPIOx_OTYPER寄存器,推挽输出,置0GPIOE.OTYPER &= ~(0x1 << 8);GPIOE.OTYPER &= ~(0x1 << 10);GPIOF.OTYPER &= ~(0x1 << 10);//GPIOx_OSPEEDR寄存器,低速,00GPIOE.OSPEEDR &= ~(0x3 << 16);GPIOE.OSPEEDR &= ~(0x3 << 20);GPIOF.OSPEEDR &= ~(0x3 << 20);//GPIOx_PUPDR寄存器,禁用上下拉电阻,00GPIOE.PUPDR &= ~(0x3 << 16);GPIOE.PUPDR &= ~(0x3 << 20);GPIOF.PUPDR &= ~(0x3 << 20);
}void led_turn_on(leds_t led){switch (led){case LED1://PE10GPIOE.BSRR = 0x1 << 10;//BSRR寄存器不需要担心向除了操作位以外的其他位中写入0,因为写0无意义,所以此处可以直接赋值操作,而无需使用"GPIOE.BSRR|=0x1<<10"break;case LED2:GPIOF.BSRR = 0x1 << 10;break;case LED3:GPIOE.BSRR = 0x1 << 8;}
}void led_turn_off(leds_t led){switch (led){case LED1://PE10GPIOE.BSRR = 0x1 << 26;break;case LED2:GPIOF.BSRR = 0x1 << 26;break;case LED3:GPIOE.BSRR = 0x1 << 24;}
}
main.c
#include "./include/led.h"void delay_ms(unsigned int ms)
{int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 1800; j++);
}int main()
{//初始化led_init();while(1){led_turn_on(LED1);led_turn_off(LED2);led_turn_off(LED3);delay_ms(1000);//延时1sled_turn_on(LED2);led_turn_off(LED3);led_turn_off(LED1);delay_ms(1000);//延时1sled_turn_on(LED3);led_turn_off(LED1);led_turn_off(LED2);delay_ms(1000);//延时1s}return 0;
}