相关文章:
【GD32L233C-START评测】1、优点与缺点都很明显的GD32L233C-START(开箱)
【GD32L233C-START评测】2、非阻塞方式点灯,blink,blink,blink……
【GD32L233C-START评测】4、串口不定长数据接收
【GD32L233C-START评测】5、Flash读写——使用内部Flash存储数据
【GD32L233C-START评测】6、硬件I2C驱动0.96吋OLED
【GD32L233C-START评测】7、硬件SPI1驱动RC522
【GD32L233C-START评测】8、获取MCU96位唯一ID、SRAM、FLASH大小
【GD32L233C-START评测】9、IAP程序升级——基于YMODEM协议
【GD32L233C-START评测】10、使用内部参考电压校准adc,adc采样更准确
【GD32L233C-START评测】11、GD32 ISP软件还不支持GD32L233
【GD32L233C-START评测】12、按键——外部中断
【GD32L233C-START评测】13、I2C驱动环境光和接近传感器RPR-0521RS
【GD32L233C-START评测】14、RT-Thread移植到GD32L233(内核,finsh移植)
【GD32L233C-START评测】15、RT-Thread消息队列、多线程使用
【GD32L233C-START评测】16、RT-Thread事件集从中断唤醒任务
【GD32L233C-START评测】17、CMSIS-RTOS2 RTX5移植到GD32L233(内核,多线程)
【GD32L233C-START评测】18、硬件SPI驱动(ST7735)1.8吋TFT LCD
1、GD32L233低功耗串口
2、串口引脚复用
3、开发板LPUART引脚
4、mcu从深度休眠唤醒条件
5、串口为什么能从休眠唤醒mcu
可以看出,LPUART连接到了外部中断28上,属于外部中断,这正是串口为什么能从休眠唤醒mcu的原因。
6、串口从休眠唤醒方式
7、代码实现
struct
{
uint8_t RecvBuff[200];
uint8_t RecvLen;
uint8_t Idle:1;
}LpSerialStr; //串口数据处理结构体
void LpuartInit(void)
{
rcu_lpuart_clock_config(RCU_LPUARTSRC_IRC16MDIV); //要进入休眠,时钟必须配置为IRC16M或LXTAL
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_LPUART);
/* connect port to LPUART TX */
gpio_af_set(GPIOA, GPIO_AF_8, GPIO_PIN_2);
/* connect port to LPUART RX */
gpio_af_set(GPIOA, GPIO_AF_8, GPIO_PIN_3);
/* configure LPUART TX as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_2);
/* configure LPUART RX as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_3);
/* LPUART configure */
lpuart_deinit();
lpuart_word_length_set(LPUART_WL_8BIT);
lpuart_stop_bit_set(LPUART_STB_1BIT);
lpuart_parity_config(LPUART_PM_NONE);
lpuart_baudrate_set(115200U);
lpuart_receive_config(LPUART_RECEIVE_ENABLE);
lpuart_transmit_config(LPUART_TRANSMIT_ENABLE);
exti_init(EXTI_28, EXTI_INTERRUPT, EXTI_TRIG_BOTH); //外部中断28配置
nvic_irq_enable(LPUART_WKUP_IRQn, 0); //休眠唤醒中断使能
lpuart_wakeup_mode_config(LPUART_WUM_RBNE ); //唤醒方式,一定要在串口使能之前配置
lpuart_wakeup_enable();
lpuart_interrupt_enable(LPUART_INT_WU); //休眠唤醒中断
lpuart_enable();
lpuart_interrupt_enable(LPUART_INT_RBNE); //接收中断
while(RESET == lpuart_flag_get(LPUART_FLAG_IDLE)){};
lpuart_flag_clear(LPUART_FLAG_IDLE);
lpuart_interrupt_enable(LPUART_INT_IDLE); //空闲中断
nvic_irq_enable(LPUART_IRQn, 3); //低功耗串口中断使能
void LpSerialSend(uint8_t *data,uint8_t len);
LpSerialSend((uint8_t *)"enter\r\n",7);
rcu_periph_clock_enable(RCU_PMU);
pmu_to_deepsleepmode(PMU_LDNPDSP_LOWDRIVE, WFI_CMD, PMU_DEEPSLEEP); //进入休眠
void system_clock_reconfig(void);
system_clock_reconfig(); //
LpSerialSend((uint8_t *)"recover\r\n",9);
}
void LpSerialRecv(uint8_t data) //串口接收
{
if(LpSerialStr.RecvLen<200)
{
LpSerialStr.RecvBuff[LpSerialStr.RecvLen++]=data;
}
}
void LpSerialSend(uint8_t *data,uint8_t len) //串口发送
{
for(uint8_t i=0; i<len;i++)
{
while (RESET == lpuart_flag_get(LPUART_FLAG_TBE ));
lpuart_data_transmit(data[i]);
while (RESET == lpuart_flag_get(LPUART_FLAG_TC ));//LPUART_FLAG_TBE
}
}
void LpSerialPro(void) //串口接收数据处理
{
uint8_t len[2];
if(LpSerialStr.Idle&&LpSerialStr.RecvLen)
{
LpSerialSend((uint8_t *)"Recv:",5);
sprintf((char *)len,"%d",LpSerialStr.RecvLen);
LpSerialSend(len,strlen((char *)len));
LpSerialSend((uint8_t *)"[",1);
LpSerialSend(LpSerialStr.RecvBuff,LpSerialStr.RecvLen);
LpSerialSend((uint8_t *)"]\r\n",3);
LpSerialStr.RecvLen=0;
LpSerialStr.Idle=0;
}
}
void system_clock_reconfig(void) //唤醒后重新配置时钟
{
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
while(SUCCESS != rcu_osci_stab_wait(RCU_HXTAL)) {};
/* configure AHB */
rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1);
/* configure APB1, APB2 */
rcu_apb1_clock_config(RCU_APB1_CKAHB_DIV1);
rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1);
/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;
/* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL;
}
void LPUART_IRQHandler(void) //串口中断处理函数
{
if(RESET != lpuart_interrupt_flag_get(LPUART_INT_FLAG_RBNE)) //接收中断
{
LpSerialRecv(lpuart_data_receive());
}
if(RESET != lpuart_interrupt_flag_get(LPUART_INT_FLAG_IDLE)) //空闲中断
{
lpuart_interrupt_flag_clear(LPUART_INT_FLAG_IDLE);
LpSerialStr.Idle=1;
}
}
void LPUART_WKUP_IRQHandler(void) //串口唤醒中断处理函数
{
if(SET == lpuart_interrupt_flag_get(LPUART_INT_FLAG_WU))
{
lpuart_flag_clear(LPUART_FLAG_WU);
exti_flag_clear(EXTI_28);
}
}
8、现象
打印“enter”提示进入休眠,接收到数据后唤醒,打印“recover”,唤醒后同时处理,唤醒时接收到的串口数据;
之后,发送不定长数据,串口在接收完后,将接收到的数据再打印出来。