打印
[方案相关]

【HC32L196PCTA测评】+RTC时钟LCD显示

[复制链接]
1383|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 hulai123456 于 2023-8-30 18:52 编辑

#申请原创# #技术资源#
【HC32L196PCTA测评】+RTC时钟LCD显示

RTC时钟介绍

HC32L96给我们提供了实时时钟/日历提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。时钟操作可通过 AM/PM 寄存器位,决定采用24或12小时格式。下图所示是其参考手册上所述基本特性和基本框图。具有最小周期为0.5S的周期中断,如果需要更短的中断周期可以使用LPTIM产生中断


我们要用到其RTC就先需要对其初始化:
void Rtc_InitConfig(void)
{
        stc_rtc_initstruct_t stcRtcInitcfg;
        DDL_ZERO_STRUCT(stcRtcInitcfg);
        Sysctrl_SetPeripheralGate(SysctrlPeripheralRtc, TRUE);//开启RTC外设时钟
        Sysctrl_ClkSourceEnable(SysctrlClkXTL, TRUE);//使能外部低速时钟XTL
        
        stcRtcInitcfg.rtcAmpm = RtcPm;//24小时制
        stcRtcInitcfg.rtcClksrc = RtcClkXtl;//外部时钟XTL
        stcRtcInitcfg.rtcPrdsel.rtcPrdsel  = RtcPrds;//定周期中断PRDS模式
        stcRtcInitcfg.rtcPrdsel.rtcPrds = Rtc1Min;//中断时间间隔,1分钟一次
        stcRtcInitcfg.rtcCompen = RtcCompenDisable;
        stcRtcInitcfg.rtcTime.u8Year = 0x23;
        stcRtcInitcfg.rtcTime.u8Month = 0x08;
        stcRtcInitcfg.rtcTime.u8Day = 0x07;
        stcRtcInitcfg.rtcTime.u8DayOfWeek = 0x05;
        stcRtcInitcfg.rtcTime.u8Hour = 0x01;
        stcRtcInitcfg.rtcTime.u8Minute = 0x09;
        stcRtcInitcfg.rtcTime.u8Second = 0x30;        
        Rtc_Init(&stcRtcInitcfg);
        Rtc_AlmIeCmd(TRUE);
        EnableNvic(RTC_IRQn, IrqLevel3, TRUE);  
        Rtc_Cmd(TRUE);
        delay1ms(10);//保险加个延时
        Sysctrl_SetFunc(SysctrlClkFuncRTCLpmEn, TRUE);//RTC进入低功耗模块
}

LCD简介
LCD控制器是一款适用于单色无源液晶显示器(LCD)的数字控制器/驱动器,最多具有8 个公用端子(COM)和 48 个区段端子(SEG),用以驱动208 (4x52)或384 (8x48)个LCD图像元素。端子的确切数量取决于数据手册中所述的器件引脚。

我在这里对其手册上的端子进行了整理,形成类似液晶屏的字库,以便于我们对其进行操作


同样,要使用其功能,则必须对其进行初始化

//LCD段码屏GPIO初始化
void LCD_GPIOInit(void)
{
        Gpio_SetAnalogMode(GpioPortA, GpioPin9);  //COM0
        Gpio_SetAnalogMode(GpioPortA, GpioPin10); //COM1
        Gpio_SetAnalogMode(GpioPortA, GpioPin11); //COM2
        Gpio_SetAnalogMode(GpioPortA, GpioPin12); //COM3   

        Gpio_SetAnalogMode(GpioPortA, GpioPin8);  //SEG0
        Gpio_SetAnalogMode(GpioPortC, GpioPin9);  //SEG1
        Gpio_SetAnalogMode(GpioPortC, GpioPin8);  //SEG2
        Gpio_SetAnalogMode(GpioPortC, GpioPin7);  //SEG3
        Gpio_SetAnalogMode(GpioPortC, GpioPin6);  //SEG4
        Gpio_SetAnalogMode(GpioPortB, GpioPin15); //SEG5
        Gpio_SetAnalogMode(GpioPortB, GpioPin14); //SEG6
        Gpio_SetAnalogMode(GpioPortB, GpioPin13); //SEG7
}

//LCD模块配置初始化
void Lcd_InitConfig(void)
{
//        stc_lcd_cfg_t LcdInitStruct;
        stc_lcd_segcom_t LcdSegCom;

        LcdSegCom.u32Seg0_31 = 0xffffff00;                              ///< 配置LCD_POEN0寄存器 开启SEG0~SEG7
        LcdSegCom.stc_seg32_51_com0_8_t.seg32_51_com0_8 = 0xfe1fffff;   ///< 初始化LCD_POEN1寄存器 全部关闭输出端口
        Lcd_SetSegCom(&LcdSegCom);                                      ///< LCD COMSEG端口配置

        M0P_LCD->CR0_f.BSEL = LcdInResLowPower;                        // 内部电阻分压模式,小功耗模式
        M0P_LCD->CR0_f.DUTY = LcdDuty4;                                                        // 1/4duty
        M0P_LCD->CR0_f.BIAS = LcdBias3;                                                        // 1/3 BIAS
        M0P_LCD->CR0_f.CPCLK = LcdClk2k;                                                // 电压泵时钟频率选择2kHz
        M0P_LCD->CR0_f.LCDCLK = LcdClk128hz;                                // LCD扫描频率选择128Hz
        M0P_LCD->CR0_f.CONTRAST = 0x0;                                                        // LCD对比度设置最大
        
        M0P_LCD->CR1_f.MODE = LcdMode0;                                                        // 选择模式0
        M0P_LCD->CR1_f.CLKSRC = LcdRCL;                                                        // LCD时钟选择RCL
        M0P_LCD->CR1_f.BLINKEN = 0;                                                                        // LCD闪屏配置禁止
//        M0P_LCD->CR1_f.BLINKCNT = 63;                                                        //
        M0P_LCD->CR0_f.EN = LcdEnable;                                                        // 使能LCD模块
}

//实例化配置
void Lcd_ConfigRead(void)
{
        
        Sysctrl_ClkSourceEnable(SysctrlClkRCL,TRUE);            ///< 使能RCL时钟
        Sysctrl_SetRCLTrim(SysctrlRclFreq32768);                ///< 配置内部低速时钟频率为32.768kHz

        Sysctrl_SetPeripheralGate(SysctrlPeripheralLcd,TRUE);   ///< 开启LCD时钟
        Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);  ///< 开启GPIO时钟
            
        LCD_GPIOInit();// GPIO配置
        Lcd_InitConfig();// 功能配置
}
而后,我们利用上图整理出来的字库,书写Display部分函数

//数字
uint16_t LCD_Char_Number[10]=
                                 {//*0*     *1*        *2*       *3*      *4*
                                         0x0F05,        0x0600,        0x0B06,        0x0F02,        0x0603,
                                        //*5*      *6*         *7*       *8*      *9*
                                         0x0D03,        0x0D07,        0x0700,        0x0F07,        0x0F03
                                 };

//点
uint16_t LCD_Char_Point=0x0008;
而有了这些显示函数后,我们对其段码屏的操作就简单了许多,因此,在RTC的时钟处理上如下:

// RTC时间显示
void Rtc_Time_Display(void)
{
        uint8_t Minute=0, Second=0;
        char k[10];
        stc_rtc_time_t stcrtctimeconfig;//这个结构体中的时间为8421BCD码
        
        Rtc_ReadDateTime(&stcrtctimeconfig);
        Minute = (stcrtctimeconfig.u8Minute>>4)*10 + (stcrtctimeconfig.u8Minute&0x0F);//需要转换为十进制数
        Second = (stcrtctimeconfig.u8Second>>4)*10 + (stcrtctimeconfig.u8Second&0x0F);
        
        sprintf(k,"%u",Minute);//将数字转换为字符串
        
        if(Minute<10)
        {
                LCD_ShowChar('0',0);
                LCD_ShowChar(k[0],1);
        }
        else
        {
                LCD_ShowChar(k[0],0);
                LCD_ShowChar(k[1],1);
        }
        
        M0P_LCD->RAM0 |= (uint32_t)((uint32_t)LCD_Char_Point<<16);//将符号":"点亮
        
        sprintf(k,"%u",Second);//将数字转换为字符串
        
        if(Second<10)
        {
                LCD_ShowChar('0',2);
                LCD_ShowChar(k[0],3);
        }
        else
        {
                LCD_ShowChar(k[0],2);
                LCD_ShowChar(k[1],3);
        }
}
而后,在main函数中调用以及对其进行硬件初始化就可以实现时钟显示了
其中 SYS_ClkConfig:系统时钟配置
       APP_System_Init: 系统硬件初始化
       main:主函数
<blockquote><blockquote>void SYS_ClkConfig(void)

最终,我们可以看到如下视频效果(提交B站的时候,其视频标题写错了





使用特权

评论回复
沙发
hulai123456|  楼主 | 2023-8-30 18:54 | 只看该作者
最后代码咋没了,补一下:
void SYS_ClkConfig(void)
{
        stc_sysctrl_clk_cfg_t stcCfg;

        Flash_WaitCycle(FlashWaitCycle0);//flash读等待周期
        Sysctrl_SetRCHTrim(SysctrlRchFreq24MHz);// RCH = 16MHZ
        Sysctrl_SetRCLTrim(SysctrlRclFreq32768);// RCL = 32.786kHz
       
        ///< 选择内部 RCH 作为HCLK时钟源;
        stcCfg.enClkSrc    = SysctrlClkRCH;// 系统时钟为24Mhz
        ///< HCLK SYSCLK/2
        stcCfg.enHClkDiv   = SysctrlHclkDiv2; //HCLK = 12MHz
        ///< PCLK 为HCLK/1
        stcCfg.enPClkDiv   = SysctrlPclkDiv1;        //PCLK = 12MHz
        ///< 系统时钟初始化
        Sysctrl_ClkInit(&stcCfg);
       
        //使能RCL
        Sysctrl_ClkSourceEnable(SysctrlClkRCL, TRUE);       
}

void APP_System_Init(void)
{
        SYS_ClkConfig();                        // 时钟初始化配置
        Rtc_InitConfig();                        // RTC时钟配置
        Lcd_ConfigRead();                        // LCD显示配置
       
}

int32_t main(void)
{
        // 硬件模块初始化
        APP_System_Init();
        while(1)
        {
                delay1ms(10);
                Rtc_Time_Display();                // RTC时间显示
        }
}

使用特权

评论回复
板凳
lzmm| | 2023-9-7 09:53 | 只看该作者
RTC时钟通常使用外部的32.768kHz晶振作为时钟源,可以提供高精度的时间计量。RTC时钟还具有独立的计数器和寄存器,可以记录日期和时间,并提供定时器功能。

使用特权

评论回复
地板
jonas222| | 2023-9-7 10:07 | 只看该作者
RTC时钟是一个独立的定时器,具有时钟日历的功能。它拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。

使用特权

评论回复
5
claretttt| | 2023-9-7 10:51 | 只看该作者
RTC模块可以产生中断信号,用于实现定时中断功能。此外,RTC模块还可以用于系统唤醒功能,例如在低功耗模式下,通过RTC时钟来唤醒系统。

使用特权

评论回复
6
timfordlare| | 2023-9-7 11:01 | 只看该作者
拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期。

使用特权

评论回复
7
maqianqu| | 2023-9-7 11:06 | 只看该作者
RTC时钟可以通过RTC API函数进行配置和控制,以满足不同的应用需求。

使用特权

评论回复
8
bestwell| | 2023-9-7 11:23 | 只看该作者
需要配置RTC的各个寄存器,选择时钟源、设置预分频、设置初始时间等。配置时要确保RTC进入配置模式,并在写入寄存器之前检查RTC是否处于更新中。一旦配置完成,RTC可以开始计时并提供精确的时间信息。

使用特权

评论回复
9
kkzz| | 2023-9-7 11:29 | 只看该作者
RTC还包含用于管理低功耗模式的自动唤醒单元。

使用特权

评论回复
10
nomomy| | 2023-9-7 11:35 | 只看该作者
独立的时钟系统,可以在系统时钟失效的情况下继续工作,以提供精确的时间计量。

使用特权

评论回复
11
jackcat| | 2023-9-7 12:10 | 只看该作者
RTC模块不仅可以提供实时的时钟功能,还可以支持日期和闹钟功能。可以通过RTC模块来读取和设置年、月、日、小时、分钟和秒等信息,并设置闹钟触发时间。

使用特权

评论回复
12
yeates333| | 2023-9-7 12:24 | 只看该作者
RTC实质是一个掉电后还继续运行的定时器,从定时器的角度来看,相对于通用定时器TIM外设,它的功能十分简单,只有计时功能

使用特权

评论回复
13
tifmill| | 2023-9-7 12:37 | 只看该作者
为了保持RTC模块的计时功能,在断电或掉电情况下,可以使用电池供电来提供电源备份。这样即使主电源中断,RTC模块仍然可以保持时间和日期的准确性。

使用特权

评论回复
14
fengm| | 2023-9-7 12:57 | 只看该作者
它的高级之处在于掉电之后还可以正常运行。

使用特权

评论回复
15
uptown| | 2023-9-7 13:06 | 只看该作者
RTC是独立的定时器,拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能,修改计数器的值可以重新设置当前时间和日期。

使用特权

评论回复
16
1988020566| | 2023-9-7 13:25 | 只看该作者
RTC还包含用于管理低功耗模式的自动唤醒单元,在断电情况下,RTC仍可以独立运行,只要芯片的备用电源一直供电,RTC上的时间会一直走。

使用特权

评论回复
17
mmbs| | 2023-9-7 13:31 | 只看该作者
RTC可以使用多种时钟源,包括低速外部晶振(LSE)、高速外部晶振(HSE)、PLL时钟以及内部LSI(低速内部振荡器)。你可以通过配置寄存器来选择适合你应用的时钟源。使用RCC_RTCCLKConfig()函数来选择时钟源。

使用特权

评论回复
18
dspmana| | 2023-9-7 13:46 | 只看该作者
由于RTC模块使用低速晶振(LSE),因此提供的时钟精度相对较高,通常在几个PPM(百万分之几)的范围内。

使用特权

评论回复
19
averyleigh| | 2023-9-7 13:52 | 只看该作者
RTC时钟是一个非常有用的功能,可以在需要准确时间跟踪的嵌入式应用中使用。

使用特权

评论回复
20
supernan| | 2023-9-7 22:33 | 只看该作者
段码屏很简单

使用特权

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

本版积分规则

9

主题

41

帖子

3

粉丝