文章目录
一、实验原理
1.STM32VET6简介
STM32F103VET6是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。
1.型号说明: 该款芯片 为 100引脚 , 512KFlash 64kSRAM LQFP 封装 32位 Cortex内核
2.简要说明:
内核 | Cortex-M3 |
---|---|
Flash | 512K×8bit |
SRAM | 64K×8bit |
GPIO | 80个 |
ADC | 12位 ADC 三路 共有 16个通道 |
CPU | 72MHz |
通讯方式 | 两个SPI,两个I2C,五个USART, 一个USB,一个CAN通信,一个SDIO |
Timer | 4个通用定时器 ,两个高级定时器,两个基本定时器 |
2.地址映射,寄存器映射和GPIO初始化
具体的STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)在下面博客当中都有详细解释:
STM32F103系列芯片的地址映射和寄存器映射原理,GIPO初始化设置
二、实验步骤
1.查看原理图
根据下图我们可以看到STM32F103VET6开发板的外设LED灯是RGB三色灯,LED灯的颜色和亮灭都通过GPIOB端口控制,想要实现流水灯就需要对相应的引脚进行操作,对相应的引脚进行时钟使能配置、端口配置(高or低)寄存器配置、端口输出寄存器配置
2.时钟使能
1.流水灯操作的引脚位于GPIO端口,AHB总线包含RCC时钟控制,GPIO是属于APB2的。需要使用的端口的复位和时间控制受RCC控制
2.寄存器起始地址表,查询RCC地址范围,控制的寄存器位于APB2中
3.外设时钟使能寄存器,通过基址加变址方式进行寻址,设置对应位的电平使GPIOB开启
4.把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟,对应代码:
# define RCC_APB2ENR *((unsigned int*)0x40021018)
RCC_APB2ENR |= (1<<3);
3.LED灯的点亮熄灭
根据前面的LED原理图可知PB端口引脚的不同控制着LED的颜色不同,而引脚的高低电平控制等的亮灭,所以可以根据一种颜色的亮灭控制就可以以同样方法控制其它颜色的亮灭
下面以PB_5端口显现LED_R为例
1.配置引脚PB5,使用的寄存器是GPIOB_CRL。下面我们来寻找这个寄存器的地址。配置工作模式
那么需要的寄存器是低位的寄存器GPIOB_CRL,它的地址是0x4001 0c00,端口号为5
找到需要操作的寄存器后,把它配置为通用输出。 我们需要的是输出高低电平,所以要设置为输出。输出模式又有好几种输出:
00:通用推挽输出模式
01:通用开漏输出模式
10:复用功能推挽输出模式
11:复用功能开漏输出模式
由此可得:
// 开启GPIOB 端口时钟
RCC_APB2ENR |= (1<<3);
//清空控制PB5的端口位
GPIOB_CRL &= ~( 0x0F<< (4*5));
// 配置PB5为通用推挽输出,速度为10M
GPIOB_CRL |= (1<<4*05);
这样就把对应的IO口输入输出模式调好了
2. 设置输出值
查看GPIO输出文档(GPIOx_ODR)
地址偏移量0x0c,由于低电平有效所以需要将第5位设置成0,其它端口设置成1,可以实现LED的点亮
// PB0 输出 低电平
GPIOB_ODR &= ~(1<<5);
所有端口设置成1,可以实现LED的熄灭了
GPIOB_ODR |= 0xFF
4.延时函数
我们知道程序执行指令的速度是很快的,若需要将灯的亮灭以及颜色的切换让人眼可观就需要设置延时函数,延时函数的延时时间跟stm32的晶振频率有关,程序执行指令需要一定时间,以此可以设计一个简单函数:
void Delay_wxc( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<800;i++);
}
当t=1000000时就延时一段时间,该函数延时t较小时不太精确,考虑到本实验对延时精度要求不高,可以采用该延时方法
通过这个延时函数就可以实现亮灭延时,流水灯再在亮灭基础上变化颜色
三、C语言实现流水灯
1.创建项目
创建项目出现弹窗,勾选setup项和core项
2.项目配置
1.在output里选择create hex file
3.C语言代码编写
source group里创建led.c,并写入代码,注意项目结构,使用的引脚是PB0,PB1,PB5
1.首先宏定义对应GPIO各个配置端口,以及时钟RCC配置端口地址指针方便下面调用
#define RCC_APB2ENR *((unsigned int*)0x40021018) //定义时钟使能
#define GPIOB_CRL *((unsigned int*)0x40010C00) //定义GPIOB低位寄存器
#define GPIOB_ODR *((unsigned int*)0x40010C0C) //定义GPIOB输出寄存器
2.时钟使能
RCC_APB2ENR |=(1<<3); //时钟使能
3.配置PB0,1,5引脚模式
GPIOB_CRL |=(1<<(4*0)); //PB0配置成推挽输出
GPIOB_CRL |=(1<<(4*1)); //PB1配置成推挽输出
GPIOB_CRL |=(1<<(4*5)); //PB5配置成推挽输出
4.配合延时函数循环每个颜色灯的亮灭
while(1)
{
/*
红灯闪烁
*/
// PB5 输出 低电平
GPIOB_ODR &= ~(1<<5);
Delay_wxc(5000000);
// PB5 输出低电平
GPIOB_ODR |=0xFFFF;
Delay_wxc(5000000);
/*
绿灯闪烁
*/
GPIOB_ODR &= ~(1<<0);
Delay_wxc(5000000);
GPIOB_ODR |=0xFFFF;
Delay_wxc(5000000);
/*
蓝灯闪烁
*/
GPIOB_ODR &= ~(1<<1);
Delay_wxc(5000000);
GPIOB_ODR |=0xFFFF;
Delay_wxc(5000000);
}
整体代码:
#define RCC_APB2ENR *((unsigned int*)0x40021018) //定义时钟使能
#define GPIOB_CRL *((unsigned int*)0x40010C00) //定义GPIOB低位寄存器
#define GPIOB_ODR *((unsigned int*)0x40010C0C) //定义GPIOB输出寄存器
void Delay_wxc( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<800;i++);
}
int main()
{
RCC_APB2ENR |=(1<<3); //时钟使能
GPIOB_CRL |=(1<<(4*0)); //PB0配置成推挽输出
GPIOB_CRL |=(1<<(4*1)); //PB1配置成推挽输出
GPIOB_CRL |=(1<<(4*5)); //PB5配置成推挽输出
GPIOB_ODR |=0xFFFF; //输出位全置为1
while(1)
{
/*
红灯闪烁
*/
// PB5 输出 低电平
GPIOB_ODR &= ~(1<<5);
Delay_wxc(5000000);
// PB5 输出低电平
GPIOB_ODR |=0xFFFF;
Delay_wxc(5000000);
/*
绿灯闪烁
*/
GPIOB_ODR &= ~(1<<0);
Delay_wxc(5000000);
GPIOB_ODR |=0xFFFF;
Delay_wxc(5000000);
/*
蓝灯闪烁
*/
GPIOB_ODR &= ~(1<<1);
Delay_wxc(5000000);
GPIOB_ODR |=0xFFFF;
Delay_wxc(5000000);
}
}
四、烧录程序
使用驱动进行烧录操作
连接到电脑,打开mcuisp,烧录HEX文件到stm32f103vet6上:
运行结果:
五、小结
GPIO初始化步骤
使能GPIOx口的时钟
指明GPIOx口的哪一位,这一位的速度大小以及模式
调用GPIOx初始化函数进行初始化
调用GPIO-SetBits函数,进行相应位的置位