Day3
目录
一、基于寄存器的新建模板
1.新建工程
2.将启动文件添加到目录下
3.在分组中添加文件
注意选择ALL File
4.与固件库版本区别
在Reset_Handler当中注释掉库函数初始化的代码
5.勾选HEX
复制代码
6.实验现象:
通过串口发送数据
二、GPIO工作原理
1.初识GPIO
STM32F103ZET6(144脚芯片)
7组IO,每组16个,一共112个IO口。
GPIOA,GPIOB…GPIOG
GPIOA:PA0~PA15(A,B,C,D,E,F,G均是16个IO口)
FT表示可以容忍5V
2. 4种输入模式:
输入浮空,输入上拉,输入下拉,模拟输入
GPIO的输入工作模式1—输入浮空模式
- .GPIO的输入工作模式2—输入上拉模式
- GPIO的输入工作模式3—输入下拉模式
- GPIO的输入工作模式4—模拟模式
3. 4种输出模式:
开漏输出,开漏复用功能,推挽式输出,推挽式复用功能
- GPIO的输出工作模式1—开漏输出模式
- GPIO的输出工作模式2—开漏复用输出模式
- GPIO的输出工作模式3—推挽输出模式
④GPIO的输出工作模式4—推挽复用输出模式
4. 3种最大翻转速度:
2MHZ,10MHZ,50MHZ
5. GPIO工作方式
推挽输出:可以输出强高低电平,连接数字器件 。
开漏输出:只可以输出强低电平,高电平得靠外部电阻拉高。
每组GPIO端口的寄存器包括:
两个32位配置寄存器(GPIOx_CRL ,GPIOx_CRH)
两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR)
一个32位置位/ 复位寄存器(GPIOx_BSRR)
一个16位复位寄存器(GPIOx_BRR)
一个32位锁定寄存器(GPIOx_LCKR)
每个I/O端口位可以自由编程,然而I/O端口寄存器必须按32位字被访问(不允许半字或字节访问) 。
每组IO口含下面7个寄存器。也就是7个寄存器,一共可以控制一组GPIO的16个IO口。
GPIOx_CRL :端口配置低寄存器
GPIOx_CRH:端口配置高寄存器
GPIOx_IDR:端口输入寄存器
GPIOx_ODR:端口输出寄存器
GPIOx_BSRR:端口位设置/清除寄存器
GPIOx_BRR :端口位清除寄存器
GPIOx_LCKR:端口配置锁存寄存器
①.端口配置低寄存器(GPIOx_CRL)和端口配置高寄存器(GPIOx_CRH)
②.端口输入数据寄存器(GPIOx_IDR)
③.端口输出数据寄存器(GPIOx_ODR)
通过设置ODR控制端口位为上拉还是下拉输出模式
ODRx设置为0就是下列输入,ODRx设置为1就是上拉输入。
④端口位设置/清除寄存器(GPIOx_BSRR)
⑤端口位清除寄存器(GPIOx_BRR)
通常就采用BSRR的低16位和BRR的低16位,因为BRR的低16位与BSRR的高16位作用类似。
⑤端口复用功能: STM32的大部分端口都具有复用功能。 所谓复用,就是一些端口不仅仅可以做为通用IO口,还可以复用为一些外设引脚。
⑥端口重映射功能:就是可以把某些功能引脚映射到其他引脚。比如串口1默认引脚是PA9,PA10可以通过配置重映射映射到PB6,PB7。
和51单片机相比,32所有的IO口都可以作为中断输入。
三、GPIO原理应用:基于固件库的LED灯
1.配置环境
需要stm32f10x_gpio.c用于控制io口,stm32f10x_rcc.c配置外设时钟,以及头文件
(取消这两个的注释)
2.初始化结构体GPIO_InitTypeDef
3.对GPIO结构体成员赋予控制参数
这样实现了对GPIO的初始化
4.开启外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
所有的GPIO都是挂载到APB2上的
开启复用时钟ADC1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
5.控制IO输出高低电平
这里要用到两个函数 GPIO_SetBits()输出高电平,GPIO_ResetBits()输出低电平。初始先调用GPIO_SetBits()函数让几个引脚输出高电平,使LED处于灭状态
6.续行符“/”
用于连接上下行代码,在/后面不能有空格、注释等一切杂物
7.写代码
[main.c]
#include "stm32f10x.h"
#include "bsp_led.h"
void Delay(__IO u32 nCount);
int main(void)
{
/*LED端口初始化*/
LED_GPIO_Config();
while(1)
{
LED1(ON); // 亮
Delay(0x0FFFEF);
LED1(OFF); // 灭
LED2(ON); // 亮
Delay(0x0FFFEF);
LED2(OFF); // 灭
LED3(ON); // 亮
Delay(0x0FFFEF);
LED3(OFF); // 灭
}
}
void Delay(__IO u32 nCount) //简单的延时函数
{
for(; nCount !=0;nCount--);
}
[bsp_led.c]
//板级支持包
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启GPIOC的外设时钟*/
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE);
/*选择要控制的GPIOC引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
/*设置引脚模式为推挽输出*/
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOC*/
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*关闭所有LED*/
GPIO_SetBits(GPIOC,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);
}
[bsp_led.h]
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
/**
* 定义LED的开关
* 1是关,0是开
*/
#define ON 0
#define OFF 1
//带参宏,可以像内联函数一样使用
#define LED1(a) if(a) \
GPIO_SetBits(GPIOC,GPIO_Pin_3);\
else \
GPIO_ResetBits(GPIOC,GPIO_Pin_3)
#define LED2(a) if(a) \
GPIO_SetBits(GPIOC,GPIO_Pin_4);\
else \
GPIO_ResetBits(GPIOC,GPIO_Pin_4)
#define LED3(a) if(a) \
GPIO_SetBits(GPIOC,GPIO_Pin_5);\
else \
GPIO_ResetBits(GPIOC,GPIO_Pin_5)
void LED_GPIO_Config(void);
#endif /* __LED_H */
四、今日总结
今天是收获颇丰的一天,通过实际写程序串联了前段时间的积累,可谓重见光明。当然,巨大的封装量(库函数)也让我认识到了32的高山比51高太多,要移这座山需要不断地投入才可以。
今天我先看书《库开发指南》然后再看视频,效果很好,因为书可以反复读,视频里一带而过的知识无法形成记忆,书可以很好的弥补这一点。多亏于此我彻底弄明白了GPIOx和CRLCRH等寄存器的作用
今天不知什么原因,写的程序不能点亮LED,我已经重新购买野火原装的仿真器,希望新的仿真器可以成功烧录文件
后记:这篇文章我后来也进行了完善,并且添加了一些图文,一开始对GPIO理解不透彻,感觉其十分抽象,经过后面对GPIO的应用,逐渐认识其重要性,也借此重新完善文章的机会,重新加深了对GPIO的理解和记忆