STM32小笔记(一) GPIO口的配置
GPIO口的使用:
1.GPIO和AFIO全系列支持
GPIO寄存器
(1)两个32位 配置寄存器(GPIOx_CRL,GPIOx_CRH);
(2)两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR);
(3)一个32位置为/复位寄存器(GPIOx_BSRR);
(4)一个16位复位寄存器(GPIOx_BRR);
(5)一个32位锁存器(GPIOx_LCKR);
输入配置
当I/O端口配置为输入时:
●
输出缓冲器被禁止
●
施密特触发输入被激活
●
根据输入配置(上拉,下拉或浮动)的不同,弱上拉和下拉电阻被连接
●
出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器
●
对输入数据寄存器的读访问可得到I/O状态
输出配置
当I/O端口被配置为输出时:
●
输出缓冲器被激活
─
开漏模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将端口置于高阻状态(PMOS从不被激活)。
─
推挽模式:输出寄存器上的’0’激活N-MOS,而输出寄存器上的’1’将激活P-MOS。
●
施密特触发输入被激活
●
弱上拉和下拉电阻被禁止
●
出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器
●
在开漏模式时,对输入数据寄存器的读访问可得到I/O状态
●
在推挽式模式时,对输出数据寄存器的读访问得到最后一次写的值。
STM32中的配置寄存器在固件函数库中早已生成,因此无需再对寄存器的每个设定写定义,而是直接调用关键字。这样我们可以不再关心寄存器的具体配置(因为那已经在固件配置好了);因此直观的从配置函数中去看,更能有效的提高。
GPIO相关的库函数如下,位于在“stm32f10x_gpio.h”
GPIO相关函数如下:
voidGPIO_DeInit(GPIO_TypeDef*
GPIOx);
voidGPIO_AFIODeInit(void);
voidGPIO_Init(GPIO_TypeDef*
GPIOx,
GPIO_InitTypeDef*
GPIO_InitStruct);
voidGPIO_StructInit(GPIO_InitTypeDef*
GPIO_InitStruct);
uint8_tGPIO_ReadInputDataBit(GPIO_TypeDef*
GPIOx,
uint16_t
GPIO_Pin);
uint16_tGPIO_ReadInputData(GPIO_TypeDef*
GPIOx);
uint8_tGPIO_ReadOutputDataBit(GPIO_TypeDef*
GPIOx,
uint16_t
GPIO_Pin);
uint16_tGPIO_ReadOutputData(GPIO_TypeDef*
GPIOx);
voidGPIO_SetBits(GPIO_TypeDef*
GPIOx,
uint16_t
GPIO_Pin);
voidGPIO_ResetBits(GPIO_TypeDef*
GPIOx,
uint16_t
GPIO_Pin);
voidGPIO_WriteBit(GPIO_TypeDef*
GPIOx,
uint16_t
GPIO_Pin,
BitAction
BitVal);
voidGPIO_Write(GPIO_TypeDef*
GPIOx,
uint16_t
PortVal);
voidGPIO_PinLockConfig(GPIO_TypeDef*
GPIOx,
uint16_t
GPIO_Pin);
voidGPIO_EventOutputConfig(uint8_t
GPIO_PortSource,
uint8_t
GPIO_PinSource);
voidGPIO_EventOutputCmd(FunctionalState
NewState);
voidGPIO_PinRemapConfig(uint32_t
GPIO_Remap,
FunctionalState
NewState);
voidGPIO_EXTILineConfig(uint8_t
GPIO_PortSource,
uint8_t
GPIO_PinSource);
voidGPIO_ETH_MediaInterfaceConfig(uint32_t
GPIO_ETH_MediaInterface);
以下将逐个说明函数功能及注释说明:
·voidGPIO_DeInit(GPIO_TypeDef*
GPIOx);
该函数原型在"stm32f10x_gpio.C"当中,类似C++的注释说明如下:
*
@brief
Deinitializes
the
GPIOx
peripheral
registers
to
their
default
reset
values.
*
@param
GPIOx:
where
x
can
be
(A..G)
to
select
the
GPIO
peripheral.
*
@retval
None
其中是为不同组的IO口进行寄存器值的初始化。
初始化语句如下:
“
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA,
ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA,DISABLE);”
再追根溯源到这个函数,位于“stm32f10x_ rcc.C”当中
"voidRCC_APB2PeriphResetCmd(uint32_t
RCC_APB2Periph,
FunctionalState
NewState)"
{
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if
(NewState
!=
DISABLE)
{
RCC->APB2RSTR
|=
RCC_APB2Periph;
}
else
{
RCC->APB2RSTR
&=
~RCC_APB2Periph;
}
}
函数注释如下:
一目了然,即配置IO口时钟状态为使能或者失效。
当然在其中此函数作为一个初学实例还是值得深究的:
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
此处两句即类似于C++中的断言函数,作为函数运行的先决条件。这里将断言函数直接说明,在后续的实例中,仍旧会有使用到的地方。
#define
assert_param(expr)
((expr)
?
(void)0
:
assert_fai
led((uint8_t
*)__FILE__,
__LINE__))
void
assert_failed(uint8_t*
file,
uint32_t
line);
#else
#define
assert_param(expr)
((void)0)
#endif
#endif
若满足断言值为"1"的条件,否则判定失败输出文件名和所在行。不为"0"返回0.
再返回“assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));”此句中。“IS_RCC_APB2_PERIPH”如下定义:
·#defineIS_RCC_APB2_PERIPH(PERIPH)
((((PERIPH)
&
0xFFC00002)
==
0x00)
&&
((PERIPH)
!=
0x00))
此处使用到的是AP2进入该函数还可以看到AP2、AP1、AP三个高速时钟族的各项定义。姑且在这里认为是判定开启对应时钟前的时钟功能验证。
·#defineIS_FUNCTIONAL_STATE(STATE)
(((STATE)
==
DISABLE)
||
((STATE)
==
ENABLE))
只为考虑还是的形参是否是“DISABLE”or“ENABLE”两个状态。
“if
(NewState
!=
DISABLE)
{
RCC->APB2RSTR
|=
RCC_APB2Periph;
}
else
{
RCC->APB2RSTR
1.GPIO和AFIO
GPIO寄存器
(1)两个32位 配置寄存器(GPIOx_CRL,GPIOx_CRH);
(2)两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR);
(3)一个32位置为/复位寄存器(GPIOx_BSRR);
(4)一个16位复位寄存器(GPIOx_BRR);
(5)一个32位锁存器(GPIOx_LCKR);
当I/O端口配置为输入时:
●
●
●
●
●
输出配置
当I/O端口被配置为输出时:
●
─
─
●
●
●
●
●
STM32中的配置寄存器在固件函数库中早已生成,因此无需再对寄存器的每个设定写定义,而是直接调用关键字。这样我们可以不再关心寄存器的具体配置(因为那已经在固件配置好了);因此直观的从配置函数中去看,更能有效的提高。
GPIO相关的库函数如下,位于在“stm32f10x_gpio.h”
GPIO相关函数如下:
void
void
void
void
uint8_t
uint16_t
uint8_t
uint16_t
void
void
void
void
void
void
void
void
void
void
以下将逐个说明函数功能及注释说明:
·void
该函数原型在"stm32f10x_gpio.C"当中,类似C++
其中是为不同组的IO口进行寄存器值的初始化。
初始化语句如下:
“
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA,
再追根溯源到这个函数,位于“stm32f10x_ rcc.C”当中
"void
{
}
函数注释如下:
一目了然,即配置IO口时钟状态为使能或者失效。
当然在其中此函数作为一个初学实例还是值得深究的:
此处两句即类似于C++中的断言函数,作为函数运行的先决条件。这里将断言函数直接说明,在后续的实例中,仍旧会有使用到的地方。
#else
#endif
#endif
若满足断言值为"1"的条件,否则判定失败输出
再返回“assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));”此句中。“IS_RCC_APB2_PERIPH”如下定义:
·#define
此处使用到的是AP2
·#define
只为考虑还是的形参是否是“DISABLE”or“ENABLE”
“