STM32实现流水灯(配置寄存器版)

本文详细介绍了STM32F103C8T6微控制器的系统架构,包括其多级AHB总线和APB总线设计,以及如何通过GPIO端口配置实现流水灯效果,涉及时钟开启、GPIO模式设置和LED控制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、STM32F103C8T6基本介绍

(一)系统构架

(二)STM32最小系统板的电路原理图

二、STM32F103C8T6寄存器配置流水灯

(一)GPIO端口的初始化设置

1、打开时钟:

2、初始化GPIO口

3、设置高电平

(二)实际应用


一、STM32F103C8T6基本介绍

(一)系统构架

1.在小容量、中容量和 大容量产品中,主系统由以下部分构成:

(1) 四个驱动单元:

  • Cortex™-M3内核DCode总线(D-bus),和系统总线(S-bus)
  • 通用DMA1和通用DMA2

(2)四个被动单元:

  • 内部SRAM
  • 内部闪存存储器
  •  FSMC
  • AHB到APB的桥(AHB2APBx),它连接所有的APB设备

这些都是通过一个多级的AHB总线构架相互连接的,如下图所示:

2.在互联型产品中,主系统由以下部分构成:

(1)五个驱动单元:

  • Cortex™-M3内核DCode总线(D-bus),和系统总线(S-bus)
  • 通用DMA1和通用DMA2
  • 以太网DMA

(2) 三个被动单元

  • 内部SRAM
  • 内部闪存存储器
  • AHB到APB的桥(AHB2APBx),它连接所有的APB设备

这些都是通过一个多级的AHB总线构架相互连接的,如图所示:

3.结构中的总线

(1)ICode总线:该总线将 Cortex™-M3 内核的指令总线与 Flash 指令接口相连接。指令预取在此总线上完成。

(2)DCode总线:该总线将 Cortex™-M3 内核的 DCode 总线与闪存存储器的数据接口相连接(常量加载和调试访问)

(3)系统总线:此总线连接 Cortex™-M3 内核的系统总线(外设总线)到总线矩阵,总线矩阵协调着内核和 DMA 间的访问。

(4)DMA总线:此总线将 DMA AHB 主控接口与总线矩阵相联,总线矩阵协调着CPU的DCode和DMASRAM、闪存和外设的访问。

(5)总线矩阵:此总线矩阵协调内核系统总线和 DMA 主控总线之间的访问仲裁。此仲裁利用轮 换算法。此总线矩阵由三个驱动部件(CPU 的 DCode、系统总线和 DMA 总线)和 三个被动部件(闪存存储器接口、SRAM 和 AHB2APB 桥)构成。 AHB 外设通过总线矩阵与系统总线相连,允许DMA 访问。

(6)AHB/APB桥(APB):两个 AHB/APB 桥在 AHB 和 2 个 APB 总线间提供同步连接。APB1 操作速度限 于 36MHz,APB2 操作于全速(最高 72MHz)。

(二)STM32最小系统板的电路原理图

二、STM32F103C8T6寄存器配置流水灯

(一)GPIO端口的初始化设置

      GPIO是STM32芯片上的通用输入输出端口,通过这些引脚,STM32可以与外部设备连接,实现通讯、控制和数据采集等功能。STM32芯片的GPIO被分成多个组,每组包含16个引脚,如STM32F103VET6型号芯片有GPIOA至GPIOE共5组GPIO,总计100个引脚,这些引脚都具有基本的输入输出功能。

      点亮LED灯,实现流水灯效果需要用到GPIO端口。为了点亮LED灯,进行以下三个步骤:

  1. 打开GPIO口的时钟
  2. 初始化GPIO口(选择推挽输出)
  3. 设置低电平

1、打开时钟:

(1)GPIO的地址:

根据芯片手册查询端口相关资料得到端口地址如下图所示:

(2)时钟的地址:

由上图可得:

  • RCC的起始地址为:0x40021000
  • APB2外设时钟使能寄存器的偏移地址是0x18
  • 因此可以得到实际地址为:0x40021000 + 0x18 = 0x40021018

则打开三个IO口的时钟需要将三个位都置1:

#define RCC_APB2ENR (*(unsigned int *)0x40021018)
 
// 打开时钟
RCC_APB2ENR |= (1<<3);  // 打开 GPIOB 时钟
RCC_APB2ENR |= (1<<4);  // 打开 GPIOC 时钟
RCC_APB2ENR |= (1<<2);  // 打开 GPIOA 时钟
 

2、初始化GPIO口

通过学习可以得到GPIO口有如下八种模式:

  • 输入浮空
  • 输入上拉
  • 输入下拉
  • 模拟输入
  • 开漏输出
  • 推挽式输出
  • 推挽式复用功能
  • 开漏复用功能

本次实验使用推挽输出:

端口1-7为低,端口8-15为高。每个引脚由四个位控制。
 PB0、PC15、PA0的设置具体代码如下:

#define GPIOB_CRH (*(unsigned int *)0x40010C04)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)
// 设置 GPIO 为推挽输出,即00,同时频率为10MHz,即01
// 设置 GPIOB 最后四位为 0001 (B0)
GPIOB_CRL |= (1<<0); // 最后一位设置为1
GPIOB_CRL &= ~(0xE); // 倒数二、三、四位设置为0
// 设置 GPIOC 前四位为 0001 (C15)
GPIOC_CRH |= (1<<28); // 第四位设置为1
GPIOC_CRH &= ~(0xE0000000); // 前三位设置为0
// 设置 GPIOA 最后四位为 0001 (A0)
GPIOA_CRL |= (1<<0); // 最后一位设置为1
GPIOA_CRL &= ~(0xE); // 倒数二、三、四位设置为0

3、设置高电平

注:输出高电平则为1,低电平则为0

以GPIOB和0号引脚(B0)为例,将其设置为低电平:

#define GPIOA_ODR (*(unsigned int *)0x4001080C)
GPIOB_ODR &= ~(1<<0);  // 最后一位变0

将相应的bit位设置为高电位则灯不亮,GPIO的A0、B0、C15代码如下:

//给GPIOA、GPIOB、GPIOC配置输入寄存器
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
// 3个LED初始化为不亮(即高点位)
GPIOB_ODR |= (1<<0); // 最后一位设置为1
GPIOC_ODR |= (1<<15); // 倒数第15位设置为1
GPIOA_ODR |= (1<<0); // 最后一位设置为1

(二)实际应用

1、题目:以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只_(或更多)红绿蓝LED 搭建电路,使用GPIOA、GPIOB、GPIOC这3个端口控制LED灯,轮流闪烁,间隔时长1秒。

Proteus原理图:

代码编写:

 
#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_ms(volatile  unsigned  int);
void A_LED_LIGHT(void);
void B_LED_LIGHT(void);
void C_LED_LIGHT(void);
void Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}
 
void A_LED_LIGHT(){
	GPIOA_ODR=0x0<<4;		//PA4低电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x1<<15;		//PC15高电平
}
void B_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x0<<9;		//PB9低电平
	GPIOC_ODR=0x1<<15;		//PC15高电平
}
void C_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x0<<15;		//PC15低电平	
}
 
int main(){
	int j=100;
	// 开启时钟
	RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
	RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
	RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
	
	
	// 设置 GPIO 为推挽输出
	GPIOB_CRH&= 0xffffff0f;	//设置位 清零		
	GPIOB_CRH|=0x00000020;  //PB9推挽输出
 
	GPIOC_CRH &= 0x0fffffff; //设置位 清零		
	GPIOC_CRH|=0x30000000;  //PC15推挽输出
 
 
	GPIOA_CRL &= 0xfff0ffff; //设置位 清零		
	GPIOA_CRL|=0x00010000; //PA4推挽输出
 
	// 3个LED初始化为不亮(即高点位)
	GPIOB_ODR |= (1<<9); 
	GPIOC_ODR |= (1<<15); 
	GPIOA_ODR |= (1<<4);  
	
	while(j){

		A_LED_LIGHT();
		Delay_ms(1000000);
		
		B_LED_LIGHT();
		Delay_ms(1000000);
 
		C_LED_LIGHT();
		Delay_ms(1000000);
 

	}
	
}
 
 
void SystemInit(){
	
}

2、题目:STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注了PC13处),一般可通过此灯的点亮让编程者验证自己烧录的代码是否正常运行了。请查阅最小版电路原理图和相关资料,将这个灯也用在流水灯中,重编新程序。

代码编写:

 
#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_ms(volatile  unsigned  int);
void A_LED_LIGHT(void);
void B_LED_LIGHT(void);
void C_LED_LIGHT(void);
void Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}
 
void A_LED_LIGHT(){
	GPIOA_ODR=0x0<<4;		//PA4低电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x1<<13;		//PC13高电平
}
void B_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x0<<9;		//PB9低电平
	GPIOC_ODR=0x1<<13;		//PC13高电平
}
void C_LED_LIGHT(){
	GPIOA_ODR=0x1<<4;		//PA4高电平
	GPIOB_ODR=0x1<<9;		//PB9高电平
	GPIOC_ODR=0x0<<13;		//PC13低电平	
}
 
int main(){
	int j=100;
	// 开启时钟
	RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
	RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
	RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
	
	
	// 设置 GPIO 为推挽输出
	GPIOB_CRH&= 0xffffff0f;	//设置位 清零		
	GPIOB_CRH|=0x00000020;  //PB9推挽输出
 
	GPIOC_CRH &= 0xff0fffff; //设置位 清零		
	GPIOC_CRH|=0x00300000;  //PC15推挽输出
 
 
	GPIOA_CRL &= 0xfff0ffff; //设置位 清零		
	GPIOA_CRL|=0x00010000; //PA4推挽输出
 
	// 3个LED初始化为不亮(即高点位)
	GPIOB_ODR |= (1<<9); 
	GPIOC_ODR |= (1<<13); 
	GPIOA_ODR |= (1<<4);  
	
	while(j){

		A_LED_LIGHT();
		Delay_ms(3000);
		
		B_LED_LIGHT();
		Delay_ms(2000);
 
		C_LED_LIGHT();
		Delay_ms(3000);
 

	}
	
}
 
 
void SystemInit(){
	
}

开发板效果:

流水灯

参考博客:STM32F103的流水灯点亮版本1(寄存器地址操作)_pc13推挽输出-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值