第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号