| 
				打卡等级:偶尔看看I打卡总天数:12最近打卡:2023-12-18 15:13:58 高级会员 
 
 
	积分886 
 | 
 
| STC8H3K64S2单片机芯片+OLED12832+DS3231+USB时间校准, 18B20---小巧时钟时钟所有资料在附件,欢迎学习交流!
 
 先看制作出来的实物:
 
 
   
 
   
 可以插手机充电器,也可以插电脑USB,也可以插tpye-c手机数据线进行供电及时间校准。校准用串口助手。
 有温度,时间,日期,星期显示。特点是小巧,可视角度大。亮度高,可以在代码里设置时间关屏幕。
 电路原理图:
 
 
   
 PCB图:
 
   
 
   
 部分单片机代码:
 
 #include "STC8xxxx.H"#include "oled.h"#include "bmp.h"#include        "config.h"#include        "gpio.h"#include        "delay.h"#include<intrins.h>#include<stdlib.h>#define uchar unsigned char#define uint unsigned int/*实物端口定义*/sbit DQ=P3^7;                                 //18b20sbit TSDA=P1^2;                             //ds32321            //模拟I2C数据传送位SDAsbit TSCL=P1^1;                                                                           //模拟I2C时钟控制位SCLsbit SDA=P3^4;                             //OLED12832            //模拟I2C数据传送位SDAsbit SCL=P3^3;                                  //模拟I2C时钟控制位SCLsbit bg=P3^2;    //控制OLED打开与关闭;//***按键功能****//////***K1停止时间显示****//////***K2选择修改位置****//////***K3进行加1的修改****//////***K4将修改写入ds3231,同时启动时间显示****//   sbit K1=P1^0;   sbit K2=P1^6;   sbit K3=P1^7;   sbit K4=P5^4;/*开发板端口定义*///sbit LCD_RS=P3^5;//sbit LCD_RW=P3^6;//sbit LCD_EN=P3^4;//sbit LCD_PSB=P2^3;//sbit DQ=P2^2;                                 //18b20//sbit SDA=P1^0;                             //ds32321            //模拟I2C数据传送位SDA//sbit SCL=P1^1;//sbit bg=P2^4;                                  //模拟I2C时钟控制位SCL////***按键功能****////////***K1停止时间显示****////////***K2选择修改位置****////////***K3进行加1的修改****////////***K4将修改写入ds3231,同时启动时间显示****////sbit K1=P3^0;//sbit K2=P3^1;//sbit K3=P3^2;//sbit K4=P3^3;//定义变量uchar numbr[10]="0123456789";                        //字模uchar i=0;bit        flag=0,flag1=0;  //串口接收完成标志uchar dis4[]="   ";                                                           //          第四行显示   自己添加uchar t[]="  . ℃" ;                                          //18b20uint  sdata,xiaoshu1,xiaoshu2;                                  //整数、小数1位、小数2位bit  fg=1;                                   //温度正负标志uchar tempL=0,tempH=0;                                                           // 变量uchar year,month,date,hour,min,sec,day;                                 //        ds3231uchar a[]="2021.01.31";uchar b[]="16时20分00秒";uchar c[]="周一周二周三周四周五周六周日";uchar ndate,nmonth,nyear;uchar buffer[21]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  //设置数据串口接收缓存数组 7e开头  0d结尾  一共有15个字节      /*农历、、、、*/          struct SPDATE {  //阴历结构体   uchar year;  //年    uchar mon;   //月    uchar day;   //日};          struct SPDATE SpDate;//阴历/********阳历转换阴历表************************************/code uchar year_code[597]={                    0x04,0xAe,0x53,    //1901 0                    0x0A,0x57,0x48,    //1902 3                    0x55,0x26,0xBd,    //1903 6                    0x0d,0x26,0x50,    //1904 9                    0x0d,0x95,0x44,    //1905 12                    0x46,0xAA,0xB9,    //1906 15                    0x05,0x6A,0x4d,    //1907 18                    0x09,0xAd,0x42,    //1908 21                    0x24,0xAe,0xB6,    //1909                    0x04,0xAe,0x4A,    //1910                    0x6A,0x4d,0xBe,    //1911                    0x0A,0x4d,0x52,    //1912                    0x0d,0x25,0x46,    //1913                    0x5d,0x52,0xBA,    //1914                    0x0B,0x54,0x4e,    //1915                    0x0d,0x6A,0x43,    //1916                    0x29,0x6d,0x37,    //1917                    0x09,0x5B,0x4B,    //1918                    0x74,0x9B,0xC1,    //1919                    0x04,0x97,0x54,    //1920                    0x0A,0x4B,0x48,    //1921                    0x5B,0x25,0xBC,    //1922                    0x06,0xA5,0x50,    //1923                    0x06,0xd4,0x45,    //1924                    0x4A,0xdA,0xB8,    //1925                    0x02,0xB6,0x4d,    //1926                    0x09,0x57,0x42,    //1927                    0x24,0x97,0xB7,    //1928                    0x04,0x97,0x4A,    //1929                    0x66,0x4B,0x3e,    //1930                    0x0d,0x4A,0x51,    //1931                    0x0e,0xA5,0x46,    //1932                    0x56,0xd4,0xBA,    //1933                    0x05,0xAd,0x4e,    //1934                    0x02,0xB6,0x44,    //1935                    0x39,0x37,0x38,    //1936                    0x09,0x2e,0x4B,    //1937                    0x7C,0x96,0xBf,    //1938                    0x0C,0x95,0x53,    //1939                    0x0d,0x4A,0x48,    //1940                    0x6d,0xA5,0x3B,    //1941                    0x0B,0x55,0x4f,    //1942                    0x05,0x6A,0x45,    //1943                    0x4A,0xAd,0xB9,    //1944                    0x02,0x5d,0x4d,    //1945                    0x09,0x2d,0x42,    //1946                    0x2C,0x95,0xB6,    //1947                    0x0A,0x95,0x4A,    //1948                    0x7B,0x4A,0xBd,    //1949                    0x06,0xCA,0x51,    //1950                    0x0B,0x55,0x46,    //1951                    0x55,0x5A,0xBB,    //1952                    0x04,0xdA,0x4e,    //1953                    0x0A,0x5B,0x43,    //1954                    0x35,0x2B,0xB8,    //1955                    0x05,0x2B,0x4C,    //1956                    0x8A,0x95,0x3f,    //1957                    0x0e,0x95,0x52,    //1958                    0x06,0xAA,0x48,    //1959                    0x7A,0xd5,0x3C,    //1960                    0x0A,0xB5,0x4f,    //1961                    0x04,0xB6,0x45,    //1962                    0x4A,0x57,0x39,    //1963                    0x0A,0x57,0x4d,    //1964                    0x05,0x26,0x42,    //1965                    0x3e,0x93,0x35,    //1966                    0x0d,0x95,0x49,    //1967                    0x75,0xAA,0xBe,    //1968                    0x05,0x6A,0x51,    //1969                    0x09,0x6d,0x46,    //1970                    0x54,0xAe,0xBB,    //1971                    0x04,0xAd,0x4f,    //1972                    0x0A,0x4d,0x43,    //1973                    0x4d,0x26,0xB7,    //1974                    0x0d,0x25,0x4B,    //1975                    0x8d,0x52,0xBf,    //1976                    0x0B,0x54,0x52,    //1977                    0x0B,0x6A,0x47,    //1978                    0x69,0x6d,0x3C,    //1979                    0x09,0x5B,0x50,    //1980                    0x04,0x9B,0x45,    //1981                    0x4A,0x4B,0xB9,    //1982                    0x0A,0x4B,0x4d,    //1983                    0xAB,0x25,0xC2,    //1984                    0x06,0xA5,0x54,    //1985                    0x06,0xd4,0x49,    //1986                    0x6A,0xdA,0x3d,    //1987                    0x0A,0xB6,0x51,    //1988                    0x09,0x37,0x46,    //1989                    0x54,0x97,0xBB,    //1990                    0x04,0x97,0x4f,    //1991                    0x06,0x4B,0x44,    //1992                    0x36,0xA5,0x37,    //1993                    0x0e,0xA5,0x4A,    //1994                    0x86,0xB2,0xBf,    //1995                    0x05,0xAC,0x53,    //1996                    0x0A,0xB6,0x47,    //1997                    0x59,0x36,0xBC,    //1998                    0x09,0x2e,0x50,    //1999 294                    0x0C,0x96,0x45,    //2000 297                    0x4d,0x4A,0xB8,    //2001                    0x0d,0x4A,0x4C,    //2002                    0x0d,0xA5,0x41,    //2003                    0x25,0xAA,0xB6,    //2004                    0x05,0x6A,0x49,    //2005                    0x7A,0xAd,0xBd,    //2006                    0x02,0x5d,0x52,    //2007                    0x09,0x2d,0x47,    //2008                    0x5C,0x95,0xBA,    //2009                    0x0A,0x95,0x4e,    //2010                    0x0B,0x4A,0x43,    //2011                    0x4B,0x55,0x37,    //2012                    0x0A,0xd5,0x4A,    //2013                    0x95,0x5A,0xBf,    //2014                    0x04,0xBA,0x53,    //2015                    0x0A,0x5B,0x48,    //2016                    0x65,0x2B,0xBC,    //2017                    0x05,0x2B,0x50,    //2018                    0x0A,0x93,0x45,    //2019                    0x47,0x4A,0xB9,    //2020                    0x06,0xAA,0x4C,    //2021                    0x0A,0xd5,0x41,    //2022                    0x24,0xdA,0xB6,    //2023                    0x04,0xB6,0x4A,    //2024                    0x69,0x57,0x3d,    //2025                    0x0A,0x4e,0x51,    //2026                    0x0d,0x26,0x46,    //2027                    0x5e,0x93,0x3A,    //2028                    0x0d,0x53,0x4d,    //2029                    0x05,0xAA,0x43,    //2030                    0x36,0xB5,0x37,    //2031                    0x09,0x6d,0x4B,    //2032                    0xB4,0xAe,0xBf,    //2033                    0x04,0xAd,0x53,    //2034                    0x0A,0x4d,0x48,    //2035                    0x6d,0x25,0xBC,    //2036                    0x0d,0x25,0x4f,    //2037                    0x0d,0x52,0x44,    //2038                    0x5d,0xAA,0x38,    //2039                    0x0B,0x5A,0x4C,    //2040                    0x05,0x6d,0x41,    //2041                    0x24,0xAd,0xB6,    //2042                    0x04,0x9B,0x4A,    //2043                    0x7A,0x4B,0xBe,    //2044                    0x0A,0x4B,0x51,    //2045                    0x0A,0xA5,0x46,    //2046                    0x5B,0x52,0xBA,    //2047                    0x06,0xd2,0x4e,    //2048                    0x0A,0xdA,0x42,    //2049                    0x35,0x5B,0x37,    //2050                    0x09,0x37,0x4B,    //2051                    0x84,0x97,0xC1,    //2052                    0x04,0x97,0x53,    //2053                    0x06,0x4B,0x48,    //2054                    0x66,0xA5,0x3C,    //2055                    0x0e,0xA5,0x4f,    //2056                    0x06,0xB2,0x44,    //2057                    0x4A,0xB6,0x38,    //2058                    0x0A,0xAe,0x4C,    //2059                    0x09,0x2e,0x42,    //2060                    0x3C,0x97,0x35,    //2061                    0x0C,0x96,0x49,    //2062                    0x7d,0x4A,0xBd,    //2063                    0x0d,0x4A,0x51,    //2064                    0x0d,0xA5,0x45,    //2065                    0x55,0xAA,0xBA,    //2066                    0x05,0x6A,0x4e,    //2067                    0x0A,0x6d,0x43,    //2068                    0x45,0x2e,0xB7,    //2069                    0x05,0x2d,0x4B,    //2070                    0x8A,0x95,0xBf,    //2071                    0x0A,0x95,0x53,    //2072                    0x0B,0x4A,0x47,    //2073                    0x6B,0x55,0x3B,    //2074                    0x0A,0xd5,0x4f,    //2075                    0x05,0x5A,0x45,    //2076                    0x4A,0x5d,0x38,    //2077                    0x0A,0x5B,0x4C,    //2078                    0x05,0x2B,0x42,    //2079                    0x3A,0x93,0xB6,    //2080                    0x06,0x93,0x49,    //2081                    0x77,0x29,0xBd,    //2082                    0x06,0xAA,0x51,    //2083                    0x0A,0xd5,0x46,    //2084                    0x54,0xdA,0xBA,    //2085                    0x04,0xB6,0x4e,    //2086                    0x0A,0x57,0x43,    //2087                    0x45,0x27,0x38,    //2088                    0x0d,0x26,0x4A,    //2089                    0x8e,0x93,0x3e,    //2090                    0x0d,0x52,0x52,    //2091                    0x0d,0xAA,0x47,    //2092                    0x66,0xB5,0x3B,    //2093                    0x05,0x6d,0x4f,    //2094                    0x04,0xAe,0x45,    //2095                    0x4A,0x4e,0xB9,    //2096                    0x0A,0x4d,0x4C,    //2097                    0x0d,0x15,0x41,    //2098                    0x2d,0x92,0xB5,    //2099};///月份数据表code uchar day_code1[9]={0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};code uint day_code2[3]={0x111,0x130,0x14e};/*函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世纪,c_sun=1为19世纪调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据*/bit c_moon;//子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0bit get_moon_day(uchar month_p,uint table_addr){        uchar temp10;    switch (month_p){        case 1:{temp10=year_code[table_addr]&0x08;             if (temp10==0)return(0);else return(1);}        case 2:{temp10=year_code[table_addr]&0x04;             if (temp10==0)return(0);else return(1);}        case 3:{temp10=year_code[table_addr]&0x02;             if (temp10==0)return(0);else return(1);}        case 4:{temp10=year_code[table_addr]&0x01;             if (temp10==0)return(0);else return(1);}        case 5:{temp10=year_code[table_addr+1]&0x80;             if (temp10==0) return(0);else return(1);}        case 6:{temp10=year_code[table_addr+1]&0x40;             if (temp10==0)return(0);else return(1);}        case 7:{temp10=year_code[table_addr+1]&0x20;             if (temp10==0)return(0);else return(1);}        case 8:{temp10=year_code[table_addr+1]&0x10;             if (temp10==0)return(0);else return(1);}        case 9:{temp10=year_code[table_addr+1]&0x08;             if (temp10==0)return(0);else return(1);}        case 10:{temp10=year_code[table_addr+1]&0x04;             if (temp10==0)return(0);else return(1);}        case 11:{temp10=year_code[table_addr+1]&0x02;             if (temp10==0)return(0);else return(1);}        case 12:{temp10=year_code[table_addr+1]&0x01;             if (temp10==0)return(0);else return(1);}        case 13:{temp10=year_code[table_addr+2]&0x80;             if (temp10==0)return(0);else return(1);}                default:return(2);    }}/*函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世纪,c_sun=1为19世纪调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据*/void Conversion(bit c,uchar year,uchar month,uchar day){                         //c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据    uchar temp1,temp2,temp3,month_p;    uint temp4,table_addr;    bit flag2,flag_y;    temp1=year/16;   //BCD->hex 先把数据转换为十六进制    temp2=year%16;    year=temp1*10+temp2;        //year=temp1*16+temp2;    temp1=month/16;    temp2=month%16;    month=temp1*10+temp2;        //month=temp1*16+temp2;    temp1=day/16;    temp2=day%16;    day=temp1*10+temp2;        //day=temp1*16+temp2;    //定位数据表地址    if(c==0){        table_addr=(year+0x64-1)*0x3;    }    else {        table_addr=(year-1)*0x3;    }    //定位数据表地址完成    //取当年春节所在的公历月份    temp1=year_code[table_addr+2]&0x60;    temp1=_cror_(temp1,5);    //取当年春节所在的公历月份完成    //取当年春节所在的公历日    temp2=year_code[table_addr+2]&0x1f;    //取当年春节所在的公历日完成    // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月    if(temp1==0x1){        temp3=temp2-1;    }    else{        temp3=temp2+0x1f-1;    }    // 计算当年春年离当年元旦的天数完成    //计算公历日离当年元旦的天数,为了减少运算,用了两个表    //day_code1[9],day_code2[3]    //如果公历月在九月或前,天数会少于0xff,用表day_code1[9],    //在九月后,天数大于0xff,用表day_code2[3]    //如输入公历日为8月10日,则公历日离元旦天数为day_code1[8-1]+10-1    //如输入公历日为11月10日,则公历日离元旦天数为day_code2[11-10]+10-1    if (month<10){        temp4=day_code1[month-1]+day-1;    }    else{        temp4=day_code2[month-10]+day-1;    }    if ((month>0x2)&&(year%0x4==0)){  //如果公历月大于2月并且该年的2月为闰月,天数加1        temp4+=1;    }    //计算公历日离当年元旦的天数完成    //判断公历日在春节前还是春节后    if (temp4>=temp3){ //公历日在春节后或就是春节当日使用下面代码进行运算        temp4-=temp3;        month=0x1;        month_p=0x1;  //month_p为月份指向,公历日在春节前或就是春节当日month_p指向首月        flag2=get_moon_day(month_p,table_addr); //检查该农历月为大小还是小月,大月返回1,小月返回0        flag_y=0;        if(flag2==0)temp1=0x1d; //小月29天        else temp1=0x1e; //大小30天        temp2=year_code[table_addr]&0xf0;        temp2=_cror_(temp2,4);  //从数据表中取该年的闰月月份,如为0则该年无闰月        while(temp4>=temp1){            temp4-=temp1;            month_p+=1;            if(month==temp2){            flag_y=~flag_y;            if(flag_y==0)month+=1;            }            else month+=1;            flag2=get_moon_day(month_p,table_addr);            if(flag2==0)temp1=0x1d;            else temp1=0x1e;        }        day=temp4+1;    }    else{  //公历日在春节前使用下面代码进行运算        temp3-=temp4;        if (year==0x0){year=0x63;c=1;}        else year-=1;        table_addr-=0x3;        month=0xc;        temp2=year_code[table_addr]&0xf0;        temp2=_cror_(temp2,4);        if (temp2==0)                        month_p=0xc;        else                        month_p=0xd; //                //month_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12        flag_y=0;        flag2=get_moon_day(month_p,table_addr);        if(flag2==0)temp1=0x1d;        else temp1=0x1e;        while(temp3>temp1){            temp3-=temp1;            month_p-=1;            if(flag_y==0)month-=1;            if(month==temp2)flag_y=~flag_y;            flag2=get_moon_day(month_p,table_addr);            if(flag2==0)temp1=0x1d;            else temp1=0x1e;         }        day=temp1-temp3+1;    }//    c_moon=c;              //HEX->BCD ,运算结束后,把数据转换为BCD数据    temp1=year/10;    temp1=_crol_(temp1,4);    temp2=year%10;    SpDate.year=temp1|temp2;    temp1=month/10;    temp1=_crol_(temp1,4);    temp2=month%10;    SpDate.mon=temp1|temp2;    temp1=day/10;    temp1=_crol_(temp1,4);    temp2=day%10;    SpDate.day=temp1|temp2;}                                    ///函数//******************延时子程序 *******************************//这个延时程序的具体延时时间是time=i*8+10,适用于小于2ms的延时//************************************************************void delay(unsigned int i){for(i;i>0;i--);}//***********************************************************//                     延时子程序//************************************************************void delay1ms(uint j){while(j!=0){uchar i;for(i=124;i>0;i--);  //延时124*8+10=1002usj--;}}void Delayxms(uint ms)                        //@33.1776MHz   1ms{        unsigned char i, j;    while(ms--)           {                unsigned char i, j;        _nop_();        _nop_();        i = 44;        j = 19;        do        {                while (--j);        } while (--i);         }}/***************************************************************//**********************************18b20************************************************//**********************************18b20************************************************/void Init_DS18B20(void)                                                                                 //初始化{uchar x=0;         EA = 0;DQ=1; //DQ先置高delay(80); //稍延时DQ=0; //发送复位脉冲delay(2000); //延时(>480us)DQ=1; //拉高数据线delay(100); //等待(15~60us)x=DQ; //用X的值来判断初始化有没有成功,18B20存在的话X=0,否则X=1delay(400);         EA = 1;}//**********读一个字节************//ReadOneChar(void)  //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号{unsigned char i=0; //每个读周期最短的持续时间为60us,各个读周期之间必须有1us以上的高电平恢复期unsigned char dat=0;        EA = 0;for (i=8;i>0;i--) //一个字节有8位{DQ=1;delay(30);DQ=0;dat>>=1;delay(3); //涉及单片机频率DQ=1;  delay(1);         //读取时间没那么快,经验,33mhz的1t单片机都需要调整时序if(DQ)dat|=0x80;delay(120);}         EA = 1;return(dat);}//*********************** **写一个字节**************************//void WriteOneChar(unsigned char dat){  unsigned char i=0; //数据线从高电平拉至低电平,产生写起始信号。15us之内将所需写的位送到数据线上,          EA = 0;  for(i=8;i>0;i--) //在15~60us之间对数据线进行采样,如果是高电平就写1,低写0发生。  {   DQ=0; //在开始另一个写周期前必须有1us以上的高电平恢复期。    delay(3);//涉及单片机频率   DQ=dat&0x01;   delay(190);   DQ=1;   dat>>=1;         delay(1);  }         EA = 1;  delay(40);}void ReadTemperature(void)                                                                          //读温度值(低位放tempL;高位放tempH;)//        {         Init_DS18B20(); //初始化         WriteOneChar(0xcc); //跳过读序列号的操作         WriteOneChar(0x44); //启动温度转换         delay(2000); //转换需要一点时间,延时         Init_DS18B20(); //初始化         WriteOneChar(0xcc); //跳过读序列号的操作         WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)         tempL=ReadOneChar(); //读出温度的低位LSB         tempH=ReadOneChar(); //读出温度的高位MSB                if(tempH>0x7f)      //最高位为1时温度是负                {                 tempL=~tempL;         //补码转换,取反加一                 tempH=~tempH+1;                 fg=0;      //读取温度为负时fg=0       }                sdata = tempL/16+tempH*16;      //整数部分                xiaoshu1 = (tempL&0x0f)*10/16; //小数第一位                xiaoshu2 = (tempL&0x0f)*100/16%10;//小数第二位        }/*****************************************ds3231********************************************/#define ADDRTW          0xD0    //器件写地址#define ADDRTD          0xD1 //器件读地址#define DS3231_SEC      0x00    //秒#define DS3231_MIN      0x01    //分#define DS3231_HOUR     0x02    //时#define DS3231_DAY      0x03    //星期#define DS3231_DATE     0x04    //日#define DS3231_MONTH    0x05    //月#define DS3231_YEAR     0x06    //年//闹铃1#define DS3231_Al1SEC   0x07    //秒#define DS3231_AL1MIN   0x08    //分#define DS3231_AL1HOUR  0x09    //时#define DS3231_AL1DAY   0x0A    //星期/日//闹铃2#define DS3231_AL2MIN   0x0b    //分#define DS3231_AL2HOUR  0x0c    //时#define DS3231_AL2DAY   0x0d    //星期/日#define DS3231_CONTROL  0x0e    //控制寄存器#define DS3231_STATUS   0x0f    //状态寄存器bit ack;uchar BCD2HEX(uchar val)           //BCD转换为Byte{        uchar i;    i= val&0x0f;    val >>= 4;    val &= 0x0f;    val *= 10;    i += val;    return i;}uchar HEX2BCD(uchar val)//B码转换为BCD码        {        uchar i,j,k;          i=val/10;          j=val%10;          k=j+(i<<4);          return k;        }void Start(){    TSDA=1;                  //发送起始条件的数据信号    delay(1);    TSCL=1;    delay(5);             //起始条件建立时间大于4.7us,延时           TSDA=0;                  //发送起始信号    delay(5);             // 起始条件锁定时间大于4μs    TSCL=0;                  //钳住I2C总线,准备发送或接收数据    delay(2);}void Stop(){    TSDA=0;                  //发送结束条件的数据信号    delay(1);             //发送结束条件的时钟信号    TSCL=1;                  //结束条件建立时间大于4us    delay(5);    TSDA=1;                  //发送I2C总线结束信号    delay(4);}/********************************************************//*******************************************************************                  字节数据发送函数函数原型:     void   SendByte(uchar Dat);功能:      将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对           此状态位进行操作.(不应答或非应答都使ack=0)           ack=1        发送数据正常,           ack=0        被控器无应答或损坏。********************************************************************/void SendByte(uchar Dat){uchar BitCnt;    for(BitCnt=0;BitCnt<8;BitCnt++)         //要传送的数据长度为8位    {        if((Dat<<BitCnt)&0x80)            TSDA=1;                          //判断发送位        else            TSDA=0;          delay(1);          TSCL=1;                            //置时钟线为高,通知被控器开始接收数据位          delay(5);                       //保证时钟高电平周期大于4μs          TSCL=0;    }    delay(2);    TSDA=1;                                  //8位发送完后释放数据线,准备接收应答位    delay(2);    TSCL=1;    delay(3);    if(TSDA==1)        ack=0;    else        ack=1;                              //判断是否接收到应答信号    TSCL=0;    delay(2);}uchar RcvByte()                                                                        // 功能:      用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数应答从机。{uchar retc;uchar BitCnt;   retc=0;   TSDA=1;                           //置数据线为输入方式   for(BitCnt=0;BitCnt<8;BitCnt++)   {        delay(1);        TSCL=0;                      //置时钟线为低,准备接收数据位        delay(5);                 //时钟低电平周期大于4.7μs        TSCL=1;                      //置时钟线为高使数据线上数据有效        delay(3);        retc=retc<<1;        if(TSDA==1)            retc=retc+1;            //读数据位,接收的数据位放入retc中        delay(2);   }   TSCL=0;   delay(2);   return(retc);}void I2CACK(bit a)                         // 功能:       主控器进行应答信号(可以是应答或非应答信号,由位参数a决定){    if(a==0)        TSDA=0;              //在此发出应答或非应答信号    else        TSDA=1;    delay(3);    TSCL=1;    delay(5);             //时钟低电平周期大于4μs    TSCL=0;                  //清时钟线,钳住I2C总线以便继续接收    delay(2);}uchar I2CRead()                                                                         /************从DS3231当前地址读一个字节************/{uchar read_data;        Start();    SendByte(ADDRTD);    if(ack==0)    {  return(0);    }    read_data = RcvByte();    I2CACK(1);    Stop();    return read_data;}uchar I2CReadAdd(uchar addr)                                                 /************从DS3231指定地址读一个字节************/        {            Start();            SendByte(ADDRTW);            if(ack==0)            {          return(0);            }            SendByte(addr);            if(ack==0)            {          return(0);            }            return(I2CRead());        }void Readtime()                                                                                 /*********************读取时间**********************/        {         uchar temp;         temp=I2CReadAdd(DS3231_SEC);//秒         sec=BCD2HEX(temp);         temp=I2CReadAdd(DS3231_MIN);//分         min=BCD2HEX(temp);         temp=I2CReadAdd(DS3231_HOUR);  //时         hour=BCD2HEX(temp);         temp=I2CReadAdd(DS3231_DATE);  //日         date=BCD2HEX(temp);         temp=I2CReadAdd(DS3231_MONTH); //月         month=BCD2HEX(temp);         temp=I2CReadAdd(DS3231_YEAR);  //年         year=BCD2HEX(temp);         temp=I2CReadAdd(DS3231_DAY);         day=BCD2HEX(temp);//星期         }         void Readtimenongli()                                                                                 /*********************读取时间为了阳历转农历**********************/        {         ndate=I2CReadAdd(DS3231_DATE);  //日        // date=BCD2HEX(temp);        nmonth=I2CReadAdd(DS3231_MONTH); //月         //month=BCD2HEX(temp);        nyear=I2CReadAdd(DS3231_YEAR);  //年         }void InitDS3231()                                                                                                 //ds3231初始化        {    TSCL=1;         delay(5);         TSDA=1;         delay(5);        }void TimeDisplay(uchar Dhour,uchar Dmin,uchar Dsec)                                //时分秒数组赋值        {        b[0]=(hour / 10)+'0';        // 时十位            b[1]=numbr[Dhour % 10];        // 时个位            b[4]=numbr[Dmin / 10];         // 分十位            b[5]=numbr[Dmin % 10];         // 分个位            b[8]=numbr[Dsec / 10];         // 秒十位            b[9]=numbr[Dsec % 10];         // 秒个位        }void DateDisplay(uchar Dyear,uchar Dmonth,uchar Dday)                        //年月天数组赋值        {        a[2]=numbr[Dyear / 10];        // 年十位            a[3]=numbr[Dyear % 10];        // 年个位            a[5]=numbr[Dmonth / 10];       // 月十位            a[6]=numbr[Dmonth % 10];       // 月个位            a[8]=numbr[Dday / 10];         // 天十位            a[9]=numbr[Dday % 10];         // 天个位        }void Start_I2C(){    TSDA=1;                  //发送起始条件的数据信号    delay(1);    TSCL=1;    delay(5);             //起始条件建立时间大于4.7us,延时    TSDA=0;                  //发送起始信号    delay(5);             // 起始条件锁定时间大于4μs    TSCL=0;                  //钳住I2C总线,准备发送或接收数据    delay(2);}void Stop_I2C(){    TSDA=0;                  //发送结束条件的数据信号    delay(1);             //发送结束条件的时钟信号    TSCL=1;                  //结束条件建立时间大于4us    delay(5);    TSDA=1;                  //发送I2C总线结束信号    delay(4);}uchar write_byte(uchar addr, uchar write_data){    Start_I2C();    SendByte(ADDRTW);                //////*******************************************************************///////////    if (ack == 0)        return 0;    SendByte(addr);    if (ack == 0)        return 0;    SendByte(write_data);    if (ack == 0)        return 0;    Stop_I2C();     delay1ms(10);    return 1;}void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec,uchar w)          //函数功能:修改时间、日期和星期{          uchar temp=0;    temp=HEX2BCD(yea);    write_byte(DS3231_YEAR,temp);   //修改年    temp=HEX2BCD(mon);    write_byte(DS3231_MONTH,temp);  //修改月    temp=HEX2BCD(da);                                                                           /////////////////////    write_byte(DS3231_DATE,temp);    //修改日    temp=HEX2BCD(hou);    write_byte(DS3231_HOUR,temp);   //修改时    temp=HEX2BCD(min);    write_byte(DS3231_MIN,temp); //修改分    temp=HEX2BCD(sec);    write_byte(DS3231_SEC,temp); //修改秒         temp=HEX2BCD(w);    write_byte(DS3231_DAY,temp);  //修改星期}void nongli()    {          uchar SetDatyue,SetDat;          Readtimenongli();         Conversion(0,nyear,nmonth,ndate);          SetDatyue = BCD2HEX(SpDate.mon);//        if (SetDatyue==1){LCD1602_Dis_Str(3, 0, "正");}//        if (SetDatyue==2){LCD1602_Dis_Str(3, 0, "二");}//        if (SetDatyue==3){LCD1602_Dis_Str(3, 0, "三");}//        if (SetDatyue==4){LCD1602_Dis_Str(3, 0, "四");}//        if (SetDatyue==5){LCD1602_Dis_Str(3, 0, "五");}//        if (SetDatyue==6){LCD1602_Dis_Str(3, 0, "六");}//        if (SetDatyue==7){LCD1602_Dis_Str(3, 0, "七");}//        if (SetDatyue==8){LCD1602_Dis_Str(3, 0, "八");}//        if (SetDatyue==9){LCD1602_Dis_Str(3, 0, "九");}//        if (SetDatyue==10){LCD1602_Dis_Str(3, 0, "十");}//        if (SetDatyue==11){LCD1602_Dis_Str(3, 0, "冬");}//        if (SetDatyue==12){LCD1602_Dis_Str(3, 0, "腊");}//        LCD1602_Dis_Str(3, 1, "月");//         SetDat = BCD2HEX(SpDate.day);//    if (SetDat==1){LCD1602_Dis_Str(3, 2, "初一");}//        if (SetDat==2){LCD1602_Dis_Str(3, 2, "初二");}//        if (SetDat==3){LCD1602_Dis_Str(3, 2, "初三");}//        if (SetDat==4){LCD1602_Dis_Str(3, 2, "初四");}//        if (SetDat==5){LCD1602_Dis_Str(3, 2, "初五");}//        if (SetDat==6){LCD1602_Dis_Str(3, 2, "初六");}//        if (SetDat==7){LCD1602_Dis_Str(3, 2, "初七");}//        if (SetDat==8){LCD1602_Dis_Str(3, 2, "初八");}//        if (SetDat==9){LCD1602_Dis_Str(3, 2, "初九");}//        if (SetDat==10){LCD1602_Dis_Str(3, 2, "初十");}//        if (SetDat==11){LCD1602_Dis_Str(3, 2, "十一");}//        if (SetDat==12){LCD1602_Dis_Str(3, 2, "十二");}//        if (SetDat==13){LCD1602_Dis_Str(3, 2, "十三");}//        if (SetDat==14){LCD1602_Dis_Str(3, 2, "十四");}//        if (SetDat==15){LCD1602_Dis_Str(3, 2, "十五");}//        if (SetDat==16){LCD1602_Dis_Str(3, 2, "十六");}//        if (SetDat==17){LCD1602_Dis_Str(3, 2, "十七");}//        if (SetDat==18){LCD1602_Dis_Str(3, 2, "十八");}//        if (SetDat==19){LCD1602_Dis_Str(3, 2, "十九");}//        if (SetDat==20){LCD1602_Dis_Str(3, 2, "二十");}//        if (SetDat==21){LCD1602_Dis_Str(3, 2, "廿一");}//        if (SetDat==22){LCD1602_Dis_Str(3, 2, "廿二");}//        if (SetDat==23){LCD1602_Dis_Str(3, 2, "廿三");}//        if (SetDat==24){LCD1602_Dis_Str(3, 2, "廿四");}//        if (SetDat==25){LCD1602_Dis_Str(3, 2, "廿五");}//        if (SetDat==26){LCD1602_Dis_Str(3, 2, "廿六");}//        if (SetDat==27){LCD1602_Dis_Str(3, 2, "廿七");}//        if (SetDat==28){LCD1602_Dis_Str(3, 2, "廿八");}//        if (SetDat==29){LCD1602_Dis_Str(3, 2, "廿九");}//        if (SetDat==30){LCD1602_Dis_Str(3, 2, "三十");}                                    //显示到液晶上}void xianshi(void)     {                     OLED_ShowNum(48,0,hour,2,32); //显示时           if(sec%2==1) {OLED_ShowString(80,0,":",32);}        if(sec%2==0) {OLED_ShowString(80,0," ",32);}                 OLED_ShowNum(96,0,min/10,1,32);         //显示分                                 OLED_ShowNum(112,0,min%10,1,32);         //显示分   // OLED_ShowNum(97,0,sec,2,32);                                        /*显示星期*/                     OLED_ShowString(0,2,"W",16);                    OLED_ShowNum(10,2,day,1,16);                        OLED_ShowString(0,0,"D",16);                    OLED_ShowNum(8,0,month,2,16);         //显示月                           OLED_ShowString(24,0,".",16);                        OLED_ShowNum(32,0,date/10,1,16);                    OLED_ShowNum(40,0,date%10,1,16); //显示日                                ReadTemperature();                        //显示温度                        OLED_ShowString(22,2,"T",16);                    OLED_ShowNum(32,2,sdata,2,16);                        }void shuaxin(void)        {                     OLED_ShowNum(48,0,hour,2,32); //显示时           if(sec%2==1) {OLED_ShowString(80,0,":",32);}        if(sec%2==0) {OLED_ShowString(80,0," ",32);}                 OLED_ShowNum(96,0,min/10,1,32);         //显示分                                 OLED_ShowNum(112,0,min%10,1,32);         //显示分   // OLED_ShowNum(97,0,sec,2,32);                                        /*显示星期*/                     OLED_ShowString(0,2,"W",16);                    OLED_ShowNum(10,2,day,1,16);                        OLED_ShowString(0,0,"D",16);                    OLED_ShowNum(8,0,month,2,16);         //显示月                           OLED_ShowString(24,0,".",16);                        OLED_ShowNum(32,0,date/10,1,16);                    OLED_ShowNum(40,0,date%10,1,16); //显示日                                ReadTemperature();                        //显示温度                        OLED_ShowString(22,2,"T",16);                    OLED_ShowNum(32,2,sdata,2,16);        }  void xiugai()           //设置时间{          if(flag==1&&flag1==1)      {  ES=0;                  flag=0;                flag1=0;           year=(buffer[1]-0x30)*10+(buffer[2]-0x30);           month=(buffer[3]-0x30)*10+(buffer[4]-0x30);           date=(buffer[5]-0x30)*10+(buffer[6]-0x30);           hour=(buffer[7]-0x30)*10+(buffer[8]-0x30);           min=(buffer[9]-0x30)*10+(buffer[10]-0x30);           sec=(buffer[11]-0x30)*10+(buffer[12]-0x30);           day=(buffer[13]-0x30);           ModifyTime(year,month,date,hour,min,sec,day);                  ES=1;           flag=0;           flag1=0;           }          else           {              //   Get_Current1();                               Readtime();//                         nongli();                     xianshi();                         shuaxin();                         flag=0;                 flag1=0;           }}  /*串口 函数*/void UartInit(void)                //9600bps@33.1776MHz{        SCON = 0x50;                //8位数据,可变波特率        AUXR |= 0x01;                //串口1选择定时器2为波特率发生器        AUXR &= 0xFB;                //定时器时钟12T模式        T2L = 0xB8;                        //设置定时初始值        T2H = 0xFF;                        //设置定时初始值        AUXR |= 0x10;                //定时器2开始计时                EA=1;                        //打开总中断            ES=1;                        //打开接收中断}main()                                          /*主程序*/{        bg=0;                           P3M1 = 0x00;            P3M0 = 0x00;                         P1M1 = 0x00;            P1M0 = 0x00;                         UartInit();                InitDS3231();                 OLED_Init();//初始化OLED             OLED_ColorTurn(0);//0正常显示,1 反色显示         OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示               OLED_Clear();                // OLED_ShowString(0,0,"12:12:12",32);          //         ModifyTime(23,12,7,12,34,56,4)        ;         while(1)         {        Delayxms(200);    xiugai();    Delayxms(200);}  }void Uart() interrupt 4 using 1        //串口1中断处理{          buffer=SBUF;        if(buffer==0x7E)          //接收的报文以#开头(即0x7E)                {          flag1=1; //进入设置界面                        i=0;                        buffer=SBUF;           //开始接收                }        RI=0;        i++;        if(buffer[i-1]==0x21) //接收的报文以!结尾(即0x21)        {                i=0;                flag=1;    }}
 
 json文件:
  json文件.7z
(89.92 KB, 下载次数: 169) 
 
 代码:
  程序12832液晶 DS3231程序20231208已实现时钟显示 串口同步时间.zip
(339.25 KB, 下载次数: 180) 
 
 | 
1
喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
 
 +2楼主威武~
 |