freeelectron 发表于 2022-3-23 21:46

【GD32L233C-START评测】19、低功耗串口(深度休眠唤醒、空闲中断不定长数据接收)

<p>相关文章:</p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192456-1-1.html" target="_blank">【GD32L233C-START评测】1、优点与缺点都很明显的GD32L233C-START(开箱)</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192706-1-1.html" target="_blank">【GD32L233C-START评测】2、非阻塞方式点灯,blink,blink,blink&hellip;&hellip;</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192810-1-1.html" target="_blank">【GD32L233C-START评测】3、pwm实现呼吸灯</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192835-1-1.html" target="_blank">【GD32L233C-START评测】4、串口不定长数据接收</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192861-1-1.html" target="_blank">【GD32L233C-START评测】5、Flash读写&mdash;&mdash;使用内部Flash存储数据</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192917-1-1.html" target="_blank">【GD32L233C-START评测】6、硬件I2C驱动0.96吋OLED</a></p>

<p><a href="https://bbs.eeworld.com.cn/forum.php?mod=viewthread&amp;tid=1193325&amp;pid=3120335&amp;page=1&amp;extra=#pid3120335" target="_blank">【GD32L233C-START评测】7、硬件SPI1驱动RC522</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192936-1-1.html" target="_blank">【GD32L233C-START评测】8、获取MCU96位唯一ID、SRAM、FLASH大小</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1192994-1-1.html" target="_blank">【GD32L233C-START评测】9、IAP程序升级&mdash;&mdash;基于YMODEM协议</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193073-1-1.html" target="_blank">【GD32L233C-START评测】10、使用内部参考电压校准adc,adc采样更准确</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193079-1-1.html" target="_blank">【GD32L233C-START评测】11、GD32 ISP软件还不支持GD32L233</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193152-1-1.html" target="_blank">【GD32L233C-START评测】12、按键&mdash;&mdash;外部中断</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193187-1-1.html" target="_blank">【GD32L233C-START评测】13、I2C驱动环境光和接近传感器RPR-0521RS</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193224-1-1.html" target="_blank">【GD32L233C-START评测】14、RT-Thread移植到GD32L233(内核,finsh移植)</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193244-1-1.html" target="_blank">【GD32L233C-START</a><a href="https://bbs.eeworld.com.cn/thread-1193224-1-1.html" target="_blank">评测</a><a href="https://bbs.eeworld.com.cn/thread-1193244-1-1.html" target="_blank">】15、RT-Thread消息队列、多线程使用</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1193269-1-1.html" target="_blank">【GD32L233C-START评测】16、RT-Thread事件集从中断唤醒任务</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1194428-1-1.html" target="_blank">【GD32L233C-START评测】17、CMSIS-RTOS2 RTX5移植到GD32L233(内核,多线程)</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1197266-1-1.html" target="_blank">【GD32L233C-START评测】18、硬件SPI驱动(ST7735)1.8吋TFT LCD</a></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">1、GD32L233低功耗串口</span></p>

<p><span style="font-size:16px;">&nbsp;可以看出GD32L233系列都只有一个低功耗串口。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">2、串口引脚复用</span></p>

<p><span style="font-size:16px;">&nbsp;使用PA2和PA3,复用功能为AF8。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">3、开发板LPUART引脚</span></p>

<p> &nbsp;</p>

<p><span style="font-size:26px;">4、mcu从深度休眠唤醒条件</span></p>

<p><span style="font-size:16px;">&nbsp;可以看出唤醒的条件是外部中断或事件。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">5、串口为什么能从休眠唤醒mcu</span></p>

<p><span style="font-size:16px;">&nbsp;可以看出,LPUART连接到了外部中断28上,属于外部中断,这正是串口为什么能从休眠唤醒mcu的原因。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">6、串口从休眠唤醒方式</span></p>

<p></p>

<p>&nbsp;</p>

<p><span style="font-size:26px;">7、代码实现</span></p>

<pre>
<code>struct
{
        uint8_t RecvBuff;
        uint8_t RecvLen;
        uint8_t Idle:1;
}LpSerialStr;//串口数据处理结构体</code></pre>

<pre>
<code>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);       
}
</code></pre>

<p>&nbsp;</p>

<pre>
<code>void LpSerialRecv(uint8_t data)//串口接收
{
        if(LpSerialStr.RecvLen&lt;200)
        {
                LpSerialStr.RecvBuff=data;
        }
}


void LpSerialSend(uint8_t *data,uint8_t len)//串口发送
{
        for(uint8_t i=0; i&lt;len;i++)
        {
                while (RESET == lpuart_flag_get(LPUART_FLAG_TBE));
                lpuart_data_transmit(data);
                while (RESET == lpuart_flag_get(LPUART_FLAG_TC));//LPUART_FLAG_TBE
        }
}


void LpSerialPro(void)                  //串口接收数据处理
{
        uint8_t len;
               
        if(LpSerialStr.Idle&amp;&amp;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;
        }
}</code></pre>

<p>&nbsp;</p>

<pre>
<code>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 &amp;= ~RCU_CFG0_SCS;
    RCU_CFG0 |= RCU_CKSYSSRC_PLL;
}</code></pre>

<p>&nbsp;</p>

<pre>
<code>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);
        }
}</code></pre>

<p><span style="font-size:26px;">8、现象</span></p>

<p><span style="font-size:16px;">&nbsp;打印&ldquo;enter&rdquo;提示进入休眠,接收到数据后唤醒,打印&ldquo;recover&rdquo;,唤醒后同时处理,唤醒时接收到的串口数据;</span></p>

<p><span style="font-size:16px;">之后,发送不定长数据,串口在接收完后,将接收到的数据再打印出来。</span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

aprilhome 发表于 2022-8-18 15:56

<p>学习一下,如果用普通串口,如usart1是相同配置吗</p>

hjl2832 发表于 2022-8-19 08:21

<p>有测过休眠电流和唤醒电流各是多少吗?否则没任何意义。</p>

zqm656993 发表于 2023-6-29 13:59

睡眠模式电流250uA

xiaoyh520 发表于 2023-9-14 14:39

GOOD
页: [1]
查看完整版本: 【GD32L233C-START评测】19、低功耗串口(深度休眠唤醒、空闲中断不定长数据接收)