STM32F103C8T6LED流水灯
一、实验要求
以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED 搭建电路,使用GPIOA、GPIOB、GPIOC这3个端口控制LED灯,轮流闪烁,间隔时长1秒。
(1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数;
(2)用C语言寄存器方式编程实现,代码须有详细注解;
(3)STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注了PC13处),一般可通过此灯的点亮让编程者验证自己烧录的代码是否正常运行了。请查阅最小版电路原理图和相关资料,将这个灯也用在流水灯中,重编新程序。
二、程序设计思路
1.设计思路
根据STM32最小系统核心板,本实验选择GPIOA、GPIOB、GPIOC这三个端口来控制红绿蓝LED灯。其步骤为:
(1)配置时钟
(2)配置输出端口
(3)配置输出模式
2.APB2外设时钟使能寄存器(RCC)
寄存器地址=初始地址+偏移地址
由此可知,该寄存器地址=0x40021000(初始地址)+0x18(偏移地址)=0x40021018。
其代码如下:
#define RCC_APB2ENR *((unsigned int*)0x40021018) //定义APB2时钟使能寄存器
由图可知我们要将GPIOA、GPIOB、GPIOC的时钟开启,需要将位2、位3、位4置1。
代码如下:
RCC_APB2ENR |=1<<2; //开启GPIOA时钟
RCC_APB2ENR |=1<<3; //开启GPIOB时钟
RCC_APB2ENR |=1<<4; //开启GPIOC时钟
3.GPIO寄存器
寄存器是一段特殊的存储器,内核可通过APB2总线对寄存器进行读写操作。其中GPIO是挂载在APB2外设总线上的,其GPIO外设的名称为GPIOA、GPIOB、GPIOC…每个外设都有16个引脚(其编号为0-15),例如GPIOA的引脚为PA0-PA15。
(1)配置端口寄存器
GPIOA端口和GPIOB端口配置低寄存器,GPIOC配置高寄存器。
代码如下:
//GPIOA端口和GPIOB端口配置低寄存器,GPIOC端口配置高寄存器
#define GPIOA_CRL *((unsigned int*)0x40010800) //PA5
#define GPIOB_CRL *((unsigned int*)0x40010C00) //PB1
#define GPIOC_CRH *((unsigned int*)0x40011004) //PC14
(2)配置输出寄存器
同理,输出寄存器=初始地址+偏移地址
其代码如下:
//配置输出寄存器
#define GPIOA_ODR *((unsigned int*)0x4001080C)
#define GPIOB_ODR *((unsigned int*)0x40010C0C)
#define GPIOC_ODR *((unsigned int*)0x4001100C)
4.输出模式
推挽模式:P-MOS和N-MOS均有效,数据寄存器为1时,上管导通,下管断开。输出直接接到VDD,就是输出高电平;数据寄存器为0时,上管断开下管导通,输出直接接到VSS,输出低电平。
此模式下,高低电平具有较强的驱动能力,因此推挽模式又叫强推输出模式。在推完输出模式下,STM32对IO口具有绝对的控制权。
将端口配置偏移到对应位置实现推挽输出模式。本实验采用输出最大速度为2MHZ的推挽输出模式,因此二进制表示为0010。
此时GPIOA偏移5 4,GPIOB偏移1 * 4,GPIOC偏移64。
代码如下:
GPIOA_CRL |=(2<<(5*4)); //PA5接口,偏移5*4
GPIOB_CRL |=(2<<(1*4)); //PB1接口,偏移1*4
GPIOC_CRH |=(2<<(6*4)); //PC14接口,偏移6*4
初始状态下,所有灯熄灭,即对应GPIO口输出高电平。
代码如下:
GPIOA_ODR=0x1<<5; //GPIOA口输出高点平
GPIOB_ODR=0x1<<1; //GPIOB口输出高点平
GPIOC_ODR=0x1<<14; //GPIOC口输出高点平
5.代码实现
#include "stm32f10x.h" //头文件
//时钟配置-输入输出模式设置
#define RCC_APB2ENR *((unsigned int*)0x40021018) //定义APB2时钟使能寄存器
//GPIOA端口和GPIOB端口配置低寄存器,GPIOC端口配置高寄存器
#define GPIOA_CRL *((unsigned int*)0x40010800) //PA5
#define GPIOB_CRL *((unsigned int*)0x40010C00) //PB1
#define GPIOC_CRH *((unsigned int*)0x40011004) //PC14
//配置输出寄存器
#define GPIOA_ODR *((unsigned int*)0x4001080C)
#define GPIOB_ODR *((unsigned int*)0x40010C0C)
#define GPIOC_ODR *((unsigned int*)0x4001100C)
void delayms(unsigned int ms) //定义延时函数
{
unsigned int i;
while(ms--)
{
i=12000;
while(i--);
}; //for(i=110;i>0;i--);
} //延时1s为delayms(1000)
int main()
{
RCC_APB2ENR |=1<<2; //开启GPIOA时钟
RCC_APB2ENR |=1<<3; //开启GPIOB时钟
RCC_APB2ENR |=1<<4; //开启GPIOC时钟
//推挽模式设置
GPIOA_CRL |=(2<<(5*4)); //PA5接口,偏移5*4
GPIOB_CRL |=(2<<(1*4)); //PB1接口,偏移1*4
GPIOC_CRH |=(2<<(6*4)); //PC14接口,偏移6*4
//灯状态
GPIOA_ODR=0x1<<5;//GPIOA口输出高点平,灯灭
GPIOB_ODR=0x1<<1;//GPIOB口输出高点平,灯灭
GPIOC_ODR=0x1<<14;//GPIOC口输出高点平,灯灭
while(1)
{
//GPIOA口输出低电平,GPIOB和GPIOC输出高电平,此时只有红灯亮
GPIOA_ODR=0x0<<5;
GPIOB_ODR=0x1<<1;
GPIOC_ODR=0x1<<14;
delayms(1000);
//GPIOB口输出低电平,GPIOA和GPIOC输出高电平,此时只有绿灯亮
GPIOB_ODR=0x0<<1;
GPIOA_ODR=0x1<<5;
GPIOC_ODR=0x1<<14;
delayms(1000);
//GPIOC口输出低电平,GPIOA和GPIOB输出高电平,此时只有黄灯亮
GPIOC_ODR=0x0<<14;
GPIOA_ODR=0x1<<5;
GPIOB_ODR=0x1<<1;
delayms(1000);
}
}
三、电路仿真图
四、实物烧录
五、补充
STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注PC13处),将这个灯也用在流水灯中,重编新程序。
代码如下:
#include "stm32f10x.h" //头文件
//时钟配置-输入输出模式设置
#define RCC_APB2ENR *((unsigned int*)0x40021018) //定义APB2时钟使能寄存器
//GPIOA端口和GPIOB端口配置低寄存器,GPIOC端口配置高寄存器
#define GPIOA_CRL *((unsigned int*)0x40010800) //PA5
#define GPIOB_CRL *((unsigned int*)0x40010C00) //PB1
#define GPIOC_CRH *((unsigned int*)0x40011004) //PC14
//配置输出寄存器
#define GPIOA_ODR *((unsigned int*)0x4001080C)
#define GPIOB_ODR *((unsigned int*)0x40010C0C)
#define GPIOC_ODR *((unsigned int*)0x4001100C)
void delayms(unsigned int ms) //定义延时函数
{
unsigned int i;
while(ms--)
{
i=12000;
while(i--);
}; //for(i=110;i>0;i--);
} //延时1s为delayms(1000)
int main()
{
RCC_APB2ENR |=1<<2; //开启GPIOA时钟
RCC_APB2ENR |=1<<3; //开启GPIOB时钟
RCC_APB2ENR |=1<<4; //开启GPIOC时钟
//推挽模式设置
GPIOA_CRL |=(2<<(5*4)); //PA5接口,偏移5*4
GPIOB_CRL |=(2<<(1*4)); //PB1接口,偏移1*4
GPIOC_CRH |=(2<<(5*4)); //PC13接口,偏移5*4
//灯状态
GPIOA_ODR=0x0<<5;//GPIOA口输出高点平,灯灭
GPIOB_ODR=0x1<<1;//GPIOB口输出高点平,灯灭
GPIOC_ODR=0x1<<13;//GPIOC口输出高点平,灯灭
while(1)
{
//GPIOA口输出低电平,GPIOB和GPIOC输出高电平,此时只有红灯亮
GPIOA_ODR=0x0<<5;
GPIOB_ODR=0x1<<1;
GPIOC_ODR=0x1<<13;
delayms(1000);
//GPIOB口输出低电平,GPIOA和GPIOC输出高电平,此时只有绿灯亮
GPIOB_ODR=0x0<<1;
GPIOA_ODR=0x1<<5;
GPIOC_ODR=0x1<<13;
delayms(1000);
//GPIOC13输出低电平灯亮,其他则熄灭
GPIOC_ODR=0x0<<13;
GPIOA_ODR=0x1<<5;
GPIOB_ODR=0x1<<1;
delayms(1000);
}
}
实物烧录