【WCH】CH32F203基于内部RTC时钟+I2C SSD1306 OLED显示

news2024/11/27 8:24:02

【WCH】CH32F203基于内部RTC时钟+SSD1306 OLED显示


  • 📌相关篇《STM32F103基于标准库+I2C SSD1306仿数码管RTC时钟显示》

  • ✨CH32F203的内部时钟频率:40KHz

  • 🔖基于Keil开发环境

  • 📜基于SDK中的RTC示例修改为内部时钟源,串口打印:
    在这里插入图片描述

  • 🌼I2C SSD1306 OLED显示
    在这里插入图片描述

⛳RTC内部时钟源修改注意事项

  1. RTC内部时钟源的频率为40KHz。
    在这里插入图片描述

🛠RTC内部时钟源代码修改

/*********************************************************************
 * @fn      RTC_Init
 *
 * @brief   Initializes RTC collection.
 *
 * @return  1 - Init Fail
 *          0 - Init Success
 */
u8 RTC_Init(void)
{
    u8 temp = 0;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);

    /* Is it the first configuration */

    BKP_DeInit();
	RCC_LSICmd(ENABLE  );//内部时钟使能
//    RCC_LSEConfig(RCC_LSE_ON);//外部时钟
// while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && temp < 250)//外部
    while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET && temp < 250)//内部
    {
        temp++;
        Delay_Ms(20);
    }
    if(temp >= 250)
    {
        return 1;
    }
     RCC_RTCCLKConfig( RCC_RTCCLKSource_LSI );//选择内部时钟源
     RCC_RTCCLKCmd( ENABLE );
     RTC_WaitForLastTask();
     RTC_WaitForSynchro();
     //		RTC_ITConfig(RTC_IT_ALR, ENABLE);
     RTC_ITConfig( RTC_IT_SEC, ENABLE );
     RTC_WaitForLastTask();
     RTC_EnterConfigMode();
		RTC_SetPrescaler( 40000-1 );//内部40KHz
//     RTC_SetPrescaler( 32767 );//外部32768HZ
     RTC_WaitForLastTask();
     RTC_Set( 2023, 4, 25, 16, 58, 55 );       /* Setup Time */
     RTC_ExitConfigMode();
     BKP_WriteBackupRegister( BKP_DR1, 0XA1A1 );//这里和STM32不一样不是0x5050
    RTC_NVIC_Config();
    RTC_Get();

    return 0;
}
  • 🌿RTC.C
#include "RTC.h"
#include "ch32f20x_rtc.h"
#include "ch32f20x_bkp.h"
#include "ch32f20x_pwr.h"


_calendar_obj calendar;

u8 const table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
const u8 mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

/* Exported_Functions */


/*********************************************************************
 * @fn      RTC_NVIC_Config
 *
 * @brief   Initializes RTC Int.
 *
 * @return  none
 */
static void RTC_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure = {0};
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*********************************************************************
 * @fn      RTC_Init
 *
 * @brief   Initializes RTC collection.
 *
 * @return  1 - Init Fail
 *          0 - Init Success
 */
u8 RTC_Init(void)
{
    u8 temp = 0;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);

    /* Is it the first configuration */

    BKP_DeInit();
	RCC_LSICmd(ENABLE  );
//    RCC_LSEConfig(RCC_LSE_ON);
    while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET && temp < 250)
    {
        temp++;
        Delay_Ms(20);
    }
    if(temp >= 250)
    {
        return 1;
    }
     RCC_RTCCLKConfig( RCC_RTCCLKSource_LSI );//仅修改了此处
     RCC_RTCCLKCmd( ENABLE );
     RTC_WaitForLastTask();
     RTC_WaitForSynchro();
     //		RTC_ITConfig(RTC_IT_ALR, ENABLE);
     RTC_ITConfig( RTC_IT_SEC, ENABLE );
     RTC_WaitForLastTask();
     RTC_EnterConfigMode();
		RTC_SetPrescaler( 40000-1 );//内部40KHz
//     RTC_SetPrescaler( 32767 );//外部32768HZ
     RTC_WaitForLastTask();
     RTC_Set( 2023, 4, 25, 16, 58, 55 );       /* Setup Time */
     RTC_ExitConfigMode();
     BKP_WriteBackupRegister( BKP_DR1, 0XA1A1 );

    RTC_NVIC_Config();
    RTC_Get();

    return 0;
}


/*********************************************************************
 * @fn      Is_Leap_Year
 *
 * @brief   Judging whether it is a leap year.
 *
 * @param   year
 *
 * @return  1 - Yes
 *          0 - No
 */
u8 Is_Leap_Year(u16 year)
{
    if(year % 4 == 0)
    {
        if(year % 100 == 0)
        {
            if(year % 400 == 0)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        else
        {
            return 1;
        }
    }
    else
    {
        return 0;
    }
}

/*********************************************************************
 * @fn      RTC_Set
 *
 * @brief   Set Time.
 *
 * @param   Struct of _calendar_obj
 *
 * @return  1 - error
 *          0 - success
 */
u8 RTC_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec)
{
    u16 t;
    u32 seccount = 0;
    if(syear < 1970 || syear > 2099)
    {
        return 1;
    }
    for(t = 1970; t < syear; t++)
    {
        if(Is_Leap_Year(t))
        {
            seccount += 31622400;
        }
        else
        {
            seccount += 31536000;
        }
    }
    smon -= 1;
    for(t = 0; t < smon; t++)
    {
        seccount += (u32)mon_table[t] * 86400;
        if(Is_Leap_Year(syear) && t == 1)
        {
            seccount += 86400;
        }
    }
    seccount += (u32)(sday - 1) * 86400;
    seccount += (u32)hour * 3600;
    seccount += (u32)min * 60;
    seccount += sec;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);
    RTC_SetCounter(seccount);
    RTC_WaitForLastTask();
    return 0;
}

/*********************************************************************
 * @fn      RTC_Alarm_Set
 *
 * @brief   Set Alarm Time.
 *
 * @param   Struct of _calendar_obj
 *
 * @return  1 - error
 *          0 - success
 */
u8 RTC_Alarm_Set(u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec)
{
    u16 t;
    u32 seccount = 0;
    if(syear < 1970 || syear > 2099)
    {
        return 1;
    }
    for(t = 1970; t < syear; t++)
    {
        if(Is_Leap_Year(t))
        {
            seccount += 31622400;
        }
        else
        {
            seccount += 31536000;
        }
    }
    smon -= 1;
    for(t = 0; t < smon; t++)
    {
        seccount += (u32)mon_table[t] * 86400;
        if(Is_Leap_Year(syear) && t == 1)
        {
            seccount += 86400;
        }
    }
    seccount += (u32)(sday - 1) * 86400;
    seccount += (u32)hour * 3600;
    seccount += (u32)min * 60;
    seccount += sec;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);
    RTC_SetAlarm(seccount);
    RTC_WaitForLastTask();

    return 0;
}

/*********************************************************************
 * @fn      RTC_Get
 *
 * @brief   Get current time.
 *
 * @return  1 - error
 *          0 - success
 */
u8 RTC_Get(void)
{
    static u16 daycnt = 0;
    u32 timecount = 0;
    u32 temp = 0;
    u16 temp1 = 0;
    timecount = RTC_GetCounter();
    temp = timecount / 86400;
    if(daycnt != temp)
    {
        daycnt = temp;
        temp1 = 1970;
        while(temp >= 365)
        {
            if(Is_Leap_Year(temp1))
            {
                if(temp >= 366)
                {
                    temp -= 366;
                }
                else
                {
                    temp1++;
                    break;
                }
            }
            else
            {
                temp -= 365;
            }
            temp1++;
        }
        calendar.w_year = temp1;
        temp1 = 0;
        while(temp >= 28)
        {
            if(Is_Leap_Year(calendar.w_year) && temp1 == 1)
            {
                if(temp >= 29)
                {
                    temp -= 29;
                }
                else
                {
                    break;
                }
            }
            else
            {
                if(temp >= mon_table[temp1])
                {
                    temp -= mon_table[temp1];
                }
                else
                {
                    break;
                }
            }
            temp1++;
        }
        calendar.w_month = temp1 + 1;
        calendar.w_date = temp + 1;
    }
    temp = timecount % 86400;
    calendar.hour = temp / 3600;
    calendar.min = (temp % 3600) / 60;
    calendar.sec = (temp % 3600) % 60;
    calendar.week = RTC_Get_Week(calendar.w_year, calendar.w_month, calendar.w_date);
    return 0;
}


/*********************************************************************
 * @fn      RTC_Get_Week
 *
 * @brief   Get the current day of the week.
 *
 * @param   year/month/day
 *
 * @return  week
 */
u8 RTC_Get_Week(u16 year, u8 month, u8 day)
{
    u16 temp2;
    u8 yearH, yearL;

    yearH = year / 100;
    yearL = year % 100;
    if(yearH > 19)
    {
        yearL += 100;
    }
    temp2 = yearL + yearL / 4;
    temp2 = temp2 % 7;
    temp2 = temp2 + day + table_week[month - 1];
    if(yearL % 4 == 0 && month < 3)
    {
        temp2--;
    }
    return(temp2 % 7);
}
/*********************************************************************
 * @fn      RTC_IRQHandler
 *
 * @brief   This function handles RTC Handler.
 *
 * @return  none
 */
void RTC_IRQHandler( void )
{
    if( RTC_GetITStatus( RTC_IT_SEC ) != RESET ) /* Seconds interrupt */
    {
        RTC_Get();
    }
    if( RTC_GetITStatus( RTC_IT_ALR ) != RESET ) /* Alarm clock interrupt */
    {
        RTC_ClearITPendingBit( RTC_IT_ALR );
        RTC_Get();
    }

    RTC_ClearITPendingBit( RTC_IT_SEC | RTC_IT_OW );
    RTC_WaitForLastTask();
}

  • 🌿RTC.H
#ifndef __RTC_H
#define __RTC_H	

#include "debug.h"

typedef struct
{
    vu8 hour;
    vu8 min;
    vu8 sec;

    vu16 w_year;
    vu8  w_month;
    vu8  w_date;
    vu8  week;
} _calendar_obj;

extern _calendar_obj calendar;
extern u8 const mon_table[12];	//月份日期数据表

u8 RTC_Init( void );
u8 Is_Leap_Year( u16 year );
u8 RTC_Alarm_Set( u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec );
u8 RTC_Get( void );
u8 RTC_Get_Week( u16 year, u8 month, u8 day );
u8 RTC_Set( u16 syear, u8 smon, u8 sday, u8 hour, u8 min, u8 sec );


#endif
  • main.c
/********************************** (C) COPYRIGHT *******************************
* File Name          : main.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2021/08/08
* Description        : Main program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for 
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/

/*
 *@Note
 Calendar routine:
 This routine demonstrates that the initial time is 13:58:55 on October 8, 2019, real-time timing, 
 every 1S through the serial port print the real-time clock value.

*/

#include "debug.h"
#include "RTC.h" 
/* Global define */


/* Global Variable */


/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main( void )
{
    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
    Delay_Init();
    USART_Printf_Init( 115200 );
    printf( "SystemClk:%d\r\n", SystemCoreClock );
    printf( "RTC Test\r\n" );
    if(RTC_Init()==0)
		{
			printf("Init Fail \r\n");
		}else printf("Init Success \r\n");

    while( 1 )
    {
        Delay_Ms( 1000 );
        printf( "year/month/day/week/hour/min/sec:\r\n" );
        printf( "%d-%d-%d  %d  %d:%d:%d\r\n", calendar.w_year, calendar.w_month, calendar.w_date,
                calendar.week, calendar.hour, calendar.min, calendar.sec );
    }
}




  • 🌿基于内部时钟源,串口打印RTC时间源码

链接: https://pan.baidu.com/s/1affWjahgxh9seB-9bcxF8g
提取码: chiw
  • 🌿基于STM32移植到CH32F203TC时钟+I2C SSD1306 OLED显示程序
链接: https://pan.baidu.com/s/1gMHbHdmvWhQqolOjeaLuZg
提取码: w9gc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/460457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解C语言string.h中常用的14个库函数(三)

本篇博客继续讲解C语言string.h头文件中的库函数。本篇博客计划讲解3个函数&#xff0c;分别是&#xff1a;strstr, strtok, strerror。其中strstr函数我会用一种最简单的方式模拟实现。 strstr char * strstr ( const char * str1, const char * str2 );strstr可以在str1中查…

电脑怎么远程控制另一台电脑

要从一台电脑远程控制另一台电脑&#xff0c;您可以使用远程桌面软件。 以下是远程控制另一台电脑的步骤&#xff1a; 一、在两台电脑上安装远程桌面软件 有多种远程桌面软件可用&#xff0c;例如 Splashtop、微软远程桌面。 在远程电脑和本地电脑上分别安装软件。访问各自软…

MQ集群(rabbitMQ)

普通集群: 创建过程 我们先在之前启动的mq容器中获取一个cookie值&#xff0c;作为集群的cookie。执行下面的命令&#xff1a; docker exec -it mq cat /var/lib/rabbitmq/.erlang.cookie 可以看到cookie值如下&#xff1a; EFLYOBKNYFETSAXOUEYI 接下来&#xff0c;停止…

中级软件设计师备考---操作系统和计算机网络

【因为我自己是软件工程专业毕业的学生&#xff0c;所以408里的这两门课都比较熟悉&#xff0c;因此这一部分只放一些我印象不是完全深刻的知识。】 目录 操作系统前驱图与PV操作死锁的预防与避免绝对路径和相对路径缺页中断的某种练习题 计算机网络网络规划与设计特殊含义的I…

Jenkins Kubernetes

Kubernetes集成Harbor Harbor 私服配置 在Kubernetes的master和所有worker节点上加上harbor配置&#xff0c;修改daemon.json&#xff0c;支持Docker仓库&#xff0c;并重启Docker。 sudo vim /etc/docker/daemon.json {"registry-mirrors": ["https://jrabv…

Talk预告 | 北京大学刘博UCL冯熙栋-TorchOpt,一个高效的可微优化库

本期为TechBeat人工智能社区第490期线上Talk&#xff01; 北京时间4月13日(周四)20:00&#xff0c;北京大学智能科学与技术研究助理—刘博和伦敦大学学院 &#xff08;UCL&#xff09; 计算机博士生—冯熙栋的Talk将准时在TechBeat人工智能社区开播&#xff01; 他们与大家分…

【具体到每一步】从0制作一个uniapp的新闻类页面(界面篇)

目录 项目初始化 / 基础配置 项目创建 配置路由/页面/tabbar pages.json配置tabbar 配置图标/静态资源 导航栏和字体颜色 scroll-view实现横向滚动条样式 公共模块定义components组件 新建组件 使用组件 组件里的结构 布局个人中心页面 组件差异化处理 数据传递 导航…

【角色用例图讲解】

角色用例图讲解 一、 用例图的定义及组成要素二、参与者与用例的4种关系三、 常用的用例图软件 我是将军我一直都在&#xff0c;。&#xff01; 一、 用例图的定义及组成要素 用例图是编写需求说明时经常用到的需求表达方式&#xff0c;用于向开发、测试同事说明需求中用户与系…

【机智云物联网低功耗转接板】+模拟无线远程控制仪表启停

GE211 是机智云自研的定制化的物联网转接板&#xff0c;使用 ESP32-C3-WROOM-02 通讯模块&#xff0c;适用于白色智能家电等设备应用。硬件设计上采用支持 WiFi 和 BLE 的双模无线通信模块&#xff0c;具备TTL电平转换串口&#xff0c;免开发快速接入&#xff0c;提高开发效率。…

SpringBoot 使用 Sa-Token 完成权限认证

一、设计思路 所谓权限认证&#xff0c;核心逻辑就是判断一个账号是否拥有指定权限&#xff1a; 有&#xff0c;就让你通过。没有&#xff1f;那么禁止访问&#xff01; 深入到底层数据中&#xff0c;就是每个账号都会拥有一个权限码集合&#xff0c;框架来校验这个集合中是…

Linux 常用命令2

文件内容查看 Linux系统中使用以下命令来查看文件的内容&#xff1a; cat 由第一行开始显示文件内容tac 从最后一行开始显示nl 显示的时候&#xff0c;顺道输出行号more 一页一页的显示文件内容less与more 类似&#xff0c;但可以往前翻页head 只看头几行tail 只看尾巴几行 j…

【ZooKeeper to KRaft Migration】kafka 3.4版本zookeeper数据迁移到kraft

引言 kafka在3.X版本后内置了kraft用来替代zookeeper管理集群&#xff0c;但是在升级的过程中发现&#xff0c;许多升级的文档都是只有新部署安装kraft版本&#xff0c;而没有涉及到数据迁移相关的资料&#xff0c;这样如果直接变更的话&#xff0c;会导致kakfa中的数据全部丢…

升级gpt4-GPT最新版本怎么下载使用

怎么 让gpt-3的模型升级gpt4 GPT-4是OpenAI的未来版本&#xff0c;目前还未发布。因此&#xff0c;我们无法准确指导如何将GPT-3升级到GPT-4。要升级GPT-3&#xff0c;需要进行大量的研究和开发工作。如果OpenAI发行了GPT-4的预览版&#xff0c;那么可能需要花费大量的时间和资…

Redission实现分布式锁lock()和tryLock()方法的区别

lock.lock(30, TimeUnit.SECONDS); // 尝试获取锁30秒&#xff0c;如果获取不到则放弃 //尝试获取锁&#xff0c;等待5秒&#xff0c;持有锁10秒钟 boolean success lock.tryLock(0, 10, TimeUnit.SECONDS); Redisson 是一种基于 Redis 的分布式锁框架&#xff0c;提供了 lo…

国产蓝牙芯片OM6621P/HS6621系列门锁方案

在5G、物联网以及互联网家装市场的快速发展等多重因素的作用下&#xff0c;中国智能家居市场展现蓬勃发展态势。作为智能家居“入口”产品以及家庭智能安防产品的核心单品&#xff0c;智能门锁以其区别于传统机械锁更具安全性、便利性、可扩展性的优势&#xff0c;逐渐成为智能…

Java+GeoTools(开源的Java GIS工具包)快速入门-实现读取shp文件并显示

场景 GeoTools GeoTools 是一个开源的 Java GIS 工具包&#xff0c;可利用它来开发符合标准的地理信息系统。 GeoTools 提供了 OGC (Open Geospatial Consortium) 规范的一个实现来作为他们的开发。 官网地址: GeoTools The Open Source Java GIS Toolkit — GeoTools 参考…

Linux账号密码安全策略设置

前言 随着云计算厂商的兴起&#xff0c;云资源如ECS不再只有企业或者公司才会使用&#xff0c;普通人也可以自己买一台ECS来搭建自己的应用或者网站。虽然云计算厂商帮我们做了很多安全相关的工作&#xff0c;但并不代表我们的机器资源就绝对是安全的。 要知道有很多事情是云…

群策群力:组织效率,管理?沟通?协作?

你好&#xff0c;我是苏杰。今天让我们一起聊聊组织效率的话题。 团队大了&#xff0c;也能够自我造血以后&#xff0c;如何可持续发展就会成为我们关注的焦点。产品会衰退、行业有生命周期&#xff0c;但人的成长&#xff0c;以及人构成的组织&#xff0c;可以帮我们不断成功…

【大厂直通车】飞猪旅行日常实习_测开面经

📑哈喽,大家好,我是小浪;📱本专栏致力于持续更新最新各大厂面经,实习消息,招聘要求; 那么目前价格也仅仅是定到了29.9💰;非常的实惠,一杯奶茶钱🍵; 🧃对于订阅本专栏的同学们,博主在努力更新,那么最近忙于学校的考试,没来得及正常更新,非常抱歉,这几…

论文综述——DORE: Document Ordered Relation Extraction based on Generative Framework

DORE: Document Ordered Relation Extraction based on Generative Framework 文章的主要目标是对文档级的关系抽取。以往的研究主要是基于分类的研究&#xff0c;生成式关系抽取研究较少而且性能不佳。 文档级相比于句子级的关系抽取存在序列长度过长&#xff0c;以及实体定位…