STM32F103C8T6实现流水灯

一、实验原理

1.STM32F103C8T6简介

STM32F103C8T6是一款由意法半导体公司(ST)推出的基于ARM Cortex-M 内核STM32系列的32位的微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。程序存储器容量是64KB,需要电压2V~3.6V,工作温度为-40°C ~ 85°C。

内核 Cortex-M3
Flash 64K x 8bit
SRAM 20K x 8bit
GPIO 37个GPIO,分别为PA0-PA15、PB0-PB15、PC13-PC15、PD0-PD1
ADC 2个12bit ADC合计12路通道(外部通道:PA0到PA7+PB0到PB1,内部通道:)
Timers 1. 4个16bit定时器/计数器,分别为TIM1、TIM2、TM4 TM1带死区插入,常用于产生PWM控制电机
通信串口 2IIC,2SPI,3USART,1CAN

2.地址映射

  1. M3存储器映射
    在这里插入图片描述
    LED灯程序中,宏定义:
#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
    在这里插入图片描述
  • 数据
    在这里插入图片描述
  • 地址映射
GPIO_TypeDef * GPIOx; //定义一个 GPIO_TypeDef 型结构体指针 GPIOx
GPIOx = GPIOA; //把指针地址设置为宏 GPIOA 地址
GPIOx->CRL = 0xffffffff; //通过指针访问并修改 GPIOA_CRL 寄存器

3.寄存器映射

  • 给已分配好地址(通过存储器映射实现)的有特定功能的内存单元取别名的过程就叫寄存器映射。
    在这里插入图片描述

  • GPIOA->CRL=0x0000 0000,表示将16进制数0赋值给GPIOA的CRL寄存器所在的存储单元
    这里属于存储器级别的映射,将外设基地址映射到0x40000000,可对应上图。

#define PERIPH_BASE      ((uint32_t)0x40000000) 

这里对外设基地址进行偏移量为0x10000的地址偏移,偏移到APB2总线对应外设区。

#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

这里对APB2外设基地址进行偏移量为0x0800的地址偏移,偏移到GPIOA对应区域。

#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)

4.GPIO端口初始化设置

1.时钟配置

原因:因为耗电量,stm32功能强大,能做很多事,但与之同时带来的消耗也越严重,此做法降低了功耗,续航持久。
时钟控制名字叫做RCC,属于AHB总线。GPIOB属于APB2。
在这里插入图片描述

GPIO输入模式:输入浮空,输入上拉,输入下拉,模拟输入;
输出方式:开漏输出,开漏复用输出,推挽输出,推挽复用输出。

2.输入输出模式

  • 输入模式
    浮空输入模式:浮空输入状态下,IO 的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的。可做KEY按键识别。
    上下拉输入模式:内部设有上拉和下拉电阻,当外部电路为低电平,IO口设为下拉模式,当外部电路为低电平,IO口设为上拉模式。
    模拟输入模式:用作内部ADC输入或DAC输出,预防干扰。
  • 输出模式
    推挽输出模式:(最常用)
    开漏输出模式:(不常用)
    推挽、开漏复用模式

3.最大速率设置

4.GPIO初始化步骤

  • 使能GPIOx口的时钟
  • 指明GPIOx口的哪一位,这一位的速度大小以及模式
  • 调用GPIOx初始化函数进行初始化
  • 调用GPIO-SetBits函数,进行相应位的置位

二、原理

1.STM32开发板中包含较多寄存器,实现流水灯操作,需要对相应的引脚进行操作,对相应的引脚进行时钟使能配置、端口配置(高or低)寄存器配置、端口输出寄存器配置

  • 配置时钟使能
  • 配置端口配置齐
  • 配置端口输出寄存器
  • 烧录程序
  • 运行

2.流水灯操作的引脚位于GPIO端口:AHB总线包含RCC时钟控制,GPIO是属于APB2的。需要使用的端口的复位和时间控制受RCC控制
在这里插入图片描述
3.寄存器起始地址表,查询RCC地址范围,控制的寄存器位于APB2中
在这里插入图片描述

4.外设时钟使能寄存器,设偏移量为0x18,起始地址0x4002 1000,该寄存器地址为0x4002 1018
在这里插入图片描述
5.手册RCC_APB2ENR,位3是IOPBEN,名字是IO端口B时钟使能,就是我们想要的。把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟

#define RCC_AP2ENR	*((unsigned volatile int*)0x40021018) #时钟使能寄存器
RCC_AP2ENR|=1<<2;

6.端口配置寄存器(每四位配置一个端口)

  • 确定引脚
  • 端口配置低寄存器(CRL) 偏移地址0x00

在这里插入图片描述

  • 端口配置高寄存器(CRH) 偏移地址0x04
    在这里插入图片描述
    7.相应端口配置器GPIOA_CRL地址为GPIOA的基址+上偏移量
    设置推挽输出并设置最大速度为2Mhz:
#define GPIOA_CRL	*((unsigned volatile int*)0x40010800)
GPIOA_CRL=0x20000000;		//PA7推挽输出,2Mhz

8.配置端口输出寄存器
点亮LED需要输出低电平,地址的偏移是0x0C,所以这个数据寄存器的地址就是0x4001 0C0C,把第8位写为0就行。默认就是0,高电压赋值为1
在这里插入图片描述
移位操作:

#define	GPIOA_ORD	*((unsigned volatile int*)0x4001080C)
GPIOA_ORD|=1<<7;			//设置初始灯为亮

9.实现流水灯只需增加灯的数量和增加一些延时

三、C语言实现流水灯

1.创建项目
在这里插入图片描述
在这里插入图片描述
2.选择STM32F103C8开发板在这里插入图片描述
遇到下列弹窗直接叉掉,无需选择
在这里插入图片描述

3.右击Sources Group 1,点击如图地区
在这里插入图片描述
4.添加一个c文件,命名为main,点击add
在这里插入图片描述

5.在output里选择create hex file
在这里插入图片描述
6.将标准库启动文件复制到工程路径下
在这里插入图片描述
在这里插入图片描述
7.右击Source Group 1,点击下图地区
在这里插入图片描述
在这里插入图片描述

8.编写代码
在main.c中写入函数:


#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){
    
    
		
		B_LED_LIGHT();
		Delay_ms(1000000);

		C_LED_LIGHT();
		Delay_ms(1000000);

		A_LED_LIGHT();
		Delay_ms(1000000);
	}
	
}


void SystemInit(){
    
    
	
}

9.编译程序
在这里插入图片描述

10.电路连接
根据设计的程序连接电路:
对于USB转TTL模块和stm32f103c8t6连接:
GND — GND
3v3 — 3v3
TXD — A10
RXD — A9

总电路:
红——B9
绿——C15
黄——A4
如图:
在这里插入图片描述
连接到电脑,随后打开mcuisp,上传HEX文件到stm32f103c8t6上:
在这里插入图片描述
烧录运行结果:
在这里插入图片描述

LED lamp

四、总结

学习和理解STM32F103系列芯片的地址映射和寄存器映射原理,了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置),并通过STM32F103C8T6完成了一个简单的流水灯。

五、参考资料

https://blog.csdn.net/qq_47281915/article/details/120812867
https://blog.csdn.net/weixin_47554309/article/details/120810913
https://blog.csdn.net/geek_monkey/article/details/86293880
https://blog.csdn.net/geek_monkey/article/details/86291377
https://blog.csdn.net/wangxuznb/article/details/50669333
https://blog.csdn.net/FRIGIDWINTER/article/details/106826511

猜你喜欢

转载自blog.csdn.net/qq_55894922/article/details/127224824