适合初学者的stm32最小系统板实现流水灯
一、实验环境以及器材版本
器材:STM32F103C8T6 USB转TLL接口 3.3v红绿蓝小灯泡 软件:Keil uVision5(通用微处理器软件开发工具)、 STM32CubeMX-6.6.1(stm32专用开发工具)、 FlyMcu(stm32串口烧写器) 以上软件均可在网上搜索下载到。 详细下载安装见上篇博客:link
二、stm32f103芯片的寄存器映射地址
1、什么是寄存器
寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。简单来说,寄存器就是存放东西的东西。寄存器存放的是指令、数据或地址。 存放数据的寄存器是最好理解的,如果你需要读取一个数据,直接到这个寄存器所在的地方来问问他,数据是多少就行了。问寄存器这个动作,叫做访问寄存器。不同的数据会存放在不同的寄存器,例如引脚PA2与PB8的高低电平数据(1或0)肯定放在不同的寄存器里,那么怎么区分不同的寄存器呢?通过地址,不同的寄存器有不同的地址,就像老张行李寄存处在101号店铺,老王行李寄存处在258号店铺。 指令、地址寄存器与数据寄存器类似,里边存放的都是0和1,毕竟单片机也只认识机器码,机器码都是0或1,只是特别的规定下,数据寄存器里面存放的0和1表示数据,指令寄存器里存放的表示指令。
2、如何找到某个寄存器的地址?查看数据手册
手册中没有直接给出所有的寄存器的地址,需要读者稍加计算。STM32给不同的寄存器分配了不同的地址,有点像划分了片区。在《STM32中文参考手册_V10》的第28页,有不同寄存器的地址范围。 现在,假如我们想读取PB3引脚的电平,该怎么找到相关的寄存器? 第一步,找到GPIOB的基地址 也就是找到GPIOB的小区。结论是,所有GPIOB相关的寄存器,都住在0x4001 0C00到0x4001 0FFF范围内。
第二步,找到端口输入寄存器的地址偏移 找到存储数据的那个屋子,PA接口是0x4001 0800+8 = 0x4001 0808 第三步:找到所需引脚的地址 GPIOA-5的数据位于从右往左数第4个
经过以上三步查找,得出以下结论: PA5的输入数据位于 0x4001 0808,这个地址上存放数据的右边第6个就是GPIOA-5引脚对应的高低电平。
3、配置时钟
为了省电,默认的时钟都是关闭的。配置STM32的任何资源前,都必须首先使能时钟。 在参考手册里查找时钟信息,时钟控制名字叫做RCC,属于AHB总线。GPIOB属于APB2。 我们已经知道,GPIO端口B的地址从0x4001 0C00开始。接下来只寻找时钟使能寄存器的地址: 复位和时钟控制RCC的地址从0x4002 1000开始; 可以在6.3.7小节找到APB2外设时钟使能寄存器(RCC_APB2ENR),偏移地址是0x18,所以APB2的地址就是0x4002 1018。 看手册RCC_APB2ENR,位3是IOPBEN,名字是IO端口B时钟使能,就是我们想要的。把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟。
4、配置通用输出
配置引脚GPIOA-5,使用的寄存器是GPIOA_CRL.下面来寻找这个寄存器的地址。 偏移地址是0x00 ,意思是在基地址上再加上0x00,所以,对于GPIOA来说就是0x4001 0800。如果需要配置PA8-PB15,那么需要的寄存器是GPIOA_CRH,地址是0x4001 0804。现在需要配置的寄存器是GPIOA_CRL。 找到需要操作的寄存器后,把它配置为通用输出。 复位值是0x4444 4444 ,所谓复位值,就是指如果没有操作这个寄存器时,寄存器存放的默认值。 我们需要的是输出高低电平,所以设置为输出模式,通用推挽输出。所以设置GPIOB_CRH的MODE8与CNF8为0b0011,即0x3。此寄存器中其它的位暂时不做修改,使用默认值,也就是GPIOB_CRL设置为:0x4444 4443。
三、C语言实现
1、创建新项目
2、选择STM32F103C8开发板 创建项目后出现以下弹窗,不做选择,直接关闭 3、点击魔法棒,在output中选择create hex file,意思是运行代码后生成.hex文件 4、在source group里创建main.c ,写入一下代码,使用的引脚PA5,PB9,PC14
#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
#define GPIOB_CRH (*(unsigned int *)0x40010C04)
#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_ch(volatile unsigned int);
void A_LED_LIGHT(void);
void B_LED_LIGHT(void);
void C_LED_LIGHT(void);
void Delay_ch( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<800;i++);
}
void A_LED_LIGHT(){
GPIOA_ODR=0x0<<5;
GPIOB_ODR=0x1<<9;
GPIOC_ODR=0x1<<14;
}
void B_LED_LIGHT(){
GPIOA_ODR=0x1<<5;
GPIOB_ODR=0x0<<9;
GPIOC_ODR=0x1<<14;
}
void C_LED_LIGHT(){
GPIOA_ODR=0x1<<5;
GPIOB_ODR=0x1<<9;
GPIOC_ODR=0x0<<14;
}
int main(){
int j=100;
RCC_APB2ENR |= (1<<3);
RCC_APB2ENR |= (1<<4);
RCC_APB2ENR |= (1<<2);
GPIOB_CRH&= 0xffffff0f;
GPIOB_CRH |=0x00000020;
GPIOC_CRH&= 0xf0ffffff;
GPIOC_CRH |=0x02000000;
GPIOA_CRL&= 0xff0fffff;
GPIOA_CRL |=0x00300000;
GPIOB_ODR |= (1<<9);
GPIOC_ODR |= (1<<14);
GPIOA_ODR |= (1<<5);
while(j){
B_LED_LIGHT();
Delay_ch(1000000);
C_LED_LIGHT();
Delay_ch(1000000);
A_LED_LIGHT();
Delay_ch(1000000);
}
}
void SystemInit(){
}
5、添加驱动文件,starup_stm32f10x_md.s ,添加到source group 1文件夹中
6、点击编译,成功后会在项目文件夹的Objects中生成.hex文件
四、连接电路
使用USB转TTL模块连接电脑和stm32最小系统板 GND — GND 3v3 — 3v3 TXD — A10 RXD — A9 三个小灯泡与系统板上的A5,B9,C14接口连接。
五、开始烧录程序到stm32最小系统板中
将USB接口连接到电脑上,打开Fly Mcu软件,上传.hex文件到系统板中。
烧录成功提示如下: 实现结果如图:
六、参考资料
https://blog.csdn.net/weixin_47554309/article/details/120810913 https://blog.csdn.net/geek_monkey/article/details/86291377 STM32F103X8中文数据手册
|