文章目录
- 一、特殊功能控制寄存器
- (一)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引脚,对应的总线为AHB4
LED2---PF10,总线AHB4
LED3---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 0x50006000
GPIOF_MODER[21:20] = 0b01 0x50007000
*/
@PE8和PE10
ldr r0, =0x50006000
ldr 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]
@PF10
ldr r0, =0x50007000
ldr 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,PE8
ldr r0, =0x50006004
ldr r1, [r0]
bic r1, r1, #(0x1 << 8)
bic r1, r1, #(0x1 << 10)
str r1, [r0]
@PF10
ldr r0, =0x50007004
ldr r1, [r0]
bic r1, r1, #(0x1 << 10)
/* 1.4 配置PE10,PE8,PF10引脚为低速模式
GPIOE_OSPEEDR[21:20] = 0b00 0x50006008
*/
@PE10,PE8
ldr r0, =0x50006008
ldr r1, [r0]
bic r1, r1, #(0x3 << 20)
bic r1, r1, #(0x3 << 16)
str r1, [r0]
@PF10
ldr r0, =0x50007008
ldr r1, [r0]
bic r1, r1, #(0x3 << 20)
str r1, [r0]
/* 1.5 配置PE10引脚禁止上下拉电阻
GPIOE_PUPDR[21:20][17:16] = 0b00 0x5000600C
*/
@PE8,PE10
ldr r0, =0x5000600C
ldr r1, [r0]
bic r1, r1, #(0x3 << 20)
bic r1, r1, #(0x3 << 16)
str r1, [r0]
@PF10
ldr r0, =0x5000700C
ldr r1, [r0]
bic r1, r1, #(0x3 << 20)
str r1, [r0]
/* 2. 实现led1灯闪烁的逻辑 */
stop:
/* 2.1 配置PE10引脚输出高电平
GPIOE_ODR[10] = 0b1 0x50006014
GPIOE_BSRR[10] = 0b1 0x50006018
*/
@LED1亮,LED3灭
ldr r0, =0x50006018
mov r1, #(0x1 << 10)
orr r1, r1, #(0x1 << 24)
str r1, [r0]
@LED2灭
ldr r0, =0x50007018
mov r1,#(0x1 << 26) @LED2灭
str r1, [r0]
@延时1s
bl delay_1s
@LED1,3灭,2亮
ldr r0, =0x50006018
mov r1, #(0x1 << 26)
orr r1, r1, #(0x1 << 24)
str r1, [r0]
ldr r0, =0x50007018
mov r1, #(0x1 << 10)
str r1, [r0]
@延时1s
bl delay_1s
/* 2. 配置PE10引进输出低电平
GPIOE_ODR[10] = 0b0 0x50006014
GPIOE_BSRR[26] = 0b1 0x50006018
*/
@LED1/2灭,3亮
ldr r0, =0x50006018
mov r1, #(0x1 << 26)
orr r1, r1, #(0x1 << 8) @LED3亮
str r1, [r0]
@LED2灭
ldr r0, =0x50007018
mov r1,#(0x1 << 26) @LED2灭
str r1, [r0]
@延时1s
bl delay_1s
b stop
@ 大概 1s的延时函数
delay_1s:
mov r3, #0x10000000
mm:
cmp r3, #0
subne r3, r3, #1
bne mm
mov 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]置1
RCC_AHB4 |= 0x3 << 4;
//GPIOx_MODER寄存器,输出模式01
//PE8
GPIOE.MODER &= ~(0x3 << 16);
GPIOE.MODER |= 0x1 << 16;
//PE10
GPIOE.MODER &= ~(0x3 << 20);
GPIOE.MODER |= 0x1 << 20;
//PF10
GPIOF.MODER &= ~(0x3 << 20);
GPIOF.MODER |= 0x1 << 20;
//GPIOx_OTYPER寄存器,推挽输出,置0
GPIOE.OTYPER &= ~(0x1 << 8);
GPIOE.OTYPER &= ~(0x1 << 10);
GPIOF.OTYPER &= ~(0x1 << 10);
//GPIOx_OSPEEDR寄存器,低速,00
GPIOE.OSPEEDR &= ~(0x3 << 16);
GPIOE.OSPEEDR &= ~(0x3 << 20);
GPIOF.OSPEEDR &= ~(0x3 << 20);
//GPIOx_PUPDR寄存器,禁用上下拉电阻,00
GPIOE.PUPDR &= ~(0x3 << 16);
GPIOE.PUPDR &= ~(0x3 << 20);
GPIOF.PUPDR &= ~(0x3 << 20);
}
void led_turn_on(leds_t led){
switch (led)
{
case LED1://PE10
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://PE10
GPIOE.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);//延时1s
led_turn_on(LED2);
led_turn_off(LED3);
led_turn_off(LED1);
delay_ms(1000);//延时1s
led_turn_on(LED3);
led_turn_off(LED1);
led_turn_off(LED2);
delay_ms(1000);//延时1s
}
return 0;
}