MM32L0130

相关阅读:基于MM32L0130的LPUART应用(1)

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

上期介绍了MM32全新低功耗系列MM32L0130的LPUART外设,并实现了基本UART收发通信和使用LPUART唤醒MCU。本期介绍LPUART的高级应用,实现DMA收发实验、使用数据匹配寄存器匹配到指定字符后唤醒MCU。

1、LPUART使用DMA

LPUART可以使用DMA来搬运数据,实现无需CPU参与的快速自动数据传输。硬件发出DMA请求与对应的DMA通道直连,也可以通过软件配置寄存器的方式触发DMA通道请求。LPUART的控制寄存器有对应的DMA使能位,如下图所示:

1.png

1.1  DMA中断

DMA的每个通道都有三种中断事件标志:DMA半传输、DMA传输完成和DMA传输出错。各通道单独的中断请求由这3种事件标志逻辑或起来。可以配置寄存器的对应位来使能这些中断:

2.png

1.2  LPUART使用DMA的配置步骤

1)根据基本UART配置步骤配置LPUART

2)使能LPUEN的DMAR与DMAT位激活DMA模式

3)使能DMA时钟

4)发送需要配置DMA的源地址(存储器地址)和目的地址(LPUTXD),传输的数据量以及DMA通道

5)配置完发送后,只要TXFIFO为空,就会请求DMA发送

6)接收需要配置DMA的源地址(LPURXD)和目的地址(存储器地址),传输的数据量以及DMA通道

7)配置完接收后,只要RXFIFO有数据,即不为空,就会请求DMA接收

1.3  功能代码实现

下面例程实现了使用DMA发送和接收LPUART数据,发送和接收完成后进入中断,例程在基本UART收发实验的基础上完成。

a.申请例程所用到的TX和RX缓存、TX和RX完成标志:

    uint8_t TX_Buffer[16], RX_Buffer[16];
uint8_t TX_Complete = 0, RX_Complete = 0;

b.配置NVIC:

    NVIC_InitTypeDef  NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

c.配置DMA通道2为LPUART_TX:

    void LPUART_DMA_TX_Init(void)
{
    DMA_InitTypeDef DMA_InitStruct;

    RCC_DMA_ClockCmd(DMA1, ENABLE);
    DMA_DeInit(DMA1_Channel2);
    DMA_StructInit(&DMA_InitStruct);
    //DMA transfer peripheral address
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&LPUART1->LPUTXD;
    //DMA transfer memory address
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)TX_Buffer;
    //DMA transfer direction from peripheral to memory
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
    //DMA cache size
    DMA_InitStruct.DMA_BufferSize = 16;
    //The peripheral address is forbidden to move backward
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    //The memory address is shifted backward
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    //Define the peripheral data width to 8 bits
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
    //M2M mode is disabled
    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
    DMA_InitStruct.DMA_Auto_reload = DMA_Auto_Reload_Disable;
    DMA_Init(DMA1_Channel2, &DMA_InitStruct);
    DMA_SetChannelMuxSource(DMA1_Channel2, DMA1_MUX_LPUART1_TX);
    //Enable LPUART_DMA1_Channel Transfer complete interrupt
    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
    LPUART_TX_DMACmd(LPUART1, ENABLE);
    while((LPUART1->LPUEN & LPUART_LPUEN_DMAT) == 0);
    //LPUART_DMA1_Channel enable
    DMA_Cmd(DMA1_Channel2, ENABLE);
}

d.配置DMA通道3为LPUART_RX:

    void LPUART_DMA_RX_Init(void)
{
    DMA_InitTypeDef DMA_InitStruct;

    RCC_DMA_ClockCmd(DMA1, ENABLE);

    DMA_DeInit(DMA1_Channel3);
    DMA_StructInit(&DMA_InitStruct);
    //DMA transfer peripheral address
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&LPUART1->LPURXD;
    //DMA transfer memory address
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)RX_Buffer;
    //DMA transfer direction from peripheral to memory
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
    //DMA cache size
    DMA_InitStruct.DMA_BufferSize = 16;
    //The peripheral address is forbidden to move backward
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    //The memory address is shifted backward
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    //Define the peripheral data width to 8 bits
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
    //M2M mode is disabled
    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
    DMA_InitStruct.DMA_Auto_reload = DMA_Auto_Reload_Disable;
    DMA_Init(DMA1_Channel3, &DMA_InitStruct);
    DMA_SetChannelMuxSource(DMA1_Channel3, DMA1_MUX_LPUART1_RX);
    //Enable LPUART_DMA1_Channel Transfer complete interrupt
    DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
    LPUART_RX_DMACmd(LPUART1, ENABLE);
    while((LPUART1->LPUEN & LPUART_LPUEN_DMAR) == 0);
    //LPUART_DMA1_Channel enable
    DMA_Cmd(DMA1_Channel3, ENABLE);
}

e.编写中断服务函数:

    void DMA1_Channel2_3_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC2))
    {
        DMA_ClearITPendingBit(DMA1_IT_TC2);
        TX_Complete = 1;
    }
    if(DMA_GetITStatus(DMA1_IT_TC3))
    {
        DMA_ClearITPendingBit(DMA1_IT_TC3);
        RX_Complete = 1;
    }
}

f.编写实验样例:

    void LPUART_RxTx_DMA_Test(void)
{
    uint8_t i;

    for(i = 0; i < 16; i++)
    {
        TX_Buffer[i] = i;
    }
    LPUART_DMA_TX_Init();
    LPUART_DMA_RX_Init();

    while(1)
    {
        if(TX_Complete == 1)
        {
            TX_Complete = 0;
            DMA1_Channel3->CMAR = (uint32_t)RX_Buffer;
            DMA1_Channel3->CNDTR = 16;
            DMA_Cmd(DMA1_Channel3, ENABLE);
        }
        if(RX_Complete == 1)
        {
            RX_Complete = 0;
            memcpy((void *)TX_Buffer, (void *)RX_Buffer, 16);
            DMA1_Channel2->CMAR = (uint32_t)TX_Buffer;
            DMA1_Channel2->CNDTR = 16;
            DMA_Cmd(DMA1_Channel2, ENABLE);
        }
    }
}

g.在main函数中配置好LPUART和DMA后,调用实验函数LPUART_RxTx_DMA_Test,可以得到如下结果:

2、使用数据匹配寄存器匹配到指定字符后唤醒MCU

为进一步降低系统功耗,MM32L0130系列的LPUART提供了一种接收到指定字符才能唤醒低功耗状态的MCU的功能。用于唤醒的指定字符,由数据匹配寄存器确定:

4.png

2.1  接收中断配置寄存器

可以通过LPUART的LPUCON.RXEV寄存器配置唤醒事件为START位、一帧接收完成、一帧数据匹配或者RXD下降沿唤醒。

5.png

2.2  功能代码实现

匹配指定字符唤醒MCU功能,需要在上期讲解的LPUART唤醒低功耗模式中的MCU基础上修改中断事件配置、指定唤醒字符,具体代码如下:

a.配置LPUART接收中断事件为接收数据匹配成功:

    LPUART_InitTypeDef init_struct;

init_struct.LPUART_Clock_Source = 0;
init_struct.LPUART_BaudRate = LPUART_Baudrate_9600;
init_struct.LPUART_WordLength = LPUART_WordLength_8b;
init_struct.LPUART_StopBits = LPUART_StopBits_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_RecvData_Mactched;
LPUART_Init(LPUART1, &init_struct);

b.配置特定的唤醒字符:

    LPUART_SetMatchData(LPUART1, ‘5’); //指定字符’5’为唤醒字符

c.编写中断服务程序,判断接收匹配事件并清除标志:

    void LPUART1_IRQHandler()
{
    if(LPUART_GetFlagStatus(LPUART1, LPUART_LPUSTA_START))
    {
        LPUART_ClearFlagStatus(LPUART1, LPUART_LPUSTA_START);
    }
    if(LPUART_GetFlagStatus(LPUART1, LPUART_LPUSTA_MATCH))
    {//判断接收中断匹配事件
        LPUART_ClearFlagStatus(LPUART1, LPUART_LPUSTA_MATCH);

    }
    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;
    }
    EXTI_ClearITPendingBit(EXTI_Line22);
}

d.编写试验样例:

    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[i]);
    }
    DELAY_Ms(20);
    for(i = 0; i < strlen(string2); i++)
    {
        Output_Byte(LPUART1, string2[i]);
    }
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);//休眠
    for(i = 0; i < strlen(string3); i++)
    {
        Output_Byte(LPUART1, string3[i]);
    }

    while(1)
    {

    }
}

e.在main函数配置好LPUART后,调用实验函数LPUART_Wakeup_Test,可以得到如下结果:

6.png

来源:灵动MM32MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 34

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

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

1、LPUART 简介

1.1  LPUART功能框图

1.jpg

1.2  LPUART功能特征

  • 支持UART帧格式的全双工异步数据收发。

  • 支持输入任意频率的时钟源,可配置为LSE/LSI/PCLK。

  • 支持可编程的波特率数据传输,发送和接收时可采用3、4分频交替,防止累计误差。

  • 可配置奇偶校验位、停止位。

  • 可配置收发数据信号取反。

2、LPUART时钟配置

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

2.png

3、LPUART中断与唤醒

支持的中断源:

  • 接收缓冲溢出

  • 帧错误

  • 奇偶校验错误

  • 接收器检测到起始位

  • 接收器检测到下降沿

  • 接收器完整接收 1byte 数据

  • 接收器完整接收数据且与预设数据匹配

  • 发送器数据完成发送

  • 发送器缓冲空

支持低功耗模式下的唤醒源:

  • 接收器检测到下降沿唤醒

  • 接收器检测到起始位唤醒

  • 接收器1字节接收完成唤醒

  • 接收器1字节数据接收并匹配唤醒

4、接收和发送时序

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

3.png

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

4.png

5、LPUART寄存器概览

5.png

6、LPUART实现普通UART功能配置步骤

1)开启LPUART所选时钟源

2)配置RCC_CFGR2寄存器选择LPUART时钟

3)配置 LPUBAUD 寄存器决定波特率

4)根据波特率选择合适的调制参数,配置 MCTL 寄存器

5)配置 LPUCON 寄存器,选择帧格式、极性、中断参数等

6)配置 LPUEN 寄存器打开发送、接收使能

7、发送和接收数据

发送数据:

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

接收数据:

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

8、LPUART功能实现代码

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

8.1  基于LSE时钟的基础UART功能实现代码

a.开启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);

b.配置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);

c.设置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);

d.编写发送函数:

    void Output_Byte(LPUART_TypeDef* lpuart, uint8_t dat)
{
    LPUART_SendData(lpuart, dat);
    while(!LPUART_GetFlagStatus(lpuart, LPUART_LPUSTA_TXE));
}

e.编写轮询接收函数:

    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;
}

f.编写实验样例:

    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[i]);
    }
    while(1)
    {
        temp = Input_Byte(LPUART1);
        if(temp != 0)
        {
            Output_Byte(LPUART1, temp);
        }
    }
}

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

7.png

8.2  在上述基本LPUART配置的基础上增加中断配置代码,实现唤醒低功耗模式中的MCU

a.开启SYSCFG、PWR时钟:

    RCC_APB2PeriphClockCmd(RCC_APB2ENR_SYSCFG, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);

b.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);

c.配置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);

d.清除接收标志并打开接收中断:

    LPUART_ClearITPendingBit(LPUART1, LPUART_LPUIF_RXIF);
LPUART_ITConfig(LPUART1, LPUART_LPUCON_RXIE, ENABLE);

e.定义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;
        }
    }
}

f.编写实验样例:

    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[i]);
    }
    DELAY_Ms(20);
    for(i = 0; i < strlen(string2); i++)
    {
        Output_Byte(LPUART1, string2[i]);
    }
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);//休眠
    for(i = 0; i < strlen(string3); i++)
    {
        Output_Byte(LPUART1, string3[i]);
    }

    while(1)
    {

    }
}

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

6.png

来源:灵动MM32MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 44

MM32L0130作为灵动微电子推出的一款低功耗芯片,内置多种省电工作模式保证低功耗应用的要求。前面章节分别对MM32L0130片上外设SLCD和RTC做了相关描述,并列举对应程序实现SLCD驱动LCD显示、RTC日历和闹钟,其实SLCD与RTC都支持在特定的低功耗模式下运行,结合这两个外设特性,在前面实验的基础上,使用EVB_L0136开发板可以轻松实现一个低功耗电子时钟设计。本次微课堂通过讲述MM32L0130 PWR电源控制模式,以及SLCD 和RTC外设配置,实现低功耗应用场景。

1、MM32L0130 PWR简介

电源控制 PWR(Power Controller)主要涉及芯片的供电系统、电源管理器和低功耗模式等功能。

1.1 供电系统

芯片由两种电源提供供电:

由VDDA和VSSA提供的模拟电源,为芯片模拟模块提供电压,用于ADC模块、内部基准电压、内部温度传感器和 PLL 等。

由VDD和VSS提供的数字电源,用于数字部分和I/O引脚工作。

1.png

电源控制功能框图

VDD 域主要给 LSE, HSE, PMU, POR, PVD 和部分 I/O 上的唤醒逻辑供电,在上电后保持工作状态。

备份域主要为 RTC、 LCD、 IWDG、备份寄存器和内部低速时钟振荡器 LSI 供电。

VDD_Core 域主要给芯片的内核、内存和外设提供供电,在上电后默认是开启状态,在进入低功耗待机模式时,芯片会硬件选择关闭该 VDD_Core 域,在唤醒后芯片会自动开启。主要有以下几种工作状态:

  • 运行模式

VDD_Core 域以正常的功耗模式运行,内存、外设都正常工作。

  • 低功耗运行模式

VDD_Core 域以低功耗模式运行,内存、外设都以低功耗工作。

  • 睡眠模式

VDD_Core 域以正常功耗模式工作, CPU 进入睡眠模式,内存、外设都以正常的功耗模式工作。

  • 低功耗睡眠模式

VDD_Core 域以低功耗睡眠模式工作, CPU 进入低功耗睡眠模式,内存、外设都以低功耗工作。

  • 停机模式

VDD_Core 域以低功耗模式工作,只保持寄存器和 RAM 的内容。

  • 深度停机模式

VDD_Core 域以更低功耗模式工作,只保持寄存器和 RAM 的内容。

  • 待机模式

VDD_Core 域停止供电。除了备份域外,其他所有寄存器和 SRAM 的内容全部丢失。

  • 关机模式

VDD_Core 域、备份域停止供电。

1.2 MM32L0130低功耗模式

MM32L0130有6种低功耗模式:包括低功耗运行模式,睡眠模式,低功耗睡眠模式,停机模式,待机模式,关机模式:

  • 低功耗运行模式

进一步降低 MCU 在运行模式下的功耗,可以通过配置 PWR_CR1 寄存器的 LPR 位将电压稳压器设置为低功耗模式。该模式下系统频率不应超过 2MHz。

  • Sleep Mode 睡眠模式

CPU 进入睡眠模式,内存、外设都以正常的功耗模式工作。在睡眠模式下,所有的 I/O 引脚都保持在运行模式时的状态。中断或事件发生后,睡眠模式立即被唤醒。

  • Low Power Sleep Mode 低功耗睡眠模式

CPU 进入低功耗睡眠模式,内存、外设都以低功耗工作。在睡眠模式下,所有的 I/O 引脚都保持在运行模式时的状态。中断或事件发生后,睡眠模式立即被唤醒。

  • Stop Mode 停机模式

停机模式下,CPU 进入深度睡眠模式, VDD_Core 域的所有时钟都被停止, PLL、 HSI 和 HSE 振荡器的功能被禁止, SRAM 和寄存器内容被保留下来。

  • DeepStop Mode 深度停机模式

深度停机是在 CPU 深度睡眠模式的基础上结合了外设的时钟控制和电压稳压器控制机制的一种低功耗模式。在深度停机模式下, VDD_Core 域的所有时钟都被停止, PLL、 HSI 和 HSE 振荡器的功能被禁止, SRAM 和寄存器内容被保留下来。

  • Standby Mode 待机模式

待机模式是在 CPU 深睡眠模式的基础上关闭电压稳压器。整个 VDD_Core 域被切断, PLL、 HSI 和HSE 振荡器也被关闭, SRAM 和寄存器内容丢失,只有备份域的寄存器和待机电路维持供电。唤醒后芯片将复位。

  • ShutDown Mode 关机模式

在关机模式下,内部所有的稳压器全都被关闭, BOR 关闭,只保留 POR 和少数其他 VDD 域的电路正常工作(PMU 部分逻辑/POR/IO Wakeup 逻辑)。

1.3 功耗模式选择

一般根据最低电源消耗,最快启动时间和可用的唤醒源等条件,选择一种最佳的低功耗模式。相关参数可以参考各系列对应的数据手册,如下数据从数据手册摘取。

1.31 电流消耗

电流消耗是多种参数和因素的综合指标,这些参数和因素包括工作电压、环境温度、 I/O引脚的负载、产品的软件配置、工作频率、 I/O 脚的翻转速率、程序在存储器中的位置以及执行的代码等。本节中给出的所有运行模式下的电流消耗测量值,都是在执行一套精简的代码。

睡眠模式下的典型电流消耗:

2.png

停机模式下的典型电流消耗和最大电流消耗:

3.png

I/O 状态为模拟输入。

待机模式下的典型电流消耗和最大电流消耗:

4.png

I/O 状态为模拟输入。

关机模式下的典型电流消耗和最大电流消耗:

5.png

I/O 状态为模拟输入。

1.32 唤醒时间

低功耗模式的唤醒时间:

6.png

2、实验

2.1 实验说明

MM32L0130的RTC和SLCD外设都支持睡眠模式、停机模式、和待机模式。RTC模块连接到EXTI部分用于低功耗唤醒信号,包括闹钟、唤醒单元、入侵事件。SLCD驱动模块在不需要显示的时候,可以完全关闭 SLCD 驱动以达到降低功耗的目的。

硬件使用灵动微电子设计的EVB-L0136开发板,板载LCD接口可以适配GDC0689液晶屏,以LCD中的6位数码管显示时间时、分、秒,在1s时间范围内完成唤醒并更新显示数据即可,根据需要可以选择停机模式和待机模式,待机模式功耗最低。在STOP模式下, VDD_Core域的所有时钟都被停止, PLL、 HSI 和 HSE 振荡器的功能被禁止,SRAM 和寄存器内容被保留下来,唤醒之后继续执行进入STOP模式指令之后的程序,可以保证各个任务顺利运行,从STOP模式唤醒时间约为20us,时间相当充分,且功耗较正常运行模式降低很多,这里选择STOP模式。

GDC0689液晶屏全显效果图如下:

7.png

2.2 唤醒单元

RTC内部包含周期性的唤醒单元,用于唤醒低功耗模式。

RTC 内部包含一个 16 位的递减计数单元,用于周期性产生唤醒标志,该唤醒定时器可扩展至 17 位。通过配置 RTC_CR 寄存器中的 WUTE 位使能。唤醒单元时钟源:

2、4、8 或 16 分频的 RTC 时钟:

当为 LSE 时,可配置的唤醒中断周期介于 122µs 和 32s 之间,且分辨率低至 61µs。

fck_spre(通常为 1Hz 内部时钟):

WUCKSEL[2:1]=10 时为 1s 到 18h;

WUCKSEL[2:1]=11 时约为 18h 到 36h。

当递减计数器计数到 0 时, RTC_ISR 寄存器的 WUTF 标志会置 1,唤醒计数器会重载 RTC_WUTR寄存器值,通过软件清零 WUTF 标志。

使能 RTC_CR 寄存器中的 WTIE,当计数到 0 时,会产生中断输出。

配置 RTC_CR 寄存器中的位 OSEL[1:0]等于 2, WUTF 连接到 RTC_ALARM 输出。配置 RTC_CR寄存器的 POL 位选择 RTC_ALARM 输出极性。

注:系统复位以及低功耗模式(睡眠、停机和待机)对唤醒定时器没有影响。

2.3 外设配置

关于SLCD和RTC的初始化配置在前面两节微课堂已有相关描述,以下外设配置与应用程序在前面代码上进行增添即可。

1)配置低功耗模式要先使能PWR时钟:

RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWREN, ENABLE);

2)在要进入STOP模式的代码后调用相关库函数,选择低功耗模式,中断唤醒:

PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);

3)RTC的时钟源选择LSE(32.768KHZ),可配置的唤醒中断周期介于 122µs 和 32s 之间,且分辨率低至 61µs。此处对RTC时钟进行16分频,1s计数2048个,配置唤醒定时器自动重装载值为256,对应125ms,该值越小,唤醒时间越短。

RTCCAL_WakeUpClockConfig(RTCCAL_WakeUpClock_RTCCLK_Div16);        
RTCCAL_SetWakeUpCounter(256);

使能唤醒单元,使能RTC唤醒中断:

RTCCAL_WakeUpCmd(ENABLE);
RTCCAL_ClearFlag(RTCCAL_FLAG_WUTF);
RTCCAL_ITConfig(RTCCAL_IT_WUT, ENABLE);

RTC&BKP 全局中断与连接到 EXTI17,配置RTC中断:

RTCCAL_NVIC_Config();

4)SLCD显示,记录当前日历和时间,使用LCD的6位数码管显示时分秒,左上方的4位数码管显示年份。

    void LCD_DisplayDataUpdate(void)
{
    Number1 = RTCCAL_tempTime.RTCCAL_Seconds; 
    Number2 = RTCCAL_tempTime.RTCCAL_Minutes; 
    Number3 = RTCCAL_tempTime.RTCCAL_Hours;   

    LCD_DisplayNumber1(0, '0' + Number3 / 10, 0);
    LCD_DisplayNumber1(1, '0' + Number3 % 10, 0);
    LCD_DisplayNumber1(2, '0' + Number2 / 10, 0);
    LCD_DisplayNumber1(3, '0' + Number2 % 10, 0);
    LCD_DisplayNumber1(4, '0' + Number1 / 10, 0); 
    LCD_DisplayNumber1(5, '0' + Number1 % 10, 0); 

    LCD_DisplayUnit(8, 1);
    LCD_DisplayUnit(9, 1);

    Number4 = RTCCAL_tempDate.RTCCAL_Year;
    LCD_DisplayNumber2(0, '2', 0);
    LCD_DisplayNumber2(1, '0', 0);
    LCD_DisplayNumber2(2, '0' + Number4 / 10, 0);
    LCD_DisplayNumber2(3, '0' + Number4 % 10, 0);

}

5)获取当前日历和时间,刷新显示数据,Flag_GainData、Flag_DataUpdate均为时间标志,这里间隔1ms获取数据,间隔10ms刷新数据,Flag_WKUP是中断唤醒标志,数据刷新之后再次进入STOP模式,等待唤醒,刷新时间是影响功耗的主要参数之一,需根据实际应用进行评估。

    if(Flag_GainData == 1)  
{
        Flag_GainData = 0;
        RTCCAL_GetDate(RTCCAL_Format_BIN, &RTCCAL_tempDate);                                RTCCAL_GetTime(RTCCAL_Format_BIN, &RTCCAL_tempTime);
}
if(Flag_DataUpdate == 1) 
{
        Flag_DataUpdate = 0;
        LCD_DisplayDataUpdate();  
        if(Flag_WKUP == 1)
        {
            Flag_WKUP = 0;  
            SystemInit(); 
            PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);   
            LED2_TOGGLE();
        }       
}

2.4 演示


板载LD2(绿色LED)闪烁,程序中LD2的控制引脚在从低功耗模式唤醒之后翻转,闪烁表示此时处于低功耗模式进入、唤醒状态。LCD液晶屏显示时、分、秒、年份。

本次微课堂在功能设计上仅是MM32L0130 SLCD与RTC在低功耗模式下的简单应用,如果对此感兴趣者,可以自己配置RTC闹钟功能、SLCD闪烁模式,以及按键调整时间、蜂鸣提醒、LED显示等进一步完善相关功能。

来源:灵动MM32MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 49

1、MM32L0130 RTC简介

RTC 模块是用于提供时间(时、分、秒、亚秒)和日期(年、月、日)功能的定时计数器,日历以 BCD码的格式显示。内部包含周期性的唤醒单元,用于唤醒低功耗模式。支持夏令时补偿,支持数字校准补偿晶振精度的偏差。灵动微电子推出的MM32L0130系列MCU片上RTC外设具有以下特征:

  • 可编程的日历功能,包括时、分、秒、小时(12/24 小时制)、日期、星期、月份、年份

  • 软件可编程的夏令时补偿

  • 可编程闹钟,任意日历字段的组合触发闹钟

  • 周期性自动唤醒单元,唤醒时间可配置

  • 数字校准,精度为 0.95ppm

  • 通过移位功能调整亚秒时间

  • 支持可配置的时间戳功能,用于记录事件的入侵时间

  • 支持可配置的入侵检测

  • 5 个 32 位宽的备份数据寄存器,当发生入侵事件时会复位备份数据寄存器

  • 可屏蔽中断源

•  闹钟

•  唤醒单元

•  时间戳事件

•  入侵事件

2、RTC功能描述

2.1 RTC模块系统框图

1.png

RTC中断请求:

2.png

注:

当使用了 PC13 的时间戳或入侵的功能时,如果需要使用 PC13 用做复用功能或者输出时,需要关闭时间戳或入侵对应的寄存器的使能位释放 PC13。

RTC_ALARM 为闹钟或唤醒标志输出, RTC_CALB 代表校准时钟输出,最终会输出到 PAD,具体的复用关系参考芯片数据手册与 RTC_OR 输出控制寄存器。

TAMP_IN 代表外部入侵管脚, TIM_TS 代表时间戳管脚,具体的对应关系参考芯片数据手册部分。

2.2 时钟和预分频

RTC 时钟包含3个独立可配置的时钟源:分别是 LSE、 LSI、 HSE 时钟的 128 分频。RTC 内部包含2个预分频器用于提供日历或其它功能的时钟,分别是一个 7 位的异步预分频器与15位的同步预分频器,为了降低功耗,建议将异步预分频的值设置到可能的最大值。

异步分频器输出时钟为fck_apre;同步预分频器输出时钟为fck_spre。

计算公式如下:

3.png

fck_apre时钟用于为二进制格式的 RTC_SSR 亚秒递减计数器提供时钟。当该递减计数器计数到 0 时,会使用 PREDIV_S 的内容重载 RTC_SSR, fck_spre用于为日历计数单元提供时钟。

注:

针对 32.768KHZ 的 LSE 时钟,异步分频部分默认设置为 128,同步分频部分设置为 256,产生1HZ(fck_spre)的时钟用于日历计数。

2.3 实时时钟和日历

RTC 时间和日期寄存器对应如下:

RTC_SSR 对应于亚秒

RTC_TR 对应于时间

RTC_DR 对应于日期

通过 APB 总线访问日历时间与日期寄存器时,由 RTC_CR 寄存器中的 BYPSHAD 位决定访问实时的日历寄存器还是影子寄存器,默认情况下访问的是影子寄存器。

每隔 2 个 RTC 时钟周期,会将实时的日历寄存器复制到影子寄存器,并将 RTC_ISR 寄存器的 RSF位置 1,在停机和待机模式下不会执行复制操作。退出这两种模式时,影子寄存器会在最长 2 个 RTC 时钟周期后进行更新。影子寄存器可以通过系统复位复位。

2.4 可编程闹钟

RTC 闹钟单元被划分为多个位 ,并且每个位支持独立的使能或屏蔽。具体可以通过配置RTC_ALRMAR 寄存器 MSKx 位以及 RTC_ALRMASSR 寄存器的 MASKSSx 位。

配置 RTC_CR 寄存器中的 ALRAE 位使能可编程闹钟功能。当该位为 1,并且配置的 RTC_ALRMAR寄存器的值同当前日历一致时, RTC_ISR 寄存器中的 ALRAF 位会置 1。同时配置 RTC_CR 寄存器中的ALRAIE 位等于 1 时,会产生闹钟中断输出。

配置 RTC_CR 寄存器中的位 OSEL[1:0]等于 1, ALRAF 连接到 RTC_ALARM 输出,配置 RTC_CR寄存器的 POL 位选择 RTC_ALARM 输出极性。

MM32L0130的RTC外设还有周期唤醒单元、日历读取、复位RTC、RTC数字校准、RTC移位、时间戳、入侵检测、RTC低功耗唤醒等功能, 在用户手册RTC章节有进行详细描述,大家可以参考查阅,此处不再进行赘述,实验涉及到再进行说明。

3、实验

3.1 实验原理

RTC 闹钟单元被划分为多个位,包括日期、星期、小时、分钟、秒,并且每个位支持独立的使能或屏蔽。当配置的闹钟A寄存器的值与当前日历(时间/日期)寄存器的值一致时,闹钟发生,相应标志置位。如果使能了闹钟中断,则会产生闹钟中断输出。

配置时间寄存器、日期寄存器的值来初始化日历,配置闹钟A寄存器的值,并使能闹钟中断,每次闹钟A寄存器的值与当前时间/日期寄存器的值一致时,闹钟发生,产生闹钟中断。读取日历,如果查询到闹钟发生,串口打印闹钟发生次数与当前日历数据。

在日历的基础上实现闹钟功能,为便于观察和验证,实验中配置闹钟发生的时间尽可能短,匹配到秒而将其余位屏蔽以使闹钟发生。

3.2 程序设计

3.21 RTCCAL_Initialize() 函数

函数实现日历初始化配置,按如下步骤初始化日历时间与日期寄存器:

1)配置 RTC_ISR 寄存器中的 INIT 位为 1 以进入初始化模式

2)等待 RTC_ISR 寄存器中的 INITF 位被硬件置 1

3)编程 RTC_PRER 寄存器,配置同步与异步预分频系数

4)配置影子寄存器(RTC_TR 和 RTC_DR),加载日历初值,配置 RTC_CR 寄存器中的 FMT 位选择 12 或 24 小时制

5)清除 RTC_ISR 寄存器中的 INIT 位退出初始化模式

注:

约 4 个 RTC 时钟周期后,影子寄存器配置值加载到内部实时计数器。初始化影子寄存器后,等待 RTC_ISR 寄存器的 RSF 位置 1,才能读取日历。

    void RTCCAL_Initialize(void)
{
    //Check if the clock is configured for the first time
    RTCCAL_InitTypeDef init_struct;
    RTCCAL_TimeTypeDef setTimeStruct;
    RTCCAL_DateTypeDef setDateStruct;
    u16 temp = 0;

    RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE); //(1)
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);  //(2)
    PWR_BackupAccessCmd(ENABLE);  //(3)
    RCC_LSEConfig(RCC_LSE_ON);
    delay_x_cycle(2000);
    //Check whether the specified RCC marker is set or not, and wait for the
    //low-speed crystal oscillator to be ready
    while(1) {     
        if(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != RESET) { //(4)
            break;
        }
        temp++;
        if(temp >= LSE_READY_TIMEOUT) {
            while(1) {
                __NOP();
            }
        }
        delay_x_cycle(10);
    }
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_RTC, ENABLE); 
    //Setting RTC Clock
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); 
    RCC_RTCCLKCmd(ENABLE);        
    RTCCAL_EnterInitMode();   //(5)
    RTCCAL_WaitForSynchro(); 

    RTCCAL_StructInit(&init_struct);
    init_struct.RTCCAL_AsynchPrediv = 0x7F;   //(6)
    init_struct.RTCCAL_SynchPrediv  = 0xFF;
    init_struct.RTCCAL_HourFormat   = RTCCAL_HourFormat_24;
    RTCCAL_Init(&init_struct); 

    RTCCAL_TimeStructInit(&setTimeStruct);
    setTimeStruct.RTCCAL_H12 = RTCCAL_H12_AM;   //(7)
    setTimeStruct.RTCCAL_Hours   = 15;
    setTimeStruct.RTCCAL_Minutes = 34;
    setTimeStruct.RTCCAL_Seconds = 0;  
    RTCCAL_SetTime(RTCCAL_Format_BCD, &setTimeStruct);

    RTCCAL_DateStructInit(&setDateStruct);
    setDateStruct.RTCCAL_Year = 0x16;     //(8)
    setDateStruct.RTCCAL_Month = 0x0A;
    setDateStruct.RTCCAL_Date = 0x1A;
    setDateStruct.RTCCAL_WeekDay = 0x01;
    RTCCAL_SetDate(RTCCAL_Format_BCD, &setDateStruct);

    RTCCAL_WaitForSynchro(); 
    RTCCAL_ExitInitMode();  //(9)
}


(1)、(2)配置 RTC 需要使能 PWR 和 BKP 的时钟

(3)RTC 寄存器写保护,取消备份域的写保护

(4)等待 LSE 时钟稳定,选择 LSE 作为 RTC 时钟源

(5)确认 RTC 进入初始化模式

(6)配置 RTC 预分频寄存器,时钟频率为 1HZ

(7)配置 PTC_TR时间寄存器,更新时间

(8)配置 PTC_DR日期寄存器,更新日期

(9)RTC 退出初始化模式


3.22 RTCCAL_AlarmConfig() 函数

函数实现闹钟初始化配置,按如下步骤编程闹钟:

1)配置 RTC_CR 中的 ALRAE 位等于 0 禁止闹钟 A

2)等待 RTC_ISR 寄存器中的 ALRAWF 位等于 1

3)设置闹钟寄存器(RTC_ALRMASSR/RTC_ALRMAR)

4)配置 RTC_CR 寄存器中的 ALRAE 位等于 1 使能闹钟 A

注:

对 RTC_CR 寄存器执行的写操作。约 2 个 RTC 时钟周期同步后生效。

  
    void RTCCAL_AlarmConfig(void)
{
RTCCAL_AlarmTypeDef RTCCAL_AlarmStructure;
RTCCAL_NVIC_Config();  //(1)
    // Set the alarm A Masks
    RTCCAL_AlarmStructure.RTCCAL_AlarmMask = (RTCCAL_ALRMAR_MSK4 | RTCCAL_ALRMAR_MSK3 | RTCCAL_ALRMAR_MSK2);   //(2)
    RTCCAL_AlarmStructure.RTCCAL_AlarmDateWeekDaySel = RTCCAL_AlarmDateWeekDaySel_Date; 
    RTCCAL_AlarmStructure.RTCCAL_AlarmDateWeekDay = RTCCAL_Weekday_Monday;
    RTCCAL_AlarmStructure.RTCCAL_AlarmTime.RTCCAL_Hours     = 0;
    RTCCAL_AlarmStructure.RTCCAL_AlarmTime.RTCCAL_Minutes   = 0;
    RTCCAL_AlarmStructure.RTCCAL_AlarmTime.RTCCAL_Seconds   = 9;
    if(ERROR == RTCCAL_AlarmCmd(RTCCAL_Alarm_A, DISABLE)) {
        while(1) {};
}
    RTCCAL_SetAlarm(RTCCAL_Format_BCD,RTCCAL_Alarm_A, &RTCCAL_AlarmStructure);

    RTCCAL_AlarmSubSecondConfig(RTCCAL_Alarm_A, 0xFF, RTCCAL_AlarmSubSecondMask_SS14_5);  //(3)
    // Enable alarm A interrupt
    RTCCAL_ITConfig(RTCCAL_IT_ALRA, ENABLE);   //(4)
    if(ERROR == RTCCAL_AlarmCmd(RTCCAL_Alarm_A, ENABLE)) {   
        while(1) {};
    }
}


(1)配置RTC闹钟中断,RTC&BKP全局中断连接到 EXTI17

(2)配置闹钟A寄存器,屏蔽日期/星期、时、分,仅匹配秒

(3)配置闹钟A亚秒寄存器

(4)使能闹钟A中断

3.23 RTC_BKP_IRQHandler() 函数

RTC闹钟中断服务子程序,记录闹钟中断次数,置位标志位。

    void RTC_BKP_IRQHandler(void )  
{
    if(RTCCAL_GetITStatus(RTCCAL_IT_ALRA) != RESET) {
        RTCCAL_ClearITPendingBit(RTCCAL_IT_ALRA);
        Flag_ALARM = 1;    
        if(AlarmCount > 500) {  
            RCC_RTCCLKCmd(DISABLE);  
            AlarmCount = 0;
        }
        else {
            AlarmCount++;
        }
        EXTI_ClearITPendingBit(EXTI_Line17);
    }
}

3.24 main() 函数

函数实现各模块初始化,在循环中获取当前日期、时间,查询到闹钟发生,打印当前日期、时间。

    s32 main(void)
{
    RTCCAL_DateTypeDef  RTCCAL_tempDate;
    RTCCAL_TimeTypeDef  RTCCAL_tempTime;
    DELAY_Init();
    CONSOLE_Init(115200);
    RTCCAL_LSE_DemoInit();
    while(1) {
        if(Flag_ALARM == 1) {
            Flag_ALARM = 0;
            printf("Alarm clock was triggered %d times !\n", AlarmCount);
            printf("20");
            printf("%02d-",RTCCAL_tempDate.RTCCAL_Year);
            printf("%02d-",RTCCAL_tempDate.RTCCAL_Month);
            printf("%02d\t",RTCCAL_tempDate.RTCCAL_Date);
            printf("%02d:",RTCCAL_tempTime.RTCCAL_Hours);
            printf("%02d:",RTCCAL_tempTime.RTCCAL_Minutes);
            printf("%02d\n",RTCCAL_tempTime.RTCCAL_Seconds);
            printf("\n");
            }
    }
}

3.3 实验演示

下载程序运行,观察串口调试助手:

4.png

串口调试助手间隔打印数据,比较前后两次数据的日期和时间,相差1分钟,在每分钟的第9秒闹钟发生,和闹钟寄存器配置一致,运行情况和预期设计相符。

来源:灵动MM32MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 72

灵动股份推出的MM32L0130系列MCU具有片上SLCD液晶显示控制器,SLCD 驱动器是用于单色无源液晶显示器(SLCD)的数字驱动器,具有多达 8 个公共端和多达 63 个分段端, SLCD 引脚最多为 64 个,因此最多可驱动 240(60x4)或 448(56x8)个段码。驱动段码的最终数量由产品规格书中设备引脚的数目决定。

1、SLCD介绍

1.1  SLCD功能框图

SLCD 驱动模块包括以下几个基本的子模块,如下图所示。

  • 显示数据寄存器

  • SLCD 输出驱动引脚

  • 时钟产生单元,包括时钟预分频器、帧时钟分频器、电荷泵时钟分频器和闪烁时钟分频器

  • 闪烁控制器

  • 内置升压电荷泵和偏置电压生成单元

  • 时序控制和波形发生器

1.png

1.2  SLCD主要特征

  • 显示帧率灵活控制

  • 兼容 APB 接口

  • 支持静态、 1/2、 1/3、 1/4、 1/6 和 1/8 占空比

  • 支持 1/2、 1/3 和 1/4 偏置电压设置

  • 为了存储显示数据,内置了 16*32bit 显示数据寄存器

  • 通过软件来调整 SLCD 输出电压,来调节对比度

  • 外围电路简单,不需要模拟器件支持

1)内嵌电容升压器来得到比电源电压更高而且不受其影响的 SLCD 驱动电压。升压器产生的 SLCD驱动电压范围可调,可以匹配支持 3V 或者 5V 的 LCD 屏幕

2)SLCD 驱动电源可以通过软件来选择内部电源或外部电源。

3)可以选择使用内嵌电容分压器对 SLCD 驱动电压进行分压,得到驱动电压的中间值(VLCDrail1,VLCDrail2, VLCDrail3, VLCDrail4)

  • 两种调整显示对比度的方法

1)当采用内部升压器来提供 VLCD 电源时,可以通过软件调节 VLCD 输出电压

2)其它情况下可以在每帧显示之间插入死区时间

  • 支持以下低功耗模式:低功耗运行模式,睡眠模式,低功耗睡眠模式,停止模式,深度停止模式,待机模式;在不需要显示的时候,可以完全关闭 SLCD 驱动以达到降低功耗的目的

  • 支持相位反转模式,降低功耗和 EMI

  • 每一帧显示开始的时候,通过中断信号与软件同步,更新显示数据

  • 闪烁功能

1)可以从所有段码中任意选择 1 到 8 个段码闪烁显示,也可以闪烁显示全部段码

2)在静态、 1/2、 1/3、 1/4 占空比模式下可以闪烁显示任意段码

3)软件选择闪烁频率,支持闪烁频率 0.5Hz, 1Hz, 2Hz 或 4Hz

  • 灵活的引脚复用功能,可以配置任意 LCD 驱动引脚成为 COM 或者 SEG 功能;SLCD 的驱动引脚在没有被配置成 SLCD 功能的时候,可以作为 GPIO 引脚来使用

  • SLCD 驱动电平(VLCDrail1, VLCDrail2, VLCDrail3, VLCDrail4)的去耦合功能

  • 支持低功耗驱动波形

  • 支持 DMA 传输

  • 支持中断

2、功能概述

2.1  显示数据寄存器

为了存储显示数据, SLCD 驱动模块内置了 16 个 32 比特显示数据寄存器。显示数据寄存器中的比特位与 LCD 显示屏上的段码一一对应, 如果要点亮 LCD 显示屏上的某个段码, 则需要把显示数据寄存器中的相对应的比特写为‘1’;反之如果要熄灭某个段码, 则需要把对应的比特写为‘0’, 如下图所示。

2.png

在 static, 1/2, 1/3 和1/4 duty模式下,显示数据寄存器被划分为主显示数据寄存器片区(SLCD_DR[7:0])和辅助显示数据寄存器片区( SLCD_DR[15:8]);在 1/6 和 1/8 duty 模式下,显示数据寄存器(SLCD_DR[15:0])全部作为主显示数据寄存器片区使用,没有辅助显示数据寄存器片区的分划。显示数据寄存器的具体结构和详细的片区划分情况见下图:

3.png

2.2  主/辅助显示数据寄存器

在 static,1/2,1/3和1/4 duty 模式下,可以通过 SLCD 帧控制寄存器(SLCD_FCR)中的DRSEL比特选择控制将主显示数据寄存器片区(SLCD_DR[7:0])或者辅助显示数据寄存器片区(SLCD_DR[15:8])的数据显示到 LCD 屏幕上,如果DRSEL为‘0’, 显示主显示数据寄存器片区的数据;如果 DRSEL 为‘1’,显示辅助显示数据寄存器片区的数据。SLCD 状态寄存器(SLCD_SR)中的 DRSS 比特可以指示出显示数据当前使用的显示数据寄存器片区, 如果当前使用的是主显示数据寄存器片区的数据, 则 DRSS 比特为‘0’;如果当前使用的是辅助显示数据寄存器片区的数据,则 DRSS 比特为‘1’。将 SLCD 帧控制寄存器(SLCD_FCR)中的 DRLC 比特置‘1’可以清除主显示数据寄存器片区的数据;将 DRHC 比特置‘1’可以清除辅助显示数据寄存器片区的数据。

2.3  COM 和 SEG 引脚配置

SLCD 模块提供公共端(COM)引脚和段(SEG)引脚的驱动。

2.4  SLCD 引脚配置

SLCD 的 SEG 和 COM 引脚是同通用功能 I/O 复用的。在不作为 SLCD 引脚使用时,这些引脚可以配置成通用功能 I/O 引脚。具体配置请参考通用功能 I/O 章节。

2.5  COM 和 SEG 引脚重映射

当作为 SLCD 引脚使用时,每一个 SLCD 引脚都可以被重映射为 COM 或者 SEG 引脚,以简化电路板上的布局布线。SLCD 模块支持从 L0 到 L63 最多 64 个 SLCD 引脚(SLCD 引脚的最终数量由产品规格书中设备引脚的数目决定),每一个引脚可以通过相应的 SLCD_CFGR0 和 SLCD_CFGR1 寄存器来配置,重映射其作为 COM 或者 SEG 功能。

2.6  时钟产生

时钟产生模块为波形发生模块和电荷泵模块提供各自所需的时钟,其结构如下:

4.png

时钟产生模块结构图

3、实验

3.1  硬件设计

本次实验使用MM32L0130片上SLCD驱动LCD液晶屏显示。硬件使用灵动股份设计的EVB-L0136开发板,板载LCD接口可以适配GDC0689液晶屏,GDC0689具有半透和反射两种模式,6位8字、6点视角、宽温,适用于工业设备等产品。GDC0689液晶屏全显效果图如下:

5.png

EVB-L0136开发板LCD模块原理图如下:

6.png

原理图1(LCD部分)

7.png

原理图2(MM32F0130部分)

3.2  程序设计

例程主要用到GDC0689液晶屏的数码管部分进行计数显示,以最右边的数码管作为小数部分,其余数码管作为整数部分,从最低位开始累加计数,满十就向前一位进1。

灵动股份设计了MM32F0130 SLCD相关的库函数以及API函数,容易理解和使用,代码较多,这里不再进行赘述,仅对部分主要程序进行分析。

3.21 SLCD测试函数

    void slcd_test(void)
{
    slcd_init();
    while(1) {
        LCD_DisplayDataUpdate();
        DELAY_Ms(100);
    }
}

3.22 SLCD初始化函数

void slcd_init()函数主要代码:

使能PWR、BKP时钟

        RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);

使能SLCD时钟,软件复位SLCD

        RCC_SLCD_ClockCmd(SLCD, ENABLE);
    SLCD_DeInit();

SLCD的时钟源选择LSI,配置LSI时钟频率为40KHZ。

        RCC_LSICLKConfig(RCC_LSICLKSource_40KHz); 
    RCC_LSICmd(ENABLE);
    RCC_SLCDCLKConfig(RCC_SLCDCLKSource_LSI);

LSI作为SLCD时钟源,对应时钟预分频系数为4,分频系数为16

        else if(slcd_clk_source_freq <= LSI_VALUE) {
        pre_value = SLCD_Prescaler_4;
        div_value = SLCD_Divider_16;
    }

初始化SLCD结构体,配置1/4偏置、1/3占空比,VDD作为SLCD电源使能

        slcd_struct.SLCD_Divider = div_value;
    slcd_struct.SLCD_Duty = SLCD_Duty_1_4;
    slcd_struct.SLCD_Bias = SLCD_Bias_1_3;
    slcd_struct.SLCD_VoltageSource = SLCD_VoltSrcCapCharggDownVdd;
    SLCD_Init(&slcd_struct);

SLCD pin对应的GPIO配置为SEG或COM,并使能

        SLCD_IO_Config(&(SEGorCOM[0]));
    //must call after SLCD_init

配合SLCD COM索引寄存器

        SLCD_COM_IndexInit(&(SCLD_COM_Index[0]));

配置电荷泵时钟分频为1024

        SLCD_ChargePumpClockDivConfig(SLCD_ChargePumpClock_Div1024);

正常驱动波形

        SLCD_LowPowerDriveCmd(DISABLE);

配置无死区插入,当在两帧之间插入死区时,SEG和COM信号电压为零

        SLCD_DeadTimeConfig(SLCD_DeadTime_0);

清除显示数据寄存器

        LCD_Clear();

关闭SLCD闪烁模式,闪烁时钟分频系数为512

        SLCD_BlinkConfig(SLCD_BlinkMode_Off, SLCD_BlinkFrequency_Div512);

配置SLCD闪烁索引

        SLCD_BLINK_IndexInit(SCLD_BLINK_Index);

3.23 LCD更新显示数据函数

LCD_DisplayDataUpdate()函数主要代码:

        Number1 = (Number1 + 1) % 1000000;

    if(Number1 < 10) {
        LCD_DisplayNumber1(0, ' ', 0);
        LCD_DisplayNumber1(1, ' ', 0);
        LCD_DisplayNumber1(2, ' ', 0);
        LCD_DisplayNumber1(3, ' ', 0);
        LCD_DisplayNumber1(4, '0', 1);
        LCD_DisplayNumber1(5, '0' + Number1, 0);
    }
    else if(Number1 < 100) {
        LCD_DisplayNumber1(0, ' ', 0);
        LCD_DisplayNumber1(1, ' ', 0);
        LCD_DisplayNumber1(2, ' ', 0);
        LCD_DisplayNumber1(3, ' ', 0);
        LCD_DisplayNumber1(4, '0' + ((Number1 / 10) % 10), 1);
        LCD_DisplayNumber1(5, '0' + ((Number1 / 1 ) % 10), 0);
    }
    ......(省略余下代码)

其中LCD显示函数 void LCD_DisplayNumber1(u8 Index, char ch, u8 Point)用于配置数码管显示,函数的3个形参含义如下:

  • Index表示选中的数码管索引,对应6个数码管,可选值为0,1,2,3,4,5

  • ch表示要显示的数字,为char类型

  • Point表示该数码管是否显示Dp字段,显示则为1,否则为0

举例:代码中LCD_DisplayNumber1(5, '0' + Number1, 0)表示选中第5个数码管(最右),显示内容是Number的值,不显示Dp字段。

3.24 LCD显示函数

LCD_DisplayNumber1()函数主要代码:

    void LCD_DisplayNumber1(u8 Index, char ch, u8 Point)
{
    u8 i;
    char TAB[6][8][4] =  {   // (1)
        {"5A ", "5B ", "5C ", "5D ", "5E ", "5F ", "5G ", "DP5"},
        {"6A ", "6B ", "6C ", "6D ", "6E ", "6F ", "6G ", "DP6"},
        {"7A ", "7B ", "7C ", "7D ", "7E ", "7F ", "7G ", "DP7"},
        {"8A ", "8B ", "8C ", "8D ", "8E ", "8F ", "8G ", "DP8"},
        {"9A ", "9B ", "9C ", "9D ", "9E ", "9F ", "9G ", "DP9"},
        {"10A", "10B", "10C", "10D", "10E", "10F", "10G", "   "},
    };

    u8 COMn = 0xFF, SEGn = 0xFF;

    u8 Code = LCD_SearchCode(ch);   // (2)

    if(Code != 0xFF) {
        for(i = 0; i < 7; i++) {
            LCD_SearchName(TAB[Index][i], &COMn, &SEGn);   // (3)

            if((COMn != 0xFF) && (SEGn != 0xFF)) {
                LCD_WriteBit(COMn, LCD_SEG_Table[SEGn][0], LCD_SEG_Table[SEGn][1], (Code >> i) & 0x01);   // (4)
            }
        }

        LCD_SearchName(TAB[Index][7], &COMn, &SEGn); // (5)

        if((COMn != 0xFF) && (SEGn != 0xFF)) {
            LCD_WriteBit(COMn, LCD_SEG_Table[SEGn][0], LCD_SEG_Table[SEGn][1], Point);   // (6)
        }
    }
}

1、定义三维字符数组TAB[6][8][4],其中[6]对应6位“8”字,[8]对应“8”字的8段(含DP段),[4]表示元素的长度,对应各段的名称。

2、形参ch表示要显示的数字,为char类型,LCD_SearchCode(char ch)函数用来遍历LCD_CODE_Table[38],如果传入的参数ch和LCD_CODE_Table[i].ch相等,则返回LCD_CODE_Table[i].Data,即该数字对应的段选信号。

3、LCD_SearchName(TAB[Index][i], &COMn, &SEGn)函数遍历所有COM口(4)和SEG口(22),如果TAB[Index][i]和LCD_NAME_Table[i][j]相等,则获取COMn和SEGn的值,然后返回。

4、获取COMn对应的显示数据寄存器索引,根据段选信号,给显示数据寄存器赋值。

5、获取Dp段对应的COMn和SEGn的值,然后返回。

6、获取COMn对应的显示数据寄存器索引,根据Dp段选信号,给显示数据寄存器赋值。

3.3  实验演示

下载程序运行,观察GDC0689液晶屏显示:

来源:灵动MM32MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 190

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易于实现等显著优点,被诸多电子设备包括消费电子、家用电器、安防器材等广泛采用,如智能手环、机顶盒、3D眼镜、智能扫地机、空调、电扇、通道闸、红外栅栏等,近年来也越来越多的应用到计算机和手机系统中。

灵动股份推出的MM32L0130系列MCU具有片上IRM红外调制器,该模块使用片上的定时器和串口,实现数据的 FSK/ASK 调制,以满足红外发码的需求。

1、IRM介绍

1.1 IRM功能框图

“使用MM32L0130

1.2 IRM主要特征

● 支持 APB 接口

● 两个调制信号源,分别为通道 1 和通道 2

● 通道 1 和通道 2 调制信号源均可选,来源包含

1)恒 0

2)恒 1

3)TIM3 的 OC1 通道

4)TIM4 的 OC1 通道

5)TIM16 的 OC1 通道

6)TIM17 的 OC1 通道

● 基带信号源可选,来源包含

1)IRM 数据寄存器

2)UART1_TX

3)UART2_TX

4)LPUART_TX

● 可实现数据的 ASK、FSK 调制,调制方式可选

● 输出信号极性可选

2、功能概述

2.1 波形产生单元

调制信号选择功能:两个通道, channel_1 和 channel_2,通过寄存器配置可选择通道输入为恒 0、恒1、 TIM3 的 OC1 通道、 TIM4 的 OC1 通道、 TIM16 的 OC1 通道、 TIM17 的 OC1 通道。

基带信号选择功能:被发送的红外信号对应源数据,可以通过寄存器配置选择源为 IRM_DR、 UART1_TX、UART2_TX、 LPUART1_TX。

调试方式:可选 FSK 或 ASK。

极性可选,输出可为正常或反相波形。

2.2 调制功能说明

2.21 FSK 调制

用不同的频率来表示不同的符号。本模块为二进制频移键控(2FSK)。信号可以看成是频载为 f1 和 f2的两个振幅键控信号的合成。该功能模式下,调制信号源为频率为 f1、 f2 的两个方波:被调制信号为 0,则对应输出 f1;被调制信号为 1 则对应输出 f2。
波形如下:

“FSK
FSK 调制波形

2.22 ASK 调制

用不同的幅度来表示不同的符号。本模块为 OOK(On-Off Keying)调制,是 ASK 调制的一个特例,把一个幅度取为 0,另一个幅度为非 0,就是 OOK。又名 2ASK(二进制振幅键控)。该功能模式下,通道 1 信号源应为恒 0,通道 2 信号源应该频率为 f2 的方波:被调制信号为 0,则对应输出 0;被调制信号为 1 则对应输出 f2。
波形如下:

“ASK
ASK 调制波形

3、实验

本次实验使用MM32L0130片上IRM驱动红外发射管实现红外发码。硬件使用灵动股份设计的EVB-L0136开发板,红外模块原理图如下:

“使用MM32L0130

原理图中PA9连接D1(红外发射管)、PA10连接D2(红外接收头),红外发射电路使用T1(N-MOS管)控制红外发射管的导通或截至,在导通的时候,红外发射管会发射出红外光,反之,不会发射出红外光。要使两者通信成功,收/发红外波长与载波频率需一致,在这里波长就是940nm,载波频率就是38KHz。当红外接收头接收到红外载波信号时,其OUT引脚输出低电平,反之,OUT引脚输出高电平。

3.1 实验1:实现数据FSK调制

程序中配置PA9作为IRM红外调制器的发送引脚,配置调制信号通道1选择TIM3_OC1,调制信号通道2选择TIM4_OC1,基带信号源选择UART1_TX信号,调制方式选择FSK调制,以实现红外发码。主要代码如下:

3.11 IRM配置

void IRM_FSK_Config(void)
{
    IRM_InitTypeDef IRM_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1ENR_IRM, ENABLE);
    IRM_FSK_Clock_Init(TIM3, TIM4);
    IRM_StructInit(&IRM_InitStruct);
    IRM_SetIRMData(0);
    IRM_InitStruct.IRM_Polarity = IRM_Polarity_Normal;
    IRM_InitStruct.IRM_Modulation = IRM_Modulation_FSK;
    IRM_InitStruct.IRM_DataSelectSource = IRM_DataSource_UART1_TX;
    IRM_InitStruct.IRM_Channel1ClockSource = IRM_Channel1ClockSource_TIM3OC1;
    IRM_InitStruct.IRM_Channel2ClockSource = IRM_Channel2ClockSource_TIM4OC1;

    IRM_Init(&IRM_InitStruct);
    UART1_NVIC_Init(600);

    IRM_StartCmd(ENABLE);
}

3.12 调制信号配置

配置TIM3输出PWM,频率为38KHZ(和载波频率一致),占空比为1/2

配置TIM4输出PWM,频率为3.8KHZ(一个非载波频率),占空比为1/2

void IRM_FSK_Clock_Init(TIM_TypeDef* chan1_tim, TIM_TypeDef* chan2_tim)
{
    u32 ui_tim_value;

    ui_tim_value = (u32)((RCC_GetSysClockFreq()) / IRM_FREQUENCE);

    TIM_Init(chan1_tim, (ui_tim_value) - 1, 0);
    TIM_Init(chan2_tim, (ui_tim_value) * 10 - 1, 0);

}

定义IRM_FREQUENCE为38000

#define IRM_FREQUENCE                   38000

3.13 配置UART1 RX中断

void UART1_NVIC_Init(u32 baudrate)
{
    UART_InitTypeDef UART_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    RCC_UART_ClockCmd(UART1, ENABLE);

    NVIC_InitStruct.NVIC_IRQChannel = UART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 3;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    UART_StructInit(&UART_InitStruct);
    UART_InitStruct.BaudRate = baudrate;
    UART_InitStruct.WordLength = UART_WordLength_8b;
    UART_InitStruct.StopBits = UART_StopBits_1;
    UART_InitStruct.Parity = UART_Parity_No;
    UART_InitStruct.HWFlowControl = UART_HWFlowControl_None;
    UART_InitStruct.Mode = UART_Mode_Rx | UART_Mode_Tx;

    UART_Init(UART1, &UART_InitStruct);
    UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE);
    UART_Cmd(UART1, ENABLE);

    UART1RX_GPIO_Init();
}

3.14 IRM收发测试

void IRM_Transmit_Test(void)
{

    u16 i, getcount;
    u8 irm_string[] = {0xFF, 0xFF, 0x55, 0xAA, 0xF0, 0x0F, 0x80, 0x01};
    u8 getbyte;
    IRM_Initialize();
    while(1) {
        getcount = 0;
        for(i = 0; i < sizeof(irm_string); i++) {
            Output_Byte(UART1, irm_string[i]);
            if(SUCCESS == UART1_CheckRxdByte(&getbyte, 10000)) {
                if(getbyte == irm_string[i]) {
                    getcount++;
                }
            }
            delay_x_cycle(1000);
        }
        if(getcount == sizeof(irm_string)) {
            __NOP();
        }
        else {
            __NOP();
        }
    }
}

定义数组irm_string[]存放需要IRM调制的数据,IRM对数据进行FSK调制后,通过IRM_TX引脚发送,控制MOS管驱动红外发射管以发射红外光,红外接收头对红外光进行解码后,由UART1_RX引脚接收,将收到的数据与数组irm_string[]中的数据进行比对,看收/发数据是否一致,并进行统计。

FSK模式下,调制信号源为频率为38K、3.8K的两个方波:被调制信号为0时,则对应输出38KHZ;被调制信号为1时,则对应输出3.8KHZ,逻辑分析仪获取一段数据如下:

“使用MM32L0130

通道4为IRM_TX发出的调制信号。

通道5是UART1_RX接收到的数据,符合红外接收头特性。

观察串口调试助手打印数据,和irm_string[]中的数据一致。

“使用MM32L0130

3.2 实验2:实现数据ASK调制

程序中配置PA9作为IRM红外调制器的发送引脚,配置调制信号通道1为恒1,调制信号通道2选择TIM4_OC1,基带信号源选择UART1_TX信号,调制方式选择ASK调制,以实现红外发码。

该实验与前面实验1相比,只是选择IRM的另一种调制模式,代码只需在实验1的基础上改动即可,主要代码如下:

3.21 IRM配置

void IRM_ASK_Config(void)
{
    IRM_InitTypeDef IRM_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1ENR_IRM, ENABLE);
    IRM_ASK_Clock_Init(TIM4);
    IRM_StructInit(&IRM_InitStruct);
    IRM_SetIRMData(0);
    IRM_InitStruct.IRM_Polarity = IRM_Polarity_Normal;
    IRM_InitStruct.IRM_Modulation = IRM_Modulation_ASK_PSK;
    IRM_InitStruct.IRM_DataSelectSource = IRM_DataSource_UART1_TX;
    IRM_InitStruct.IRM_Channel1ClockSource = IRM_Channel1ClockSource_KeepHigh;              
    IRM_InitStruct.IRM_Channel2ClockSource = IRM_Channel2ClockSource_TIM4OC1;

    IRM_Init(&IRM_InitStruct);
    UART1_NVIC_Init(600);

    IRM_StartCmd(ENABLE);
}

3.22 调制信号配置

配置TIM4输出PWM,频率为38KHZ(和载波频率一致),占空比为1/2

void IRM_FSK_Clock_Init(TIM_TypeDef* chan1_tim, TIM_TypeDef* chan2_tim)
{
    u32 ui_tim_value;
    ui_tim_value = (u32)((RCC_GetSysClockFreq()) / IRM_FREQUENCE);
    TIM_Init(chan1_tim, (ui_tim_value) - 1, 0);
}

定义IRM_FREQUENCE为38000

#define IRM_FREQUENCE                   38000 

其余代码同实验1,下载运行。

ASK模式下,被调制信号为1时,则对应输出38KHZ;被调制信号为0时,则对应输出0,截取逻辑分析仪的一段数据分析:

“使用MM32L0130

通道4为IRM_TX发出的调制信号。

通道5是UART1_RX接收到的数据,符合红外接收头特性。

观察串口调试助手打印数据,和irm_string[]中的数据一致。

“使用MM32L0130

实验简单演示了使用MM32L0130片上IRM模块实现红外发码,并判断收发数据的一致性。IRM模块使用片上的定时器和串口,实现数据的 FSK/ASK 调制,满足红外发码的需求。

来源:灵动MM32MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 59

2022年7月29日,上海灵动微电子股份有限公司(以下简称“灵动微电子)发布低功耗 MM32L0130 系列 MCU 产品。MM32L0130 搭载 Arm Cortex-M0+ 处理器,集成段码 LCD 驱动,功耗可低至 100nA,适用于多种低功耗应用场景。

“灵动微电子发布低功耗

L0130 系列特色

1、丰富的资源配置

● Arm® Cortex-M0+ 内核,工作频率可达 48MHz

● 高达 64KB Flash,8KB SRAM

● 3 个 UART接口(包含 1 个 LPUART 接口)、2 个 SPI 接口、2 个 I2S 接口、1 个 I2C 接口

● 多达 40x4 或 36x8 个段码 LCD 驱动器

● 1 个红外信号调制模块 IRM,支持 ASK、PSK 或 FSK 调制

● 5 通道 DMA

● 5 个 16 位定时器

● 硬件日历 RTC

● 1 个 12 位 SAR ADC,配置 15 个外部通道,转换速率可达 1MSPS

● 1 个低功耗比较器

● 工作电压为 1.8V - 5.5V

● 支持的温度范围为 -40℃ - 85 ℃

● 多种省电工作模式支持低功耗应用的需求

● 提供 LQFP64 和 LQFP48 封装

“灵动微电子发布低功耗

2、先进的 LCD 控制器

● 可支持在待机状态下使用,最低功耗仅 1.5uA

● 可驱动多达 40x4 或 36x8 个段码。帧率和对比度可调节,可选段码进行闪烁

● 可通过内部重映射矩阵,实现 COM 和 SEG 的任意映射,提供单层 PCB 搞定 LCD 布线的选项

● 内置电荷泵,可在 1.8~5.5V 下工作。在 MCU 电源电压下降时依然可保持液晶屏的清晰

● 多种占空比和偏压模式可供选择,适配各种屏幕

3、出色的低功耗表现

L0130产品出色的低功耗模式,可在低功耗、短启动时间和多种唤醒事件之间达到最佳平衡。以下列举主要的几种模式,供参考:

● 低功耗运行模式

CPU、所有芯片外设包括 CPU 外设如 NVIC、 SysTick 等运行。在1MHz主频时功耗仅有 270uA;最高可运行在 2MHz

● 睡眠模式

CPU 停止,所有芯片外设包括CPU的外设仍可运行。运行功耗在57uA/MHz,最高可运行在 48MHz

● 深度停机模式

CPU 及绝大部分外设时钟都停止,在保持寄存器和RAM的内容的同时提供 LPUART 收发数据、RTC 日历计时和 LCD 显示的能力。最低功耗可达 400nA

● 待机模式

除备份域外的所有内容丢失,可支持 RTC 日历计时和 LCD 显示。最低功耗可达 300nA

● 关机模式

仅 POR、 PMU 部分逻辑、NRST PIN和 IO 唤醒逻辑正常工作。最低功耗可达 100nA,可供一粒 CR2032 电池使用 200 年!

L0130选型指南与购买渠道

MM32L0130 现已开始送样,提供 LQFP64 和 QFP48 两种可选封装形式,全系列提供 -40~85℃ 产品型号。主流开发设计工具和编程器厂家也已实现对 MM32L0130 的支持。有关芯片购买事宜,请洽灵动的销售、官方代理商和方案设计公司。

同时推出的还有 EVB-L0130 开发板,该开发板搭载 MM32L0136C7P 芯片,板载段码 LCD 屏等外设模块,用于 MM32L0130 系列 MCU 的评估。

“灵动微电子发布低功耗

在软件支持方面,灵动全新推出的软件开发平台 MindSDK 也将在 8 月份支持 MM32L0130 系列,敬请期待。

更多详细信息,请访问灵动官网 www.mm32mcu.com

来源:灵动MM32MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 34
订阅 RSS - MM32L0130