DS1302时钟+单片机+普中+江科大自化协
1、现象:

2、参考程序
2.1 主程序
#include <REGX52.H>
#include "LCD1602.H"
#include "DS1302.H" void main()
{
LCD1602_Init();
DS1302_Init();
LCD1602_ShowString(1,1," - - "); //静态字符初始化显示
LCD1602_ShowString(2,1," : : "); DS1302_SetTime( ); //设置时间 while(1)
{
DS1302_ReadTime( ); //读取时间
LCD1602_ShowNum(1,1,DS1302_Time[0],2); //显示年
LCD1602_ShowNum(1,4,DS1302_Time[1],2); //显示月
LCD1602_ShowNum(1,7,DS1302_Time[2],2); //显示日
LCD1602_ShowNum(2,1,DS1302_Time[3],2); //显示时
LCD1602_ShowNum(2,4,DS1302_Time[4],2); //显示分
LCD1602_ShowNum(2,7,DS1302_Time[5],2); //显示秒
}
}
2.2 DS1302源程序及头文件
#include <REGX52.H> //引脚定义,与硬件原理图有关
sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;
sbit DS1302_CE = P3^5; #define DS1302_SECOND_ADDR 0x80 //DS1302秒寄存器写地址
#define DS1302_MINUTE_ADDR 0x82 //DS1302分寄存器写地址
#define DS1302_HOUR_ADDR 0x84 //DS1302时寄存器写地址
#define DS1302_DATE_ADDR 0x86 //DS1302日寄存器写地址
#define DS1302_MONTH_ADDR 0x88 //DS1302月寄存器写地址
#define DS1302_DAY_ADDR 0x8A //DS1302星期寄存器写地址
#define DS1302_YEAR_ADDR 0x8C //DS1302年寄存器写地址
#define DS1302_WP_ADDR 0x8E //DS1302控制寄存器写地址 unsigned char DS1302_Time[]={22,8,7,20,8,55,7};
//时间数字,索引0-6分别为年、月、日、时、分、秒、星期 /**
* @brief DS1302初始化
* @param 无
* @retval 无
*/
void DS1302_Init(void)
{
DS1302_CE = 0;
DS1302_SCLK = 0;
} /**
* @brief DS1302写一个字节
* @param Command 命令字/地址
* @param Data 要写入的数据
* @retval 无
*/
void DS1302_WriteByte(unsigned char Command,Data)
{
unsigned char i;
DS1302_CE = 1; for(i=0;i<8;i++) //写地址/命令
{
DS1302_IO = Command & (0x01<<i); //从最低位开始,一次取出相应位的数据
DS1302_SCLK = 1; //SCLK上升沿,MCU向DS1302写入数据
DS1302_SCLK = 0; //一个完整的脉冲
} for(i=0;i<8;i++) //写数据
{
DS1302_IO = Data & (0x01<<i); //从最低位开始,一次取出相应位的数据
DS1302_SCLK = 1; //SCLK上升沿,MCU向DS1302写入数据
DS1302_SCLK = 0; //一个完整的脉冲
} DS1302_CE = 0;
} /**
* @brief DS1302读一个字节
* @param Command 命令字/地址
* @retval 读出的数据
*/
unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i;
unsigned char Data = 0x00; Command = Command | 0x01; //将读地址指令转换为相应的读地址指令 DS1302_CE = 1; for(i=0;i<8;i++) //写地址/命令
{
DS1302_IO = Command & (0x01<<i); //从最低位开始,一次取出相应位的数据
DS1302_SCLK = 0; //一个完整的脉冲,与写地址写数据相反
DS1302_SCLK = 1; //SCLK上升沿,MCU向DS1302写入数据
} for(i=0;i<8;i++)
{
DS1302_SCLK = 1; //写地址读数据
DS1302_SCLK = 0; //SCLK下降沿,MUC读取DS1302的数据
if(DS1302_IO) {Data = Data | (0x01<<i);}
} DS1302_CE = 0;
DS1302_IO = 0; //读取后将IO设置为0,否则读出的数据会出错
return Data;
} /**
* @brief DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
* @param 无
* @retval 无
*/
void DS1302_SetTime(void)
{
DS1302_WriteByte(DS1302_WP_ADDR,0x00); //解除芯片写保护
DS1302_WriteByte(DS1302_YEAR_ADDR, DS1302_Time[0]/10*16+DS1302_Time[0]%10); //写入年数据,十进制转为十六进制
DS1302_WriteByte(DS1302_MONTH_ADDR, DS1302_Time[1]/10*16+DS1302_Time[1]%10); //写入月数据
DS1302_WriteByte(DS1302_DATE_ADDR, DS1302_Time[2]/10*16+DS1302_Time[2]%10); //写入日数据
DS1302_WriteByte(DS1302_HOUR_ADDR, DS1302_Time[3]/10*16+DS1302_Time[3]%10); //写入小时数据
DS1302_WriteByte(DS1302_MINUTE_ADDR, DS1302_Time[4]/10*16+DS1302_Time[4]%10); //写入分钟数据
DS1302_WriteByte(DS1302_SECOND_ADDR, DS1302_Time[5]/10*16+DS1302_Time[5]%10); //写入秒钟数据
DS1302_WriteByte(DS1302_DAY_ADDR, DS1302_Time[6]/10*16+DS1302_Time[6]%10); //写入星期数据
DS1302_WriteByte(DS1302_WP_ADDR,0x80); //开启芯片写保护
} /**
* @brief DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
* @param 无
* @retval 无
*/
void DS1302_ReadTime(void)
{
unsigned char Temp;
Temp = DS1302_ReadByte(DS1302_YEAR_ADDR); DS1302_Time[0]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_MONTH_ADDR); DS1302_Time[1]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_DATE_ADDR); DS1302_Time[2]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_HOUR_ADDR); DS1302_Time[3]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_MINUTE_ADDR); DS1302_Time[4]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_SECOND_ADDR); DS1302_Time[5]=Temp/16*10+Temp%16;
Temp = DS1302_ReadByte(DS1302_DAY_ADDR); DS1302_Time[6]=Temp/16*10+Temp%16;
}
#ifndef __DS1302_H__
#define __DS1302_H__ //外部可调用时间数组,索引0~6分别为年、月、日、时、分、秒、星期
extern unsigned char DS1302_Time[]; void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_SetTime(void);
void DS1302_ReadTime(void); #endif
2.3 LCD1602源程序及头文件
#include <REGX52.H>
#include "intrins.h" //引脚配置,硬件原理图,普中A2
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_E = P2^7;
#define LCD1602_DATAPORT P0 /**
* @brief LCD1602延时函数
* @param xms=1, 延时1ms
* @retval 无
*/
void LCD1602_Delayms(unsigned char xms) //@11.0592MHz
{
unsigned char i, j,k; for(k=0;k<xms;k++)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
} } /**
* @brief LCD1602写命令,时序图
* @param Command 要写入的命令
* @retval 无
*/
void LCD1602_WriteCommand(unsigned char Command)
{
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DATAPORT = Command;
LCD1602_E = 1;
LCD1602_Delayms(1); //延时1ms
LCD1602_E = 0;
LCD1602_Delayms(1); //延时1ms
} /**
* @brief LCD1602写数据,时序图
* @param Data 要写入的数据
* @retval 无
*/
void LCD1602_WriteData(unsigned char Data)
{
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DATAPORT = Data;
LCD1602_E = 1;
LCD1602_Delayms(1); //延时1ms
LCD1602_E = 0;
LCD1602_Delayms(1); //延时1ms
} /**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD1602_Init(void)
{
LCD1602_WriteCommand(0x38); //0011_1000 功能设置,设置16x2显示,5x7点阵,8位数据接口
LCD1602_WriteCommand(0x0C); //0000_1100 显示开关控制,显示开,光标关,闪烁关
LCD1602_WriteCommand(0x06); //0000_0110 输入方式设置,数据写后,AC自动加一,画面不动
LCD1602_WriteCommand(0x01); //0000_0001 清屏,数据指针清零、所有显示清零
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD1602_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line == 1)
{
LCD1602_WriteCommand(0x80|(Column-1)); //设置要存入数据的DDROM地址,第一行地址
}
else
{
LCD1602_WriteCommand(0x80|(Column-1)+0x40); //设置要存入数据的DDROM地,第二行地址
}
} /**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD1602_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
LCD1602_SetCursor(Line,Column);
LCD1602_WriteData(Char);
} /**
* @brief 在LCD1602指定位置上显示所给字符串
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符串
* @retval 无
*/
void LCD1602_ShowString(unsigned char Line,unsigned char Column,unsigned char *String) //指针
{
unsigned char i;
LCD1602_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++) //字符串结束标志'\0'
{
LCD1602_WriteData(String[i]);
} } /**
* @brief 返回值=X的Y次方,指数运算
*/
int LCD_Power(int X,int Y)
{
unsigned char i;
int result = 1;
for(i=0;i<Y;i++)
{
result = result * X;
}
return result;
} /**
* @brief 在LCD1602指定位置开始显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~65535
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD1602_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD1602_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD1602_WriteData('0'+Number/LCD_Power(10,i-1)%10); // '0'=0x30,转换为字符显示; /**
* 789, 789/100%10, 取出百位
* 789, 789/10%10, 取出十位
* 789, 789/1%10, 取出个位
*/
}
} /**
* @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD1602_ShowSignedNum(unsigned char Line,unsigned char Column, int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD1602_SetCursor(Line,Column);
if(Number >= 0)
{
LCD1602_WriteData('+');
Number1 = Number;
}
else
{
LCD1602_WriteData('-');
Number1 = -Number; //-32768
}
for(i=Length;i>0;i--)
{
LCD1602_WriteData('0'+Number1/LCD_Power(10,i-1)%10);
}
} /**
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xffff
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD1602_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
unsigned char SingleNumber;
LCD1602_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber = Number/LCD_Power(16,i-1)%16; //从高位到低位,取出每一个十六进制数字
if(SingleNumber < 10)
LCD1602_WriteData('0'+SingleNumber);
else
LCD1602_WriteData('A'+SingleNumber-10); //SingleNumber已含有10+x
}
} /**
* @brief 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111_1111_1111_1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD1602_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD1602_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD1602_WriteData('0'+Number/LCD_Power(2,i-1)%2); //从高位到低位,取出每一个二进制数字
}
}
#ifndef __LCD1602_H__
#define __LCD1602_H__ void LCD1602_WriteCommand(unsigned char Command);
void LCD1602_WriteData(unsigned char Data); void LCD1602_Init(void);
void LCD1602_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
void LCD1602_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);
void LCD1602_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD1602_ShowSignedNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD1602_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD1602_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length); #endif
DS1302时钟+单片机+普中+江科大自化协的更多相关文章
- 单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》
引言 本设计以AT89S52单片机为控制核心,时钟芯片DS1302提供时钟源,配合LCD1602液晶显示模块,组成基本硬件系统,同时利用HC-05嵌入式蓝牙串口通讯模块,可在手机端进行日期.时间的校准 ...
- Arduino和C51开发DS1302时钟
技术:51单片机.Arduino.DS1302时钟.串口通信 概述 本文实现51单片机和Arduino串口实时显示时钟功能,让读者对DS1302能够更好的理解,这次功能也和上节课学到的串口通信运用 ...
- DS1302时钟基础使用(含代码)
了解其管脚 X1 X2 32.768KHz 晶振管脚 GND 地 RST 复位脚 I/O 数据输入/输出引脚,具有三态 SCLK 串行时钟 Vcc1,Vcc2(备用电源供电) 电源供电管脚 DS130 ...
- 「雕爷学编程」Arduino动手做(29)——DS1302时钟模块
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- DS1302时钟
采用串行数据传送方式,SPI 3线接口 SPI总线 SPI接口是以主从方式工作的,通常有一个主器件和一个或多个从器件 MOSI – 主器件数据输出,从器件数据输入 MISO – 主器件数据输入,从器件 ...
- spi接口的ds1302时钟芯片控制在lcd1602上显示
spi接口的ds1302时钟芯片控制在lcd1602上显示 ...
- 安装WP8 SDK出现“根据当前系统时钟或签名文件中的时间戳验证时要求的证书不在有效期内”的解决办法
今天重装系统了,在安装WP8 SDK时,安装了一小部分就提示“根据当前系统时钟或签名文件中的时间戳验证时要求的证书不在有效期内”的错误. 根据错误提示,貌似跟时间有关,百度了下.果真.把系统时间往前调 ...
- 关于NOR_FLASH的大小在单片机程序中的应用
在单片机开发中,NOR_FLASH常用的有4M和8M的大小: 4M的FLASH在程序中可以这样表示:Ptr < 0x220000 8M的FLASH在程序中可以这样表示:Ptr < 0x40 ...
- 单片机 MCU 中 stack 使用的探讨
stack 的使用,是单片机开发中影响最大,但是最少被讨论的问题.而提及这个问题的地方,都是对这个问题含糊其辞. 今天花了点时间,使用最笨的办法,直接阅读汇编代码,来对这个问题就行探究,这里做一下记录 ...
- VB6单片机编程中的汉字处理
在DOS时代,拥有一个华丽的汉字菜单几乎是每个高档中文应用程序必须的包装.中文Windows操作系统的出现使得高级开发平台实现全中文的提示和界面非常容易和方便.在一般的应用程序中已经很少需要去专门考虑 ...
随机推荐
- springboot~入门第二篇~页面html跳转~
遇到的问题:按照别人的blog搭jsp页面就是html页面跳转不了,总是如图: 终于找到了一个能用的blog ,换 thymeleaf(html页面跳转)成功. 控制器代码 注意下: @Control ...
- VLFeat库实现KD-Tree算法
VLFeat库实现KD-Tree算法 K-D树(K-Dimensional Tree,即K维二叉树),K=1时,即是一棵普通的二叉树.常被用于高维空间中的搜索,比如范围搜索和最近邻搜索.考虑这样一种情 ...
- Excel:使用powerquery进行多表合并
注:本文原创为:https://www.cnblogs.com/fanyu2019/p/11175827.html,本文在原创的基础上添加修改了一点内容 目录 一. 单工作簿多工作表合并 二. 多工 ...
- taro从0开发一个组件插件包
前言 经常看到taro物料市场 上有很多好用的组件,因此我也想造轮子. 网上有很多现成的方案,可是我觉得不好,他们都是在一个完整的项目中开发依赖的,实际上我们可能不需要这么多无用的依赖和代码. 所以我 ...
- 产品更新丨谷云科技 iPaaS 集成平台 V7.6 版本发布
六月,谷云科技iPaaS集成平台更新了V7.6版本.这次更新中我们着重对API网关.API编排.组织管理权限.API监控等功能进行了增强以及优化,一起来看看有什么新变化吧! 网关.监控.编排.组织权限 ...
- Restcloud ETL开箱即用-永久免费
2022年4月18日,国内领先的数据集成企业RestCloud发布了全新的ETL社区版本. RestCloud ETL社区版是一款完全国产化自主研发创新的全WEB化.开箱即用.永久免费的数据集成工具, ...
- SciTech-Mathmatics - Advanced Linear Algebra(高等线性代数): Vector、Vectors、Vector Space 和 Matrix 的奇妙联系
SciTech-Mathmatics - Advanced Linear Algebra(高等线性代数): Vector.Vectors.Vector Space和 Matrix 的奇妙联系 \(\l ...
- SciTech-EECS-STM32便携式电烙铁电原理图 + 几种常用的烙铁芯、功率及接法: jbc470/jbc245/t12/t20/tss02/jbc210/jbc115l
烙铁芯温控(测温)原理: T12仅有两根线: 测温和加热交替进行 你可能会奇怪烙铁头只引出了两根线, 是怎么实现加热和测温的? 因为烙铁头上有两种导体已形成热电偶, 而热电偶是可以测温的. 让我们来看 ...
- ICEE-Power-SCR-OptoisolaterDriver-MOC Series-MOC3081/2/3: 6-Pin DIP Zero-Cross TriacDriver Optocoupler (800 V Peak)
English Words: Thyristor: 可控硅 SCR: 单向可控硅 SCRs are unidirectional (one-way) current devices, making t ...
- NEC红外解码:定时器+外部中断实现
最近在写遥控器的解码程序,了解了NEC红外解码. NEC红外码:NEC 红外码(NEC Infrared Protocol)是目前非常常见的一种红外通信协议,广泛应用于电视遥控器.空调遥控器等设备中. ...