【实验步骤】
1. 学习 STM32 电源控制相关知识,熟悉所调用的库函数。2.搭建测试电路。 3.编写程序,测试电流消耗,对照数据手册,对没有达到的指标进行分析。
【程序代码】
#include "stm32f10x.h" #include "stm32_eval.h"
GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure;
void EXTI_Config_owl(void);
void RCC_Config_HSI_32M_owl(void); void RCC_Config_HSE_32M_owl(void); void TIM2_Base_Config_owl(void);
void TIM2_PWM_Config_owl(void);
void USART1_Config_owl(void);//配置 USART1 口
void RTC_Config_owl(void);//RTC 配置
int main(void)
{
RCC_Config_HSI_32M_owl();//配置内部时钟到 32M
// RCC_Config_HSE_32M_owl();//选择 HSE 倍频做为时钟
EXTI_Config_owl(); //对接收中断的初始化USART1_Config_owl();//配置 USART1 口
TIM2_Base_Config_owl();
RTC_Config_owl(); //对 RTC 配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);//时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);//时钟使能
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_OD ; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFE); //进入停机模式
// PWR_EnterSTANDBYMode(); //进入待机模式
while (1)
{
}
}
void EXTI_Config_owl(void)
{
NVIC_InitTypeDef NVIC_InitStructure;//NVIC 配置结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//中断时钟使能
//中断向量控制 reg 初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//对优先级的配置,还需要简单了解
//使能 1 中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
// 选 择 做 中 断 的 引 脚 A1 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
//外中断初始化设置
EXTI_InitStructure.EXTI_Line = EXTI_Line1;//第 1 线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能EXTI_Init(&EXTI_InitStructure);//操作
EXTI_GenerateSWInterrupt(EXTI_Line1);//类似于允许中断EXTI_ClearITPendingBit(EXTI_Line1);//退出之前一定要记得清标志位
}
//配置时钟使用 HSI,32M
void RCC_Config_HSI_32M_owl(void)
{
RCC_DeInit();//复位到初始值RCC_HSICmd(ENABLE);//使能 HSI
RCC_AdjustHSICalibrationValue(0x10);//校正值FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能预取指缓存区FLASH_SetLatency(FLASH_Latency_1);//设置 flash 操作等待RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选择 PLL 作为系统时钟RCC_HCLKConfig(RCC_SYSCLK_Div1);//主时钟不分频RCC_PCLK1Config(RCC_HCLK_Div1);//APB1 由 AHB 不分频得到RCC_PCLK2Config(RCC_HCLK_Div1);//APB2 由 AHB 不分频得到RCC_ITConfig(RCC_IT_HSIRDY , ENABLE );//HSI 中断允许
//RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);//USB 时钟为系统不分频RCC_ADCCLKConfig(RCC_PCLK2_Div8);//AD 时钟为 AOB2 的 2 分频RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SRAM | RCC_AHBPeriph_FLITF,
ENABLE);//使能 SRAM、FLITF 时钟
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_8);//PLL 时钟源及倍频因子设定
RCC_PLLCmd(ENABLE);//使能 PLL
while (RCC_GetSYSCLKSource() != 0x08)//检查时钟是否配置正确
{
}
}
//配置时钟使用 HSE,32M
void RCC_Config_HSE_32M_owl(void)
{
ErrorStatus HSEStartUpStatus;
RCC_DeInit();//复位到初始值RCC_HSEConfig(RCC_HSE_ON);;//使能 HSE
HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待 HSE 准备好
if (HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能预取指缓存区FLASH_SetLatency(FLASH_Latency_1);//设置 flash 操作等待RCC_HCLKConfig(RCC_SYSCLK_Div1);//主时钟不分频RCC_PCLK1Config(RCC_HCLK_Div2);//APB1 由 AHB2 分频得到RCC_PCLK2Config(RCC_HCLK_Div1);//APB2 由 AHB 不分频得到RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_4);//PLL 时钟源及倍频因
子设定
RCC_PLLCmd(ENABLE);//使能 PLL
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)//等待 PLL 启动
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选择 PLL 作为系统时钟
//RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);//USB 时钟为系统不分频RCC_ADCCLKConfig(RCC_PCLK2_Div2);//AD 时钟为 AOB2 的 2 分频RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SRAM | RCC_AHBPeriph_FLITF,
ENABLE);//使能 SRAM、FLITF 时钟
while(RCC_GetSYSCLKSource() != 0x08)
{
}
}
}
// 程序名 : void TIM2_Base_Config_owl(void)
// 作用 : 通用定时器 2 配置函数,配置定时器 2 工作在普通计时模式
// 输入参数:无
// 输出参数:无
// 说明: 配置定时器 2 工作在普通计时模式,定时器 UP 模式,使能 up 中断,
//
void TIM2_Base_Config_owl(void)
{
NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//中断时钟使能 为什么要使能这个时钟?
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//中断向量在 flash 中
// 中 断 控 制 器 中 选 中 TIM2 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//定时器基本配置
TIM_TimeBaseStructure.TIM_Period = 0x4000;//重载计数值TIM_TimeBaseStructure.TIM_Prescaler = TIM_PSCReloadMode_Update;//估计这个只是对
分频因子何时装载进行设置
//TIM_TimeBaseStructure.TIM_Prescaler = 0x0002; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;//还不清楚作用TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//操作
TIM_PrescalerConfig(TIM2, 0x0000, TIM_PSCReloadMode_Immediate);//定时器使用的时钟的分频设置
TIM_ITConfig(TIM2, TIM_IT_Update , ENABLE);//对定时器中哪个中断源进行设置。TIM_Cmd(TIM2, ENABLE);//定时器 2 允许工作
}
// 程序名 : void USART1_Config_owl(void)
// 作用 : 配置 USART1 口工作在普通异步传输模式
// 输入参数:无
// 输出参数:无
// 说明:
//
//
void USART1_Config_owl(void)
{
USART_InitTypeDef USART_InitStructure;//配置 USART 数据结构NVIC_InitTypeDef NVIC_InitStructure;//NVIC 配置结构体GPIO_InitTypeDef GPIO_InitStructure;//GPIO 配置结构体
//GPIO 配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);//时钟使能
//TX 配置GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
//RX 配置
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 ,ENABLE);//时钟使能
USART_InitStructure.USART_BaudRate=57600; //波特率USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8 位数据USART_InitStructure.USART_StopBits=USART_StopBits_1;//1 个停止位USART_InitStructure.USART_Parity=USART_Parity_No;//无校验USART_InitStructure.USART_Mode=USART_Mode_Rx | USART_Mode_Tx; //模式
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//
硬件流控制失能
USART_Init(USART1, &USART_InitStructure);//操作
//对 USART1 中断的配置,这是可选项,很多时候可以不使用中断
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//中断时钟使能 为什么要使能这个时钟?
//中断向量控制 reg 初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//对优先级的配置,还需要简单了解
//使能对 USART1 中断NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USART1, USART_IT_TC | USART_IT_RXNE, ENABLE);//使能发
送完成中断和接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//使能接收中断
// USART_ITConfig(USART1, USART_IT_TC, ENABLE);//使能发送完成中断
USART_Cmd(USART1, ENABLE);
}
// 程序名 : void RTC_Config_owl(void)
// 作用 : 配置 RTC 和 BKP,RTC 开启秒中断。
// 输入参数:无
// 输出参数:无
// 说明:
//
//
void RTC_Config_owl(void)
{
NVIC_InitTypeDef NVIC_InitStructure;//NVIC 配置结构体
EXTI_InitTypeDef EXTI_InitStructure;
//对 RTC 中断的配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//中断时钟使能
//中断向量控制 reg 初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//对优先级的配置,还需要简单了解
// NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//RTC 中断NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;//闹钟中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
//闹钟中断接到第 17 线,视为 17 线外引脚中断, EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitStructure.EXTI_Line = EXTI_Line17; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);//电源管理部分时钟开启
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);//BKP 部分使能
PWR_BackupAccessCmd(ENABLE);//使能或者失能 RTC 和后备寄存器访问
//RCC_LSEConfig(RCC_LSE_ON);//使能 LSE RCC_LSICmd(ENABLE);//使能 LSI
//等待晶振启动(有内、外之分)
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//设置时钟为内部低振RCC_RTCCLKCmd(ENABLE);
//若在读取 RTC 寄存器时,RTC 的 APB1 接口曾经处于禁止状态,
//则软件首先必须等待 RTC_CRL 寄存器中的 RSF 位(寄存器同步标志)被硬件置’1’。
RTC_WaitForSynchro();
RTC_WaitForLastTask();//等待最近一次对 RTC 寄存器的写操作完成
// RTC_ITConfig(RTC_IT_SEC);//使能秒中断RTC_ITConfig( RTC_IT_ALR, ENABLE);//使能闹钟中断RTC_WaitForLastTask();
RTC_SetPrescaler(32767); //分频系数RTC_WaitForLastTask(); RTC_SetCounter(0x0); //初始计数值RTC_WaitForLastTask(); RTC_SetAlarm(5);//闹钟变量RTC_WaitForLastTask();
}
闹钟中断服务函数
// 程序名 : void RTCAlarm_IRQHandler(void)
// 作用 : 本函数是闹钟中断处理函数
// 输入参数:无
// 输出参数:无
// 说明:
//
void RTCAlarm_IRQHandler(void)
{
//若在读取 RTC 寄存器时,RTC 的 APB1 接口曾经处于禁止状态,
//则软件首先必须等待 RTC_CRL 寄存器中的 RSF 位(寄存器同步标志)被硬件置’1’。
RTC_WaitForSynchro(); if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line17);//清 17 线中断标志
//检查 Wake-Up 标志置位
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
PWR_ClearFlag(PWR_FLAG_WU);//清标志
}
RTC_WaitForLastTask(); RTC_SetAlarm(RTC_GetCounter()+ 3); //重设闹钟标志RTC_WaitForLastTask(); RTC_ClearITPendingBit(RTC_IT_ALR);//清闹钟标志位RTC_WaitForLastTask();
}
}
|