STM32F103的流水灯点亮版本1(寄存器地址操作)
目录
一.实验原理
1.STM32F103C8T6
STM32F103C8T6是一种微控制器,属于意法半导体(STMicroelectronics)的STM32系列。它是一款基于ARM Cortex-M3内核的32位单片机,具有高性能、低功耗、丰富的外设接口和强大的计算能力。STM32F103C8T6还具有丰富的存储容量和扩展性,适合于各种应用领域,如工业自动化、消费类电子、通信和控制等。
2.地址映射
STM32F103C8T6是一款32位ARM Cortex-M3微控制器,其地址映射如下:
Flash存储器:用于存储程序代码的非易失性存储器,大小为64KB,起始地址为0x0800 0000。
SRAM存储器:用于存储数据和程序的易失性存储器,大小为20KB,起始地址为0x2000 0000。
外设地址映射:
GPIO端口:每个GPIO端口有4个寄存器,包括输入数据寄存器、输出数据寄存器、数据方向寄存器和上拉下拉寄存器,其地址为0x4001 0800 - 0x4001 0C00。
ADC:内置12位ADC转换器,其地址为0x4001 2400 - 0x4001 27FF。
TIM定时器:STM32F103C8T6支持多个TIM定时器,每个定时器有数个寄存器,包括控制寄存器、计数器寄存器、比较寄存器等,其地址为0x4000 0000 - 0x4000 1000。
USART串口通信:STM32F103C8T6支持多个USART串口通信口,每个口有数个寄存器,包括控制寄存器、状态寄存器和数据寄存器等,其地址为0x4001 3800 - 0x4001 3C00。
I2C总线:STM32F103C8T6支持多个I2C总线,每个总线有数个寄存器,包括控制寄存器、状态寄存器和数据寄存器等,其地址为0x4000 5400 - 0x4000 5800。
NVIC中断向量表:用于存储中断向量表和NVIC寄存器的非易失性存储器,其地址为0xE000 E000 - 0xE000 FFFF。
3.寄存器映射
STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,其内部集成了大量的外设模块,比如GPIO、USART、SPI、I2C等等。这些外设模块都需要通过寄存器进行配置和控制。
以下是STM32F103C8T6主要的寄存器映射:
RCC寄存器映射:RCC(Reset and Clock Control)寄存器用于控制系统时钟和外设时钟的配置和控制。该寄存器映射如下:
RCC_CR:时钟控制寄存器,用于控制系统时钟和外设时钟的开关。
RCC_CFGR:时钟配置寄存器,用于配置系统时钟和外设时钟的分频和时钟源选择等参数。
RCC_APB2ENR:APB2总线外设时钟使能寄存器,用于控制APB2总线上的外设时钟使能。
RCC_APB1ENR:APB1总线外设时钟使能寄存器,用于控制APB1总线上的外设时钟使能。
GPIO寄存器映射:GPIO(General Purpose Input/Output)寄存器用于控制GPIO口的输入/输出状态。该寄存器映射如下:
GPIOx_CRL:GPIO口配置寄存器0,用于控制GPIO口的输入/输出模式、上下拉电阻等参数。
GPIOx_CRH:GPIO口配置寄存器1,用于控制GPIO口的输入/输出模式、上下拉电阻等参数。
GPIOx_ODR:GPIO口数据输出寄存器,用于控制GPIO口的输出状态。
GPIOx_IDR:GPIO口数据输入寄存器,用于读取GPIO口的输入状态。
外设寄存器映射:除了上述的寄存器映射之外,STM32F103C8T6还有大量的外设寄存器需要配置和控制,比如USART、SPI、I2C等等。这些外设的寄存器映射可以在官方的数据手册中查找到。
4.GPIO端口设置
本次实验采用GPIO的ABC端口进行电平输出
时钟地址
首先打开ABC三个输出端口的时钟,将三个位置1
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
// 打开时钟
RCC_APB2ENR |= (1<<3); // 打开 GPIOB 时钟
RCC_APB2ENR |= (1<<4); // 打开 GPIOC 时钟
RCC_APB2ENR |= (1<<2); // 打开 GPIOA 时钟
}
以GPIOA和0号引脚(A0)为例,将其设置为推挽输出,并设置最大速度为10MHz,则将控制A0的四个位设置为0001
#define GPIOA_CRL (*(unsigned int *)0x40010800)
// 最后四位变为0001
GPIOA_CRL |= (1<<0); // 最后一位变1
GPIOA_CRL &= ~(0xE<<0); // 倒数2、3、4位变0
三个端口设置如下
#define GPIOB_CRL (*(unsigned int *)0x40010C00)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)
// 配置 GPIO 口为推免输出
// GPIOB----最后四位为0001
GPIOB_CRL |= (1<<0); // 最后一位变1
GPIOB_CRL &= ~(0xE<<0); // 倒数2、3、4位变0
// GPIOC----前四位为0001
GPIOC_CRH |= (1<<28); // 第四位变1
GPIOC_CRH &= ~(0xE0000000); // 前三位变0
// GPIOA----最后四位为0001
GPIOA_CRL |= (1<<0); // 最后一位变1
GPIOA_CRL &= ~(0xE<<0); // 倒数2、3、4位变0
设置低电平
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
GPIOB_ODR &= ~(1<<0); //最后一位变为0
GPIOC_ODR &= ~(1<<15); //倒数16位变为0
GPIOA_ODR &= ~(1<<0); //最后一位变为
二.创建项目
1.新建keil工程
2.编写代码并生成hex文件
在上一节点亮led的基础上加上时延函数
void Delay_ms( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<1000;i++);
}
总代码如下
#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
#define GPIOB_CRL (*(unsigned int *)0x40010C00)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
void SystemInit(void);
void Delay_ms(volatile unsigned int);
void Delay_ms( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<1000;i++);
}
int main(){
// 开启时钟
RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
// 设置 GPIO 为推挽输出
// 设置 GPIOB 最后四位为 0001 (B0)
GPIOB_CRL |= (1<<0); // 最后一位设置为1
GPIOB_CRL &= ~(0xE); // 倒数二、三、四位设置为0
// 设置 GPIOC 前四位为 0001 (C15)
GPIOC_CRH |= (1<<28); // 第四位设置为1
GPIOC_CRH &= ~(0xE0000000); // 前三位设置为0
// 设置 GPIOA 最后四位为 0001 (A0)
GPIOA_CRL |= (1<<0); // 最后一位设置为1
GPIOA_CRL &= ~(0xE); // 倒数二、三、四位设置为0
// 3个LED初始化为不亮(即高点位)
GPIOB_ODR |= (1<<0); // 最后一位设置为1
GPIOC_ODR |= (1<<15); // 倒数第15位设置为1
GPIOA_ODR |= (1<<0); // 最后一位设置为1
while(1){
GPIOB_ODR &= ~(1<<0); // 点灯1
Delay_ms(1000000);
GPIOB_ODR |= (1<<0); // 灭灯1
Delay_ms(1000000);
GPIOC_ODR &= ~(1<<15); // 点灯2
Delay_ms(1000000);
GPIOC_ODR |= (1<<15); // 灭灯2
Delay_ms(1000000);
GPIOA_ODR &= ~(1<<0); // 点灯3
Delay_ms(1000000);
GPIOA_ODR |= (1<<0); // 灭灯3
Delay_ms(1000000);
}
}
void SystemInit(){
} //防报错
生成hex文件
3.烧录实现
c39672e091b9b22fa
四.实验总结
此次实验让我认识到如何用GPIO端口的八种工作方式并进行输入输出,在实现烧录时虽然出现了不少问题,但是依然实现了,总的来说在stm32的学习中我刚入门,还需多多学习。