【程序】STM32L476RG实现在STOP2模式下使用LPTIM,5秒钟从STOP2唤醒

#include 
#include 

// 供printf使用, 项目属性中勾选Use MicroLIB后有效
int fputc(int ch, FILE *fp)
{
	if (fp == &__stdout)
	{
		if (ch == '\n')
		{
			// 自动添加\r
			while ((USART2->ISR & USART_ISR_TXE) == 0); // 等待TDR可写入
			USART2->TDR = '\r';
		}
		while ((USART2->ISR & USART_ISR_TXE) == 0);
		USART2->TDR = ch;
	}
	return ch;
}

int main(void)
{
	RCC->AHB2ENR = RCC_AHB2ENR_GPIOAEN; // 开PA时钟
	RCC->APB1ENR1 = RCC_APB1ENR1_LPTIM1EN | RCC_APB1ENR1_PWREN | RCC_APB1ENR1_USART2EN; // 开低功耗定时器1和串口2时钟
	
	RCC->CSR |= RCC_CSR_LSION; // 开LSI
	while ((RCC->CSR & RCC_CSR_LSIRDY) == 0); // 等待LSI稳定
	RCC->CCIPR = RCC_CCIPR_LPTIM1SEL_0; // LPTIM1时钟选LSI
	
	GPIOA->MODER &= ~(GPIO_MODER_MODE2_0 | GPIO_MODER_MODE3_0); // 串口2端口: PA2~3设为复用模式
	GPIOA->MODER &= ~GPIO_MODER_MODE5_1; // LED灯: PA5设为普通输出(推挽输出)
	GPIOA->BSRR = GPIO_BSRR_BS5; // 开LED灯
	
	// 根据芯片手册的Table 16. Alternate function AF0 to AF7可知
	// PA2-3的复用功能应映射为AF7才是USART2的功能
	GPIOA->AFR[0] = GPIO_AFRL_AFSEL2_2 | GPIO_AFRL_AFSEL2_1 | GPIO_AFRL_AFSEL2_0;
	GPIOA->AFR[0] |= GPIO_AFRL_AFSEL3_2 | GPIO_AFRL_AFSEL3_1 | GPIO_AFRL_AFSEL3_0;
	
	USART2->BRR = 417; // 波特率: 9600
	USART2->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE; // 打开串口2, 允许收发, 开接收中断
	NVIC_EnableIRQ(USART2_IRQn); // 允许执行串口中断函数
	
	LPTIM1->CFGR = LPTIM_CFGR_PRESC_1; // 4分频
	LPTIM1->IER = LPTIM_IER_ARRMIE; // 开定时器中断
	NVIC_EnableIRQ(LPTIM1_IRQn); // 允许执行定时器中断函数
	LPTIM1->CR = LPTIM_CR_ENABLE; // 打开LPTIM, 但暂不开始计时
	LPTIM1->ARR = 39999; // 计时5s
	
	printf("Press 1 to enter stop mode: \n");
	while (1);
}

// 低功耗定时器中断
void LPTIM1_IRQHandler(void)
{
	if (LPTIM1->ISR & LPTIM_ISR_ARRM)
	{
		LPTIM1->ICR = LPTIM_ICR_ARRMCF;
		SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // 退出中断时不再自动进入低功耗模式
		USART2->CR1 |= USART_CR1_UE; // 开串口
		GPIOA->BSRR = GPIO_BSRR_BS5; // PA5=1, 开LED灯
		printf("Waked up!\n");
	}
}

// 串口2中断
void USART2_IRQHandler(void)
{
	uint8_t ch;
	if (USART2->ISR & USART_ISR_RXNE)
	{
		ch = USART2->RDR; // 读取接收到的数据
		if (ch == '1')
		{
			// 串口发送1进入睡眠模式
			printf("Enter stop mode!\n");
			while ((USART2->ISR & USART_ISR_TC) == 0); // 等待串口数据收发完毕
			USART2->CR1 &= ~USART_CR1_UE; // 关闭串口
			LPTIM1->CR |= LPTIM_CR_SNGSTRT; // 定时器开始计时
			GPIOA->BRR = GPIO_BRR_BR5; // PA5=0, 关LED灯
			PWR->CR1 |= PWR_CR1_LPMS_STOP2;
			SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk; // 离开中断时自动进入Stop 2模式
		}
	}
}


你可能感兴趣的:(【程序】STM32L476RG实现在STOP2模式下使用LPTIM,5秒钟从STOP2唤醒)