实验目的
1. 了解STM32最小系统核心板(STM32F103C8T6,国际上称为 STM32 Blue Bill开发板) 的电路原理图,用Proteus 设计一个STM32最小系统板+LED流水灯实验原理图,仿真运行。
最小系统板的引脚原理图如下所示,电路原理图请网上查找。
2. 以 STM32最小系统核心板(STM32F103C8T6)+面包板+3只_(或更多)红绿蓝LED 搭建电路,使用GPIOA、GPIOB、GPIOC这3个端口控制LED灯,轮流闪烁,间隔时长1秒。
1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数;
2)用C语言寄存器方式编程实现,代码须有详细注解。
3)STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注了PC13处),一般可通过此灯的点亮让编程者验证自己烧录的代码是否正常运行了。请查阅最小版电路原理图和相关资料,将这个灯也用在流水灯中,重编新程序。
一、STM32F103C8T6开发板
STM32F103C8T6是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。
1.命名规则
2.最小系统板的引脚原理图
3.最小系统板电路原理图
4.寄存器(以STM32为例)
(1)是什么
实际是一个存储空间,并且它的地址很容易可以索引到。在STM32中是由32bit组成的存储空间,给每一个寄存器定义一个地址,先要定位某一个寄存器的地址只需要知道它的基地址,它的地址就等于基地址+偏移量。GPIO的一个IO口有四bit的一些状态组合来和它的工作模式相对应。一个组(如GPIOB)这个组共有PIN_0到PIN_15共16个引脚,所以总共就需要4*16=64bit,而一个寄存器只有32bit,所以要再配置一个寄存器,而高八位的就叫做CRH,低八位的就叫CRL。
(2)有什么用
寄存器的作用是程序与硬件沟通的桥梁。通过程序改变寄存器某些位的值从而改变GPIO的工作模式。对寄存器的读写操作就映射为我们对硬件的一些读写或者是配置操作。
二、GPIO端口
GPIO(通用输入/输出)端口是微控制器中的一种通用功能,可以通过软件控制其输入和输出状态。它们通常用于连接外部设备,如LED、按钮、传感器等,以与微控制器进行通信。GPIO端口通常包含一个或多个引脚,每个引脚可以被配置为输入或输出。在嵌入式系统中,GPIO端口通常由寄存器控制,GPIO端口可以通过软件控制来读取外部信号或向外部设备发送信号。例如,配置一个GPIO端口为输出时,可以通过将相应的输出寄存器位设置为高电平或低电平来控制外部设备(例如LED)的亮灭。配置为输入时,可以读取外部设备(例如按钮)的状态,以执行相应的操作。
想要点亮LED灯只需要配置三个寄存器:
1.打开GPIO口的时钟
2.初始化GPIO口(选择推挽输出)
3.设置低电平
1.打开时钟
寄存器地址:
各个位取值不同代表的含义:
2、初始化GPIO口:
GPIO口有八种模式:
- 输入浮空
- 输入上拉
- 输入下拉
- 模拟输入
- 开漏输出
- 推挽式输出
- 推挽式复用功能
- 开漏复用功能
本次实验使用推挽输出。
每个引脚由四个位控制,端口1-7为低,端口8-15为高。
下图位低寄存器(0-7引脚):
下图位高寄存器(8-15引脚):
3.设置低电平
输出高电平则为1,低电平则为0
三、工程建立
1.打开Keil5,点击Project——>New uVision Project...,给文件起名选好保存地址并保存
(2)选择STM32F103C8芯片,点击OK
这个不用直接叉了
(3) 将md.s启动文件粘贴到刚才创建的文件夹中
没这个文件可到此处下载。
链接:https://pan.baidu.com/s/1nngJJlorK_m5eCfJ69yPCA?pwd=l5wq
提取码:l5wq
(4) 右键到点击Source Group 1选择Add Existing Files...,文件类型选择All Files就可以看到md.s文件,然后选择点击Add。
添加成功后相应的文件夹下就会显示md.s文件
(5)然后再在Source Group 1处单击右键选择Add New...,选择c文件,起名为main,点击Add
四、流水灯的实现
1.以 STM32最小系统核心板(STM32F103C8T6)+面包板+3只红绿蓝LED 搭建电路,使用GPIOA、GPIOB、GPIOC这3个端口控制LED灯,轮流闪烁,间隔时长1秒。
(1)在main.c中写入寄存器代码(利用了PB9、PC15、PA4这三个GPIO口):
#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(1000);
C_LED_LIGHT();
Delay_ms(1000);
A_LED_LIGHT();
Delay_ms(1000);
}
}
void SystemInit(){
}
(2)实物连接
B9引脚——红色LED灯
C15引脚——绿色LED灯
A4 引脚——黄色LED灯
3.3V引脚——正极
GND引脚——负极
连接效果:
(3) 点击魔法棒,点击Debug,选择ST-Link Debugger,再点击Settings,点击Flash Download,选择Reset and Run,点击确定,点击OK
(4)接入ST-Link,在Keil5软件中点击左上角的编译按钮对代码进行编译,编译成功会显示0 Error(s)
(5)最后点击Load按钮烧录程序,烧录成功下方Build Output会显示如下文字
实验结果:
2.STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注了PC13处),将这个灯用在流水灯中
(1)在main.c中写入寄存器代码(利用了PB9、PC13、PA4这三个GPIO口):
#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){
B_LED_LIGHT();
Delay_ms(2000);//单片机上2000 100
C_LED_LIGHT();
Delay_ms(3000);//单片机上3000 200
A_LED_LIGHT();
Delay_ms(3000);//单片机上3000 200
}
}
void SystemInit(){
}
(2)实物连接
B9引脚——红色LED灯
C13引脚——绿色LED灯
A4 引脚——黄色LED灯
3.3V引脚——正极
GND引脚——负极
(3)实验结果
五、总结
通过本次实验我进一步了解到了流水灯的制作以及STM32F103开发板的一些基础知识,通过网是上的博客以及视频自己动手实现了流水灯效果,如有不足或错误敬请指正。