Linux-Ubuntu之RTC实时时钟显示

Linux-Ubuntu之RTC实时时钟显示

一,原理

这个RTC的和计数器差不多,往对应寄存器中放入初始化的时间,然后在时钟的作用下,进行累加,实现计时,首先对初始化的寄存器进行配置,将要放入的年月日时分秒转化为整形数据,把这个整形数据放入到寄存器中,便可进行计时,然后读时间,将寄存器中的值读出来,转化为年月日时分秒,将其放入数组中,运用屏幕显示字符函数,进行显示。

二,代码实现

c 复制代码
/*rtc.h*/
#ifndef _DSP_RTC_H
#define _DSP_RTC_H
#include "imx6ul.h"

/*时间宏定义*/
#define SECONDS_IN_A_DAY  86400
#define SECONDS_IN_A_HOUR 3600
#define SECONDS_IN_A_MINUTE 60
#define DAYS_IN_A_YEAR  365
#define YEAR_RANGE_START 1970
#define YEAR_RANGE_END 2099

/*时间结构体*/
struct rtc_datetime{
    unsigned short year;
    unsigned char month;
    unsigned char day;
    unsigned char hour;
    unsigned char minute;
    unsigned char second;
};
/*rtc初始化*/
void rtc_init(void);
/*使能*/
void rtc_enable(void);
/*关闭使能*/
void rtc_disable(void);
/*判断润年*/
unsigned char rtc_isleapyear(unsigned short year);
/*将年月日时间转换为秒函数*/
unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime);
/*将相应秒数,写入到相应寄存器中*/
void rtc_in_register(struct rtc_datetime *rtctime);
/*将读出第秒数,转化为真的时间*/
void rtc_convertseconds_to_datetime(u64 seconds, struct rtc_datetime *datetime);
/*读寄存器值,从而得到时间*/
void rtc_out_register(struct rtc_datetime *rtctime);

#endif 

/*rtc.c*/
#include "dsp_rtc.h"

/*rtc初始化*/
void rtc_init(void)
{

    SNVS->HPCOMR |=(1<<31)|(1<<8);
    struct rtc_datetime rtcDate;
    rtcDate.year=2025;
    rtcDate.month=1;
    rtcDate.day=2;
    rtcDate.hour=4;
    rtcDate.minute=1;
    rtcDate.second=0;
    rtc_in_register(&rtcDate);

    rtc_enable();//使能
}

/*使能*/
void rtc_enable(void)
{
    SNVS->LPCR |=1<<0;
    while((SNVS->LPCR & 0x01)==0);//当为0时候,一直在while里面循环
}

/*关闭使能*/
void rtc_disable(void)
{
    SNVS->LPCR &=~(1<<0);
    while((SNVS->LPCR & 0x01)==1);//为1的时候,一直循环
}

/*判断润年*/
unsigned char rtc_isleapyear(unsigned short year)
{	
	unsigned char value=0;
	
	if(year % 400 == 0)
		value = 1;
	else 
	{
		if((year % 4 == 0) && (year % 100 != 0))
			value = 1;
		else 
			value = 0;
	}
	return value;
}
/*将年月日时间转换为秒函数*/
unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime)
{	
	unsigned short i = 0;
	unsigned int seconds = 0;
	unsigned int days = 0;
	unsigned short monthdays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
	
	for(i = 1970; i < datetime->year; i++)
	{
		days += DAYS_IN_A_YEAR; 		/* 平年,每年365天 */
		if(rtc_isleapyear(i)) days += 1;/* 闰年多加一天 		*/
	}

	days += monthdays[datetime->month];
	if(rtc_isleapyear(i) && (datetime->month >= 3)) days += 1;/* 闰年,并且当前月份大于等于3月的话加一天 */

	days += datetime->day - 1;

	seconds = days * SECONDS_IN_A_DAY + 
				datetime->hour * SECONDS_IN_A_HOUR +
				datetime->minute * SECONDS_IN_A_MINUTE +
				datetime->second;

	return seconds;	
}

/*将相应秒数,写入到相应寄存器中*/
void rtc_in_register(struct rtc_datetime *rtctime)
{
    unsigned int seconds = 0;
    rtc_disable();//关闭使能
    seconds=rtc_coverdate_to_seconds(rtctime);

    /*放入寄存器中*/
    SNVS->LPSRTCMR = (unsigned int)(seconds>>17);
    SNVS->LPSRTCLR = (unsigned int)(seconds<<15);
}
/*将读出第秒数,转化为真的时间*/
void rtc_convertseconds_to_datetime(u64 seconds, struct rtc_datetime *datetime)
{
    u64 x;
    u64  secondsRemaining, days;
    unsigned short daysInYear;

    /* 每个月的天数       */
    unsigned char daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};

    secondsRemaining = seconds; /* 剩余秒数初始化 */
    days = secondsRemaining / SECONDS_IN_A_DAY + 1; 		/* 根据秒数计算天数,加1是当前天数 */
    secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY; /*计算天数以后剩余的秒数 */

	/* 计算时、分、秒 */
    datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
    secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
    datetime->minute = secondsRemaining / 60;
    datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;

    /* 计算年 */
    daysInYear = DAYS_IN_A_YEAR;
    datetime->year = YEAR_RANGE_START;
    while(days > daysInYear)
    {
        /* 根据天数计算年 */
        days -= daysInYear;
        datetime->year++;

        /* 处理闰年 */
        if (!rtc_isleapyear(datetime->year))
            daysInYear = DAYS_IN_A_YEAR;
        else	/*闰年,天数加一 */
            daysInYear = DAYS_IN_A_YEAR + 1;
    }
	/*根据剩余的天数计算月份 */
    if(rtc_isleapyear(datetime->year)) /* 如果是闰年的话2月加一天 */
        daysPerMonth[2] = 29;

    for(x = 1; x <= 12; x++)
    {
        if (days <= daysPerMonth[x])
        {
            datetime->month = x;
            break;
        }
        else
        {
            days -= daysPerMonth[x];
        }
    }

    datetime->day = days;

}

/*读寄存器值,从而得到时间*/
void rtc_out_register(struct rtc_datetime *rtctime)
{
    uint64_t seconds = 0;
    seconds = (uint64_t)((uint64_t)SNVS->LPSRTCMR<<17|SNVS->LPSRTCLR>>15);
    rtc_convertseconds_to_datetime(seconds,rtctime);

}

主函数:

c 复制代码
#include "main.h"

#include "dsp_clk.h"

#include "dsp_led.h"

#include "dsp_delay.h"

#include "beep.h"

#include "dsp_key.h"

#include "dsp_int.h"

#include "dsp_exti.h"

#include "dsp_epit.h"

#include "dsp_uart.h"

#include "stdio.h"

#include "dsp_lcd.h"

#include "dsp_lcdapi.h"

#include "dsp_rtc.h"

int main(void)

{

    // int b=0;

    unsigned char kkkk=0;

    struct rtc_datetime rtc_now_time;

    char buf[160]={};

    int_init();//中断初始化

    imx6u_clkinit();//时钟初始化

    key_init();//按键初始化

    clk_enable();//时钟初始化

    uart_init();//串口初始化

    beep_init();//凤鸣器初始化

    led_init();//led初始化

    lcd_init();//LCD读ID号

    rtc_init();//RTC初始化

    tftlcd_dev.forecolor = LCD_RED;

    tftlcd_dev.backcolor = LCD_WHITE;

    // unsigned char *b,*c,*f;

    // unsigned short *a;

   // lcd_show_string(10,40,260,32,32,(char *)"Fucking high");

    while(1)

    {

        tftlcd_dev.forecolor = LCD_RED;

        //lcd_show_string(100,100,240,16,16,(char *)"2025.1.2");



        rtc_out_register(&rtc_now_time);

        sprintf(buf,"%d.%d.%d-%d:%d:%d\r\n",rtc_now_time.year,rtc_now_time.month,

                rtc_now_time.day,rtc_now_time.hour,rtc_now_time.minute,rtc_now_time.second);



        char *a;

        *a=rtc_now_time.month;

        // a=&rtc_now_time.year;

        // b=&rtc_now_time.month;

        // c=&rtc_now_time.day;

        // f=&rtc_now_time.second;

        lcd_show_string(140,140,240,32,32,(char *)buf);//屏幕显示时间

        lcd_show_string(200,200,240,32,32,a);

        printf("a=%d\r\n",*a);

        printf("rtc_now_time.month=%d\r\n",rtc_now_time.month);

        // lcd_clear(show_color[b]);

        // b++;

        // if(b==8) b=0;

        led_mode(kkkk);

        delay(1000);

        kkkk = !kkkk;     

    }

    return 0;    

}

三,小结

1.为什么这个显示不出来?

c 复制代码
      lcd_show_string(140,140,240,32,32,(char *)buf);//屏幕显示时间

       lcd_show_string(200,200,240,32,32,a);// ?

也设置为指针类型,并且数据打印出来是1,在屏幕上就是无法显示。

相关推荐
.Ashy.6 小时前
2026.4.11 蓝桥杯软件类C/C++ G组山东省赛 小记
c语言·c++·蓝桥杯
菜菜艾6 小时前
基于llama.cpp部署私有大模型
linux·运维·服务器·人工智能·ai·云计算·ai编程
重生的黑客6 小时前
Linux开发工具:条件编译、动静态库与 make/makefile 入门
linux·运维·服务器
2401_892070986 小时前
链栈(链式栈) 超详细实现(C 语言 + 逐行精讲)
c语言·数据结构·链栈
minji...7 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
w6100104667 小时前
cka-2026-ConfigMap
java·linux·cka·configmap
cc_yy_zh7 小时前
Win10 家庭版找不到Device Guard; 无法处理 VMware Workstation与Device Guard不兼容问题
linux·vmware
嵌入式吴彦祖7 小时前
Luckfox Pico Ultra W WIFI
linux·嵌入式硬件
SPC的存折8 小时前
MySQL 8组复制完全指南
linux·运维·服务器·数据库·mysql
Linux技术芯9 小时前
Refault Distance算法详解
linux