为什么每用一个GPIO引脚,都要初始化一次时钟?
TM32 微控制器采用了 时钟门控(Clock Gating)机制,这是现代微控制器的一种功耗管理策略。时钟门控机制的核心思想是,只有在外设需要运行时,才使能相应外设的时钟,而在不使用时关闭时钟,以减少功耗和节省电源。
//初始化时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIO引脚初始化GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //把初始化的值重新在检查赋值一次,与硬件对应上GPIO_Init(GPIOA, &GPIO_InitStructure);
时钟设置
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){//RCC->APB2ENR寄存器对应的RCC_APB2Periph位被置位1,选择响应的时钟RCC->APB2ENR |= RCC_APB2Periph;}else{//RCC->APB2ENR寄存器对应的RCC_APB2Periph位被置位0,其余为不变,关闭响应的时钟RCC->APB2ENR &= ~RCC_APB2Periph;}
}
GPIO引脚的参数选择
typedef struct
{uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIOSpeed_TypeDef */GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
//速度可选项
typedef enum
{ GPIO_Speed_10MHz = 1,GPIO_Speed_2MHz, GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
//模式可选项
typedef enum
{ GPIO_Mode_AIN = 0x0,GPIO_Mode_IN_FLOATING = 0x04,GPIO_Mode_IPD = 0x28,GPIO_Mode_IPU = 0x48,GPIO_Mode_Out_OD = 0x14,GPIO_Mode_Out_PP = 0x10,GPIO_Mode_AF_OD = 0x1C,GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
每个外设(如 GPIO、USART、SPI、ADC 等)都有自己的时钟源。
#define RCC_APB2Periph_AFIO ((uint32_t)0x00000001)
//ABCDEFG 其实是代表不同的 GPIO 端口组,而每个端口组下面可以包含多个 GPIO 引脚(Pin)//GPIOA代表一个时钟组,00000004代表位掩码 用于给寄存器RCC->APB2ENR确定是那一组的时钟使能
//RCC->APB2ENR |= RCC_APB2Periph_GPIOA; #define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG ((uint32_t)0x00000100)#define RCC_APB2Periph_ADC1 ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2 ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1 ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1 ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8 ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1 ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3 ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15 ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16 ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17 ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9 ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10 ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11 ((uint32_t)0x00200000)