第4周作业--STM32寄存器&HAL库方式的LED程序(一)
STM32F103C8T6简介
STM32F103C8T6是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。

假设你手中已有 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,分别GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。
1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数;
解题过程:原理很简单,只需要确定点亮流水灯所使用的引脚,并完成对应引脚上时钟、端口以及寄存器的配置,即可完成点灯的程序
第一步
实验要求分别在 GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制 LED 灯(最高时钟 2Mhz)
首先要确定这三个引脚的地址


偏移地址



延时设置
由于我们的要求是一个小灯泡亮起后 1s 熄灭,在熄灭 1s 后,下一个小灯泡亮起,所以这里就要用到延时函数,
由芯片数据手册可以指导内部 APB2 时钟频率最大值是 72MHz :
在 STM32 中最常用的延时一共有两种,delay_ms (毫秒级延时) 和 delay_us (微秒级延时) ,代码分别如下
// 粗延时函数,微秒级,1s = 1000000μs
void delay_us(u32 time){
	u32 i;
	while(time--){
		i = 800;	// 自行定义合理数字
		while(i--){
			// 由于循环中的变量的声明和运算,也会无形中影响循环的速度,所以,这里.什么都不用写
		}
	}
}
// 毫秒级延时
void delay_ms(u32 time){
	u32 i;
	while(time--){
		i = 12000;	// 自行定义合理数字
		while(i--){
			// 由于循环中的变量的声明和运算,也会无形中影响循环的速度,所以,这里.什么都不用写
		}
	}
}
设置小灯泡状态
在对小灯泡进行设置之前,需要给时钟使能
// 时钟使能
RCC_APB2ENR |= (1<<2);// 开启 GPIOA 时钟
RCC_APB2ENR |= (1<<3);	// 开启 GPIOB 时钟
RCC_APB2ENR |= (1<<4);	// 开启 GPIOC 时钟
初始状态下,小灯泡为灭,通过循环,使小灯泡可以按顺序延时点亮,实现一种流水灯的效果,具体代码如下:
// 这里以在 GPIOA-5 点亮小灯泡为例
GPIOA_CRL &= 0xFF0FFFFF;	// 清空控制 PA5 的端口位
// F 的位置表示的是对应引脚的位置上的电压,从右向左 CRL 分别为1、2、……、8,CRH 分别为9、10、……、16
GPIOA_CRL |= 0x00300000;	// PB5 推挽输出(和电压设置有关), 绿灯
GPIOA_ODR |= 1<<5;
2)用C语言 寄存器方式编程实现。
寄存器配置
// APB2使能时钟寄存器
#define RCC_APB2ENR	*((unsigned volatile int*)0x40021018)
// GPIOA配置寄存器
#define GPIOA_CRL	*((unsigned volatile int*)0x40010800)
#define	GPIOA_ODR	*((unsigned volatile int*)0x4001080C)
// GPIOB配置寄存器
#define GPIOB_CRL	*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR	*((unsigned volatile int*)0x40010C0C)
// GPIOC配置寄存器
#define GPIOC_CRH	*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR	*((unsigned volatile int*)0x4001100C)
具体代码
#include "stm32f10x.h"
// APB2使能时钟寄存器
#define RCC_APB2ENR	*((unsigned volatile int*)0x40021018)
// GPIOA配置寄存器
#define GPIOA_CRL	*((unsigned volatile int*)0x40010800)
#define	GPIOA_ODR	*((unsigned volatile int*)0x4001080C)
// GPIOB配置寄存器
#define GPIOB_CRH	*((unsigned volatile int*)0x40010C04)
#define	GPIOB_ODR	*((unsigned volatile int*)0x40010C0C)
// GPIOC配置寄存器
#define GPIOC_CRH	*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR	*((unsigned volatile int*)0x4001100C)
	
void SystemInit(){}
void delay(u32 time){
	u32 i = 0;
	while(time--){
		i = 2000;
		while(i--){
		}
	}
}
int main(void){
	
	RCC_APB2ENR |= (1<<2);	// GPIOA 时钟使能
	RCC_APB2ENR |= (1<<3);	// GPIOB 时钟使能
	RCC_APB2ENR |= (1<<4);	// GPIOC 时钟使能
	
	GPIOA_CRL &= 0xFF0FFFFF;	// 清空控制 PA5 的端口位
	// F 的位置表示的是对应引脚的位置上的电压,从右向左 CRL 分别为1、2、……、8,CRH 分别为9、10、……、16
	GPIOA_CRL |= 0x00300000;	// PB5 推挽输出(和电压设置有关), 绿灯
	//GPIOA_ODR &= ~(1<<5);		
	GPIOA_ODR |= 1<<5;				// 设置灯初始状态为关闭
	
	GPIOB_CRH &= 0xFFFFFF0F;
	GPIOB_CRH |= 0x00000020;	// 红灯
	//GPIOA_ODR &= ~(1<<9);
	GPIOB_ODR |= 1<<9;
	
	
	GPIOC_CRH &= 0xF0FFFFFF;
	GPIOC_CRH |= 0x02000000;	// 黄灯
	//GPIOC_ODR &= ~(1<<14);
	GPIOC_ODR |= 1<<14;
	
	while(1){
		GPIOA_ODR &= ~(1<<5);	//PB5低电平,因为是置0,所以用按位与
		delay(1000);
		GPIOA_ODR |= 1<<5;		// 设置高电位
		
		// 后面的两个灯的设置方式与上面相同
		
		GPIOB_ODR &= ~(1<<9);
		delay(1000);
		GPIOB_ODR |= 1<<9;
		
		GPIOC_ODR &= ~(1<<14);
		delay(1000);
		GPIOC_ODR |= 1<<14;
	}
	
}
单片机接线图
使用FlyMcu,,单片机在线编程网使用最多的 usb 转 ttl 烧录工具

烧录

打开软件

在选择程序文件时,找到寄存器编译的文件地址

如图

界面以及使用方法(找的例图,并非本机实验内容图,只是方便理解)

注意:我们再烧录的时候一定要在 usb 转 ttl 设备插入电脑之前。将 Boot0 设置为 1 :然后在烧录完成之后,拔出 usb ,将 Boot0 切换回 0 之后再供电才能正常运行程序
运行结果

                    
                
                
            
        
浙公网安备 33010602011771号