[GD32L233C-START Review] 19. Low-power serial port (deep sleep wake-up, idle interrupt indefinite length data reception)
[Copy link]
Related articles:
[GD32L233C-START Review] 1. GD32L233C-START with obvious advantages and disadvantages (unboxing)
[GD32L233C-START Review] 2. Non-blocking way to light up, blink, blink, blink...
[GD32L233C-START Review] 3. PWM to achieve breathing light
[GD32L233C-START Review] 4. Serial port variable length data reception
[GD32L233C-START Review] 5. Flash Read and Write - Using Internal Flash to Store Data
【GD32L233C-START Review】6. Hardware I2C drive 0.96-inch OLED
[GD32L233C-START Review] 7. Hardware SPI1 driver RC522
[GD32L233C-START Review] 8. Get MCU 96-bit unique ID, SRAM, FLASH size
[GD32L233C-START Review] 9. IAP program upgrade - based on YMODEM protocol
[GD32L233C-START Review] 10. Use internal reference voltage to calibrate ADC, ADC sampling is more accurate
[GD32L233C-START Review] 11. GD32 ISP software does not support GD32L233 yet
[GD32L233C-START Review] 12. Button - External Interrupt
[GD32L233C-START Review] 13. I2C driven ambient light and proximity sensor RPR-0521RS
[GD32L233C-START Review] 14. RT-Thread ported to GD32L233 (kernel, finsh porting)
[GD32L233C-START Review ] 15. RT-Thread message queue, multi-threaded use
[GD32L233C-START Evaluation] 16. RT-Thread event set wakes up tasks from interrupts
[GD32L233C-START Review] 17. CMSIS-RTOS2 RTX5 ported to GD32L233 (kernel, multithreading)
[GD32L233C-START Review] 18. Hardware SPI driver (ST7735) 1.8-inch TFT LCD
1. GD32L233 low power serial port
It can be seen that the GD32L233 series has only one low-power serial port.
2. Serial port pin multiplexing
Use PA2 and PA3, and the multiplexing function is AF8.
3. Development board LPUART pin
4. MCU wake-up conditions from deep sleep
It can be seen that the wake-up condition is an external interrupt or event.
5. Why can the serial port wake up the MCU from sleep mode?
It can be seen that LPUART is connected to external interrupt 28, which is an external interrupt. This is why the serial port can wake up the MCU from sleep mode.
6. Serial port wakeup from sleep mode
7. Code Implementation
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. Phenomenon
Print "enter" to prompt entering sleep mode, wake up after receiving data, print "recover", and process the serial port data received when waking up at the same time;
After that, the indefinite length data is sent, and the serial port prints out the received data after receiving it.
|