实验介绍
一. 实验目的:
1、了解stm32f103c8t6最小核心板的主要引脚接口;
2、掌握Keil 开发stm32程序的环境搭建和设置;
3、使用GPIO引脚,外接LED灯,编写程序让LED灯周期性亮灭。
二. 具体实验过程:
- 了解STM32最小系统核心板(STM32F103C8T6,国际上称为 STM32 Blue Bill开发板) 的电路原理图,用Proteus 设计一个STM32最小系统板+LED流水灯实验原理图,仿真运行。
- 以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只_(或更多)红绿蓝LED 搭建电路,使用GPIOA、GPIOB、GPIOC这3个端口控制LED灯,轮流闪烁,间隔时长1秒。
(1)写出程序设计思路,包括GPIOx端口的各寄存器地址和详细参数;
(2)用C语言寄存器方式编程实现,代码须有详细注解。
(3)STM32最小系统核心板子出厂时已经焊接好了1个led灯(标注了PC13处),一般可通过此灯的点亮让编程者验证自己烧录的代码是否正常运行了。请查阅最小版电路原理图和相关资料,将这个灯也用在流水灯中,重编新程序。
stm32F103C8T6最小核心板
单片机最小系统一般有晶振电路、电源电路、复位电路以及调试电路组成。
1.电源电路
主要有两部分组成:
1、供电电路
可以使用普通的USB接口电路,5V电源输出
2、降压电路
USB的5V输入,然后输出为3.3V
这里使用两种不同的电容。
1、输入滤波电容的作用:
输入电压,当接入电源,其幅值是从零起始的,波动非常大,加入足够容量的电容进行滤波后,因电容的充放电效应,该脉动直流变成纹波不大的直流电,这是输入滤波的作用。
2、输出滤波电容的作用:
稳压电路的工作过程需要从输出采样,然后根据其反馈值调节输出以达稳压的目的。如果此时没有输出滤波电容,只要因负载变化带来的电压波动频率恰好与稳压电路的调节速率差不多就会产生振荡效应,导致输出失控,所以稳压输出也必须加滤波电容,而且增加滤波电容也可以进一步增加稳压输出的稳定性。
3、大电容和小电容并联的作用:
至于与大容量电解电容并联的小电容,其作用在于旁路频率较高的波动电压,因为铝电解电容的制造工艺导致其具有较大的ESL(等效电感),无法滤除高频成份,故需加个小电容。
2、晶振电路
晶振电路用来给芯片提供时钟信号,原理图如下:
3.复位电路
复位电路如下:
stm32有三种复位方式:电源复位、系统复位和后备域复位电源复位时,当NRST引脚被拉低,产生外部复位,并产生复位脉冲,从而使系统复位。
4.去耦电容
主要用来滤除杂波,保持引脚电压的稳定。这些电容也尽量离芯片相关引脚近一点。分布在芯片四周即可。
5.调试下载电路
6、总原理图
芯片引脚图
这是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。
STM32F103C8T6单片机采用LQFP48封装设计,芯片一共引出44只引脚,其中A口有A0-A15共16个引脚,B口有B0-B15共16个引脚,C口有C13-C15共3个引脚,D口有D0-D1共两个引脚。
1、电源管脚: 引脚图中的 VDD、VSS、VREF+、VREF-、VSSA、VDDA 等都属于电源引脚。
2、晶振管脚:引脚图中的 PC14、PC15 和 OSC_IN、OSC_OUT 都属于晶振引脚,不过它们还可以作为普通引脚使用。
3、复位管脚: 引脚图中的 NRST 属于复位引脚,不做其他功能使用。
4、下载引脚:引脚图中的 PA13、PA14、PA15、PB3 和 PB4 属于 JTAG 或SW 下载引脚。不过它们还可以作为普通引脚或者特殊功能使用,具体的功能可以查看芯片数据手册,里面都会有附加功能说明。当然,STM32 的串口功能引脚也是可以作为下载引脚使用。
5、T BOOT 引脚:引脚图中的 BOOT0 和 PB2(BOOT1)属于 BOOT 引脚,PB2 还可以作为普通管脚使用。在 STM32 启动中会有模式选择,其中就是依靠着 BOOT0和 BOOT1 的电平来决定。
6、GPIO管脚:引脚图中的 PA、PB、PC、PD 等均属于 GPIO 引脚。从引脚图可以看出,GPIO 占用了 STM32 芯片大部分的引脚。并且每一个端口都有 16 个引脚,比如 PA 端口,它有 PA0-PA15。其他的 PB、PC 等端口是一样的。
原理学习
寄存器
寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,存储器有累加器(ACC)。
寄存器地址配置:
GPIOA寄存器地址从0x4001 0800开始GPIOB寄存器地址从0x4001 0C00开始GPIOC寄存器地址从0x4001 1100开始
外设时钟使能寄存器
GPIOA~C的时钟是能寄存器为RCC_APB2ENR,由于RCC寄存器地址为0x4002 1000,RCC_APB2ENR的偏移地址为0x18,因此实际RCC_APB2ENR地址为:
0x4002 1000+0x18=0x4002 1018
GPIO配置寄存器
低寄存器偏移地址为0x00,所以计算所得与原地址相同。
高寄存器偏移地址为0x04,PA4(4<0~7,低寄存器)的配置寄存器0x40010800(0x40010800+0x00)
PA9(9>0~7,高寄存器)的配置寄存器地址为0x4001 0C04 (0x40010C00 +0x04)
PA15(15>0~7,高寄存器)的配置寄存器地址为0x4001 0804(0x40011000+0x04)
GPIO介绍
输入输出端口的简称。可以通过软件控制其输出和输入。
内部结构:
主要功能:
1、输入模式(模拟、上拉、下拉、浮空)
在输入模式时,施密特触发器打开,输出被禁止。
可通过输入数据寄存器GPIOx_IDR 读取 I/O 状态。
输入模式可以配置为模拟、上拉、下拉以及浮空模式。上拉和下拉输入很好理解,默认的电平由上拉或者下拉决定。
浮空输入的电平是不确定的,完全由外部的输入决定,一般接按键的时候可以使用这个模式。
模拟输入则用于 ADC 采集。
2、输出模式(推挽/ / 开漏)
在输出模式中,推挽模式时双 MOS 管以推挽方式工作,输出数据寄存器GPIOx_ODR 可控制 I/O 输出高低电平。
开漏模式时,只有 N-MOS 管工作,输出数据寄存器可控制 I/O 输出高阻态或低电平。
输出速度可配置,有2MHz\25MHz\50MHz 的选项。此处的输出速度即 I/O 支持的高低电平状态最高切换频率,支持的频率越高,功耗越大,如果功耗要求不严格,把速度设置成最大即可。
在输出模式时,施密特触发器是打开的,即输入可用,通过输入数据寄存器 GPIOx_IDR 可读取 I/O 的实际状态。
3、复用功能(推挽/ / 开漏)
复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器 GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取 I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。
4、模拟输入输出(上下拉无影响)
模拟输入输出模式中,双 MOS 管结构被关闭,施密特触发器停用,上/下拉也被禁止。其它外设通过模拟通道进行输入输出。通过对 GPIO 寄存器写入不同的参数,就可以改变 GPIO 的应用模式,再强调一下,要了解具体寄存器时一定要查阅《STM32F1xx 参考手册》中对应外设的寄存器说明。在 GPIO 外设中,通过设置“端口配置寄存器 GPIOx_CRL 和 GPIOx_CRH”可配置 GPIO 的工作模式和输出速度。CRH 控制端口的高八位,CRL 控制端口的低八位。
protues仿真
代码
#define GPIOA_BASE 0x40010800
#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
#define GPIOA_CRL (*(unsigned int *)0x40010800)
#define GPIOB_CRH (*(unsigned int *)0x40010C04)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
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低电平
Delay_ms(1000);
GPIOA_ODR=0x1<<4; //PA4高电平
}
void B_LED_LIGHT(){
GPIOB_ODR=0x0<<9; //PB9低电平
Delay_ms(1000);
GPIOB_ODR=0x1<<9; //PB9高电平
}
void C_LED_LIGHT(){
GPIOC_ODR=0x0<<15; //PC15低电平
Delay_ms(1000);
GPIOC_ODR=0x1<<15; //PC15高电平
}
int main(){
int j=100;
// 开启时钟
RCC_APB2ENR |= (1<<2); // 开启 GPIOA 时钟
RCC_APB2ENR |= (1<<3); // 开启 GPIOB 时钟
RCC_APB2ENR |= (1<<4); // 开启 GPIOC 时钟
// 设置 GPIO 为推挽输出
GPIOA_CRL &= 0xfff0ffff; //设置位清零
GPIOA_CRL|=0x00020000; //PA4推挽输出
GPIOB_CRH&= 0xffffff0f; //设置位 清零
GPIOB_CRH|=0x00000020; //PB9推挽输出
GPIOC_CRH &= 0x0fffffff; //设置位 清零
GPIOC_CRH|=0x20000000; //PC15推挽输出
// 3个LED初始化为不亮(即高点位)
GPIOA_ODR |= (1<<4);
GPIOB_ODR |= (1<<9);
GPIOC_ODR |= (1<<15);
while(j){
A_LED_LIGHT();
B_LED_LIGHT();
C_LED_LIGHT();
}
}
void SystemInit(){
}
总结心得
此次实验我学习了什么叫做寄存器与GPIO,并且学习了如何计算寄存器配置时由于偏移地址带来的影响。还再次学习了如何配置keil来仿真stm32系列的芯片。