12864 OLED屏显示日历

普中51-单核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


       stdint.h【51单片机快速入门指南】1:基础知识和工程创建
       I2C版OLED驱动程序见【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解
       SPI版OLED驱动程序见SPI驱动0.96/1.3寸 OLED屏幕,易修改为DMA控制
       软件I2C程序见【51单片机快速入门指南】4: 软件 I2C
       软件SPI程序见【51单片机快速入门指南】5:软件SPI

calendar.c

#include "./I2C_OLED/oled.h"
#include <string.h>
#include <stdint.h>
#include <stdio.h>

#define DAYS_PER_WEEK 7
#define MONTHS 12
#define is_leap_year(year) ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) //返回当前年份是否为闰年
#define Date_Distance 16

//存储平年每月的天数
code uint8_t month_days[MONTHS] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

code uint8_t Month_Str[12][10] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

code uint8_t Week_Str[] = "MoTuWeThFrSaSu";

code uint8_t F4X6[][4] =
{
    { 0x00, 0x1F, 0x11, 0x1F },/*0*/
    { 0x00, 0x00, 0x00, 0x1F },/*1*/
    { 0x00, 0x1D, 0x15, 0x17 },/*2*/
    { 0x00, 0x15, 0x15, 0x1F },/*3*/
    { 0x00, 0x07, 0x04, 0x1F },/*4*/
    { 0x00, 0x17, 0x15, 0x1D },/*5*/
    { 0x00, 0x1F, 0x15, 0x1D },/*6*/
    { 0x00, 0x01, 0x01, 0x1F },/*7*/
    { 0x00, 0x1F, 0x15, 0x1F },/*8*/
    { 0x00, 0x17, 0x15, 0x1F }, /*9*/
};

void OLED_Showsmallnum(uint8_t x, uint8_t y, uint8_t chr)
{
    uint8_t i = 0;
    OLED_Set_Pos(x, y);
    for (i = 0; i < 4; i++)
        OLED_WR_Byte(F4X6[chr][i], OLED_DATA);
}

//返还某年某月有几天
uint8_t days_of_month(uint16_t year, uint8_t month)
{
    if (2 == month && is_leap_year(year))
        return 29; // 如果是闰年2月,返回29天
    else
        return month_days[month - 1];  //正常返回
}

//返回某年某月某日是当前年份第几天
uint16_t days_of_year(uint16_t year, uint8_t month, uint8_t day)
{
    uint8_t i;
    uint16_t days = 0;
    for (i = 1; i < month; i++)
    {
        days += days_of_month(year, i);
    }
    return days + day;
}

//返回从公元元年算起,某年某月某日是第几天,用这个数字算星期几
uint32_t get_days(uint16_t year, uint8_t month, uint8_t day)
{
    uint16_t days = days_of_year(year, month, day);
    uint16_t temp = year - 1;
    return (uint32_t)temp * 365 + temp / 4 - temp / 100 + temp / 400 + days;
}

//返回某年某月某日是星期几,星期天返回0
uint8_t day_of_week(uint16_t year, uint8_t month, uint8_t day)
{
    return get_days(year, month, day) % DAYS_PER_WEEK;
}

void printfsm(uint8_t x, uint8_t y, uint8_t num)
{
    if (num < 10)
        OLED_Showsmallnum(x, y, num);
    else
    {
        OLED_Showsmallnum(x - 4, y, num / 10);
        OLED_Showsmallnum(x, y, num % 10);
    }
}

//输出某年某个月的日历
void print_date_of_month(uint16_t year, uint8_t month)
{
	uint8_t first, days, i, h = 2;
	int16_t x;
	uint8_t year_month_str[14] = {0}; 

    //先求出这个月第一天星期几
    first = day_of_week(year, month, 1);

    //求出这个月一共有几天
    days = days_of_month(year, month);

	if(first)
	{
		x = first * Date_Distance;
	}
	else
	{
		x = 7 * Date_Distance;
	}

    for (i = 0; i < days; ++i)
    {
        printfsm(x + Date_Distance * i, h, i + 1);
        if ((first + i) % 7 == 0)
        {
            h++;
            x = -Date_Distance * i;
        }
    }
	OLED_ShowNum(64 - 4 * (strlen(Month_Str[month - 1]) + 5), 0, year, 4, 6, 0);
	OLED_ShowString(64 - 4 * strlen(Month_Str[month - 1] + 5) + 4, 0, Month_Str[month - 1], 6, 0);
	OLED_ShowString(64 - 4 * strlen(Week_Str), 1, Week_Str, 6, 0);
}

测试程序

#include <STC89C5xRC.H>
#include "intrins.h"
#include "stdint.h"
#include "./I2C_OLED/oled.h"

void print_date_of_month(int year, int month);

void main(void)
{
	OLED_Init();
	OLED_Clear();
	OLED_Display_On();	    

	print_date_of_month(2022, 1);

	OLED_Refresh_Gram();

	while(1)
	{

	}
}

效果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乙酸氧铍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值