打印
[其他]

基于MM32L0130的LPUART应用(1)

[复制链接]
504|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 MM灵灵灵 于 2023-1-4 13:14 编辑

基于MM32L0130的LPUART应用(1)

LPUART(Low power universal asynchronous receiver transmitter,低功耗通用异步收发器),相比标准的UART,其功耗极低,支持在低功耗模式下运行,并且可以将MCU从低功耗模式唤醒。

本文介绍MM32全新低功耗系列MM32L0130的LPUART外设,实现基本UART收发通信、通过UART中断使MCU从低功耗模式中唤醒。

1. LPUART 简介
1.1 LPUART功能框图


1.2 LPUART功能特征
  • 支持UART帧格式的全双工异步数据收发。
  • 支持输入任意频率的时钟源,可配置为LSE/LSI/PCLK。
  • 支持可编程的波特率数据传输,发送和接收时可采用3、4分频交替,防止累计误差。
  • 可配置奇偶校验位、停止位。
  • 可配置收发数据信号取反。

2. LPUART时钟配置
LPUART时钟源配置寄存器在RCC_CFGR2中的位0和位1,可配置LSE、LSI、PCLK作为时钟源。


3. LPUART中断与唤醒
支持的中断源:
  • 接收缓冲溢出
  • 帧错误
  • 奇偶校验错误
  • 接收器检测到起始位
  • 接收器检测到下降沿
  • 接收器完整接收 1byte 数据
  • 接收器完整接收数据且与预设数据匹配
  • 发送器数据完成发送
  • 发送器缓冲空

支持低功耗模式下的唤醒源:
  • 接收器检测到下降沿唤醒
  • 接收器检测到起始位唤醒
  • 接收器1字节接收完成唤醒
  • 接收器1字节数据接收并匹配唤醒

4. 接收和发送时序
由于LPUART工作时钟不是波特率的整数倍,采用固定分频系数的话会引入累计误差,所以在接收和发送的时候采用3、4分频交替进行接收和发送,每个bit采样一次,每个bit采用3分频还是4分频由MCTL寄存器控制,接收和发送时序图如下:


当LPUART工作时钟配置为标准的32.768KHz时,软件可配置BREN为0,然后根据通信波特率调整调制寄存器MCTL,建议配置参数如下表:


5. LPUART寄存器概览


6. LPUART实现普通UART功能配置步骤
  • 开启LPUART所选时钟源
  • 配置RCC_CFGR2寄存器选择LPUART时钟
  • 配置 LPUBAUD 寄存器决定波特率
  • 根据波特率选择合适的调制参数,配置 MCTL 寄存器
  • 配置 LPUCON 寄存器,选择帧格式、极性、中断参数等
  • 配置 LPUEN 寄存器打开发送、接收使能

7. 发送和接收数据
发送数据:
将待发送的数据写入LPUTXD,当发送完成时,LPUSTA的TXE标志位会被硬件置起,表示数据已传入移位寄存器,发送 buffer为空。此时可往LPUTXD写入下一个数据。软件向发送buffer写数据时TXE标志位自动清零。

接收数据:
当接收一个完整帧时,LPUSTA的RXF标志位置起,表示已完整接收数据,此时软件可读取LPURXD读出接收到的数据。软件读LPUDATA寄存器时,RXF标志位自动清零。

8. LPUART功能实现代码
首先编写基础UART的代码,通过轮询的方式发送和接收数据。然后添加中断代码,实现通过LPUART将MCU从低功耗模式唤醒。

8.1 基于LSE时钟的基础UART功能实现代码
  • 开启BKP、LSE时钟,待LSE时钟稳定,使能LPUART时钟:
RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON);
DELAY_Ms(100);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {;}
RCC_APB2PeriphClockCmd(RCC_APB2ENR_LPUART1, ENABLE);

  • 配置LPUART的LPUART_InitTypeDef结构体参数:
LPUART_InitTypeDef init_struct;
init_struct.LPUART_Clock_Source = 0; //时钟源选择
init_struct.LPUART_BaudRate = LPUART_Baudrate_9600; //波特率选择9600
init_struct.LPUART_WordLength = LPUART_WordLength_8b; //8位数据位
init_struct.LPUART_StopBits = LPUART_StopBits_1; //1位停止位
init_struct.LPUART_Parity = LPUART_Parity_No; //没有校验位
init_struct.LPUART_MDU_Value = 0x952; //波特率调制控制寄存器
init_struct.LPUART_NEDET_Source = LPUART_NegativeDectect_Source2;//下降沿采样使能
init_struct.LPUART_RecvEventCfg = LPUART_RecvEvent_Start_Bit;//中断检测模式
LPUART_Init(LPUART1, &init_struct);
LPUART_Cmd(LPUART1, ENABLE);

  • 设置LPUART引脚复用,例程复用到PA4、PA5:
GPIO_InitTypeDef GPIO_InitStruct;
RCC_GPIO_ClockCmd(GPIOA, ENABLE);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_3);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_3);

//LPUART1_TX   GPIOA.4
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);

//LPUART1_RX    GPIOA.5
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);

  • 编写发送函数:
void Output_Byte(LPUART_TypeDef* lpuart, uint8_t dat)
{
    LPUART_SendData(lpuart, dat);
    while(!LPUART_GetFlagStatus(lpuart, LPUART_LPUSTA_TXE));
}

  • 编写轮询接收函数:
uint8_t Input_Byte(LPUART_TypeDef* lpuart)
{
    uint8_t temp;
    while(1) {
        if(LPUART_GetFlagStatus(lpuart, LPUART_LPUSTA_RXF)) {
            //read LPUART_LPUSTA_RXF bit and clear
            temp = (uint8_t)LPUART_ReceiveData(lpuart);
            break;
        }
    }
    if(temp == 0xd) {
        return 0;
    }
    return temp;
}

  • 编写实验样例:
void LPUART_TxRx_Test(void)
{
    uint8_t temp, i;
    char string[] = "LPUART polling test!\r\n";

    for(i = 0; i < strlen(string); i++)
    {
        Output_Byte(LPUART1, string);
    }
    while(1)
    {
        temp = Input_Byte(LPUART1);
        if(temp != 0)
        {
            Output_Byte(LPUART1, temp);
        }
    }
}

  • 在main函数中配置好LPUART后,调用LPUART_TxRx_Test函数,可得到如下实验结果:


8.2 在上述基本LPUART配置的基础上增加中断配置代码,实现唤醒低功耗模式中的MCU
  • 开启SYSCFG、PWR时钟:
RCC_APB2PeriphClockCmd(RCC_APB2ENR_SYSCFG, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);

  • EXTI模块可以产生中断请求,用来唤醒低功耗模式中的MCU,LPUART连接到EXTI22,使能EXTI22:
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_StructInit(&EXTI_InitStruct);
EXTI_InitStruct.EXTI_Line = EXTI_Line22;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);

  • 配置NVIC:
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = LPUART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPriority = 1;
NVIC_Init( &NVIC_InitStruct);

  • 清除接收标志并打开接收中断:
LPUART_ClearITPendingBit(LPUART1, LPUART_LPUIF_RXIF);
LPUART_ITConfig(LPUART1, LPUART_LPUCON_RXIE, ENABLE);

  • 定义RX缓存,然后编写中断服务函数:

char rxDataBuf[10], cnt = 0;
uint8_t cnt_flag = 0;
void LPUART1_IRQHandler()
{
    if(LPUART_GetFlagStatus(LPUART1, LPUART_LPUSTA_START))
    {
        LPUART_ClearFlagStatus(LPUART1, LPUART_LPUSTA_START);

    }
    if(LPUART_GetITStatus(LPUART1, LPUART_LPUIF_RXIF) == SET)
    {
        LPUART_ClearITPendingBit(LPUART1, LPUART_LPUIF_RXIF);
        rxDataBuf[cnt] = LPUART_ReceiveData(LPUART1);
        if(++cnt >= 10)
        {
            cnt_flag = 1;
            cnt = 0;
        }
    }
}

  • 编写实验样例:
void LPUART_Wakeup_Test(void)
{
    uint8_t temp, i;
    char string1[] = "LPUART wakeup mcu test!\r\n";
    char string2[] = "mcu stop!\r\n";
    char string3[] = "mcu wakeup!\r\n";

    for(i = 0; i < strlen(string1); i++)
    {
        Output_Byte(LPUART1, string1);
    }
    DELAY_Ms(20);
    for(i = 0; i < strlen(string2); i++)
    {
        Output_Byte(LPUART1, string2);
    }
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);//休眠
    for(i = 0; i < strlen(string3); i++)
    {
        Output_Byte(LPUART1, string3);
    }

    while(1)
    {

    }
}

  • 在main函数中配置好LPUART后,调用实验函数LPUART_Wakeup_Test,可以的到如下结果:

使用特权

评论回复
沙发
caigang13| | 2023-1-4 22:05 | 只看该作者
LPUART的通信速率最高能到多少?

使用特权

评论回复
板凳
MindMotion|  楼主 | 2023-1-5 14:47 | 只看该作者
caigang13 发表于 2023-1-4 22:05
LPUART的通信速率最高能到多少?

任意比特率情况下,1/2 pclk 的波特率

使用特权

评论回复
地板
Jacquetry| | 2023-1-5 17:04 | 只看该作者
caigang13 发表于 2023-1-4 22:05
LPUART的通信速率最高能到多少?

1/2 pclk 的波特率

使用特权

评论回复
5
tpgf| | 2023-2-1 14:29 | 只看该作者
LPUART

可全双工和半双工。全双工双线,半双工单线。

使用特权

评论回复
6
qcliu| | 2023-2-1 14:45 | 只看该作者
lpuart1_ipg_clk 时钟,这是串口 1 的外设时钟,用于驱动串口 1 的正常运行(除波特率发生器以外的时钟,都由该时钟驱动),该时钟来自 IPG_CLK_ROOT,由 CCGR5[CG12]控制。

lpuart1_ipg_clk_s 时钟,这是串口 1 的访问时钟,必须开启该时钟,才可以访问串口 1 相关寄存器,该时钟来自 IPG_CLK_ROOT,由 CCGR5[CG12]控制。

使用特权

评论回复
7
drer| | 2023-2-1 14:51 | 只看该作者
是什么原理使得它能比普通的串口更加节省功耗呢

使用特权

评论回复
8
coshi| | 2023-2-1 15:10 | 只看该作者
LPUART为low power UART的缩写,其实现较低速率的UART功能,同时具有sleep、stop模式,能够在不使用时关闭,以达到更低功耗的目的

使用特权

评论回复
9
kxsi| | 2023-2-1 15:18 | 只看该作者
drer 发表于 2023-2-1 14:51
是什么原理使得它能比普通的串口更加节省功耗呢

这个说不好 只是知道这个模块很早之前就有了

使用特权

评论回复
10
wiba| | 2023-2-1 15:41 | 只看该作者
请问串口通讯的速度和功耗有关系吗? 有没有相关的定量的说法

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:上海灵动微电子股份有限公司
简介:上海灵动微电子股份有限公司成立于 2011 年,是中国本土通用 32 位 MCU 产品及解决方案供应商。 灵动股份的 MCU 产品以 MM32 为标识,基于 Arm Cortex-M 系列内核,自主研发软硬件和生态系统。目前已量产近 300 多款型号,累计交付超 4 亿颗,在本土通用 32 位 MCU 公司中位居前列。

92

主题

110

帖子

5

粉丝