STM32F103C8T6是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define PERIPH_BASE ((uint32_t)0x40000000)
注:PERIPH_BASE 外设基地址:因为stm32是32位的,宏展开为0x40000000并转化为 uint32_t
APB2PERIPH_BASE 总线基地址:宏展开为PERIPH_BASE加上偏移地址 0x10000
2.寄存器寻址
GPIOB基址:
GPIOB相关的寄存器,都住在0x4001 0C00到0x4001 0FFF范围内。
端口输入寄存器地址偏移:
存储数据的位置:0X40010C00+0X0x =
地址为: GPIOC_BASE +0x0x
数据
3.地址映射
GPIO_TypeDef * GPIOx; //定义一个 GPIO_TypeDef 型结构体指针 GPIOx
GPIOx = GPIOA; //把指针地址设置为宏 GPIOA 地址
GPIOx->CRL = 0xffffffff; //通过指针访问并修改 GPIOA_CRL 寄存器
给已分配好地址(通过存储器映射实现)的有特定功能的内存单元取别名的过程就叫寄存器映射。
会有GPIOA->CRL=0x0000 0000这种写法,表示将16进制数0赋值给GPIOA的CRL寄存器所在的存储单元
#define PERIPH_BASE ((uint32_t)0x40000000)
1.这里属于存储器级别的映射,将外设基地址映射到0x40000000,可对应图2
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
2.这里对外设基地址进行偏移量为0x10000的地址偏移,偏移到APB2总线对应外设区。
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
3.这里对APB2外设基地址进行偏移量为0x0800的地址偏移,偏移到GPIOA对应区域。
本次实验采用GPIOA、B、C三个端口。该三个端口都属于APB2总线
1.找到时钟使能寄存器映射基地址
2.找到端口偏移地址以及对应端口所在位置
3.使能对应端口时钟
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR *((unsigned volatile int*)0x40021018)
RCC_APB2ENR|=1<<2|1<<3|1<<4; //APB2-GPIOA、GPIOB、GPIOC外设时钟使能
本次实验采用通用推挽输出模式,最高输出时钟频率2Mhz。分别用到A4、B5、C14三个引脚。其中A4、B5属于端口配置低寄存器偏移地址为0x00,C13属于端口配置高寄存器偏移地址为0x04。
1.找到GPIOx端口基地址
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.设置输出模式为推挽输出,输出速度为2Mhz
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
本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。
初始状态为0 0 0,
状态一为1 0 0
状态二为0 1 0
状态三为0 0 1
状态三结束后继续进入状态一,一直循环达到流水灯效果。
1.创建项目
2.选择STM32F103C8开发板
注:创建项目出现弹窗,不勾选setup项,只勾选core项
3.在output里选择create hex file
添加驱动文件
拷贝到工程目录下
右击文件夹,选择Add Existing Files to Group Source Group 1
选择All FIles,选择刚刚添加的启动文件,Add,Add之后Close
4.线路连接
对于USB转TTL模块和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,所以用按位与
}
}
生成hex文件
使用驱动进行烧录操作
连接到电脑,打开mcuisp,上传HEX文件到stm32f103c8t6上:
通过本次实验,我学会了了如何对GPIO进行初始化(时钟配置、输入输出模式设置、最大速率设置),同时也学习和理解了STM32F103系列芯片的地址映射和寄存器映射原理。
stm32寄存器实现流水灯
stm32寄存器实现流水灯
STM32寄存器的简介、地址查找,与直接操作寄存器
STM32从地址到寄存器