STM32F103c8t6
地址映射
被控单元的FLASH,RAM,FSMC和AHB到APB的桥(即片上外设),这些功能部件共同排列在一个 4GB 的地址空间内
存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射
在这 4GB 的地址空间中,ARM 已经粗线条的平均分成了 8 个块,每块 512MB,每个块也都规定了用途
存储器功能分类
所以cpu就能直接通过这些地址来访问到实际的一个物理上的硬件,对自身地址空间的分配就是地址映射。
寄存器映射
根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
通常我们访问内存单元有两种方式
1.绝对地址访问
0x4001 0C0C在我们看来是 GPIOB端口 ODR的地址,但是在编译器看来,这只是一个普通的变量,是一个立即数,要想让编译器也认为是指针,我们得进行强制类型转换,把它转换成指针,即(unsigned int *)0x4001 0C0C,然后再对这个指针进行 * 操作。
2.寄存器映
这样是把GPIOB寄存器的基地址加上地址偏移后的地址转化为一个指针,命名为GPIOB_ODR,这样我们以后访问这个地址时就可以直接用这个指针名访问也就是取别名。
GPIO端口设置
GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32 芯片的 GPIO 被分成很多组,每组有 16 个引脚,所有的 GPIO 引脚都有基本的输入输出功能。
1.时钟配置
时钟配置属于RCC寄存器控制,挂载在AHB总线.GPIO挂载在AHB总线分出的APB2总线
RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能 `
2.输入输出配置
一般情况下都习惯使用推挽输出模式
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
3.最大速率设置
GPIOA_CRL&=0xFFF0FFFF; //设置位 清零
GPIOA_CRL|=0x00020000; //PA4推挽输出,把第19、18、17、16位变为0010
GPIOB_CRL&=0xFF0FFFFF; //设置位 清零
GPIOB_CRL|=0x00200000; //PB5推挽输出,把第23、22、21、20变为0010
GPIOC_CRH&=0xFF0FFFFF; //设置位 清零
GPIOC_CRH|=0x00200000; //PC14推挽输出,把第23、22、21、20变为0010
STM32F103C8T6实现流水灯
代码实现
#include "stm32f10x.h"
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
#define GPIOA_ODR *((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL *((unsigned volatile int*)0x40010C00)
#define GPIOB_ODR *((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
#define GPIOC_ODR *((unsigned volatile int*)0x4001100C)
//延时函数
void Delay()
{
u32 i=0;
for(;i<5000000;i++);
}
int main(void)
{
RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能
GPIOA_CRL&=0xFFF0FFFF; //设置位 清零
GPIOA_CRL|=0x00020000; //PB5推挽输出
GPIOA_ODR&=~(1<<4); //设置初始灯为灭
GPIOB_CRL&=0xFF0FFFFF; //设置位 清零
GPIOB_CRL|=0x00200000; //PB5推挽输出
GPIOB_ODR&=~(1<<5); //设置初始灯为灭
GPIOC_CRH&=0xF0FFFFFF; //设置位 清零
GPIOC_CRH|=0x02000000; //PB5推挽输出
GPIOC_ODR&=~(1<<14); //设置初始灯为灭
while(1){
//A灯
GPIOA_ODR|=1<<4; //PB5高电平
Delay();
GPIOA_ODR&=~(1<<4); //PB5低电平,因为是置0,所以用按位与
//B灯
GPIOB_ODR|=1<<5; //PB5高电平
Delay();
GPIOB_ODR&=~(1<<5); //PB5低电平,因为是置0,所以用按位与
//C灯
GPIOC_ODR|=1<<14; //PB5高电平
Delay();
GPIOC_ODR&=~(1<<14); //PB5低电平,因为是置0,所以用按位与
}
}
HAL库编写led流水灯(软件stm32cubeide)
1.安装HAL
点击之后会跳出来一个选择型号界面 勾选上你要安装的HAL库, 点击“Install Now” 直到安装成功。 如下图:
2.创建工程
点击
创建一个工程,然后弹出以下界面
然后设置成如图所示
配置时钟按图操作
然后就是
将里面的代码替换为
SystemClock_Config();//系统时钟初始化
MX_GPIO_Init();//gpio初始化
while (1)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15熄灯
HAL_Delay(1000);//延时1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9亮灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15熄灯
HAL_Delay(1000);//延时1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);//PC15亮灯
HAL_Delay(1000);//延时1s
}
ide可以直接使用st-link 烧录到芯片里
效果如图所示
观察GPIO端口的输出波形
进行完相关的配置之后