51单片机DS1302时钟芯片应用Proteus仿真
系列文章目录
第一章 51单片机Proteus仿真(一) DS1302使用
文章目录
- 系列文章目录
- 前言
- 一、DS1302时序解读
- 二、BCD码转十进制解读
- 三、Proteus仿真
- 四、详细代码
前言
51单片机使用Proteus仿真。小白一枚记录自己学习日常。疫情期间Proteus走起,这软件很强大,使用中也遇到很多问题,求助度娘已解决。代码解释不是特别详细,文笔不好,请各位大神见谅。本人记录自己大四毕业之际准备毕业论文随笔,如有能帮助到您的地方,跪求点赞关注。诸君共勉,共同进步。本文代码实现当前时间 21时02分39秒。万年历下次再写以及显示温度等
提示:以下是本篇文章正文内容,下面案例可供参考
一、DS1302时序解读
时序解释:
写时序 ( 给DS1302写入数据) 需要先确定写哪个寄存器,再写入数据。因为每个寄存器存储数据不同,有存储秒、分、小时、日期、年等寄存器
这里要理解数据输入(单片机向时钟芯片写数据)是SCLK上升沿,数据输出(单片机读取时钟芯片数据)是SCLK下降沿。
向某一个寄存器写入一个字节,就是送入16位(就是数据输入),需16个脉冲。先0后1算一个脉冲(上升沿实现)。
CE=1时,先写命令字,确定给哪个寄存器写数据。最低位设置写还是读,当时钟上升沿来临时,最低位被写入,依次时钟上升沿来临读入一位数据。最高位默认为1。第六位为0是时钟芯片数据,为1是RAM数据。A0-A4是寄存器地址。一个时钟上升沿写入一位数据。写完命令字,再写入数据指令。
因为时钟芯片要一位一位的读写,所以取出一位数据即可。使用Data&0X01读取最低位(第一位),Data&0X02读取第二位,使用for循环8次即可读取8位数据。代码如下
DS1302_IO=Data&(0x01<<i);
因为时钟脉宽是ns级别,而51单片机运行速度慢,一个机器周期是1微妙,即运行一行代码需要1微妙,所以在SCLK=1和SCLK=0之间可以不加延时。若单片机运行速度很快,必须加延时。
读时序 (读取DS1302数据,需要先确定哪个寄存器,再读取数据)
读寄存器数据与写入有很大不同 观察时序图发现,读数据时只有15个脉冲。这是因为输入数据是上升沿,输出数据是下降沿。先确定哪个寄存器,应该是写入数据,若依照写数据代码,先SCLK=1;(上升沿写入)再SCLK=0; 会发现第一个for循环最后一次0导致时钟芯片输出了一位数据(下降沿输出),造成读写操作不连贯,我们目的只是写入数据确定哪个寄存器。读数据代码还没有作用。
for(i=0;i<8;i++){DS1302_IO=command&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}for(i=0;i<8;i++){DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}
此时第一个for循环改为先SCLK=0;再SCLK=1;循环8次就写入了一个字节指令,确定是哪个寄存器(8个脉冲)。
然后第二个for循环写SCLK=1;相当于将SCLK=1脉宽变大了,不影响时序,只是为了满足15个脉冲,这里赋值操作最关键,需认真理解。此时再将SCLK=0;读出第一位数据。循环8次则读出8位数据,也满足15个脉冲。**
for(i=0;i<8;i++){DS1302_IO=command&(0x01<<i);DS1302_SCLK=0;DS1302_SCLK=1;//写入数据,即上升沿到来}for(i=0;i<8;i++){DS1302_SCLK=1;//很关键,将写命令的第8个脉冲宽度延长,满足15个脉冲DS1302_SCLK=0;//读取DS1302数据,下降沿输出if(DS1302_IO==1) //当数据输出为1时,保存下来,第几位就左移几位Data|=(0x01<<i);//输出为0不用处理}
二、BCD码转十进制解读
BCD码 用4位二进制数表示1位十进制数
DS1302寄存器默认使用BCD码存储数据
0001 0011表示13 0010 0101表示25 0001 1010不合法因为后四位10在十进制个位里面没有10
BCD码转十进制 DEC=BCD/1610+BCD%16; (两位BCD)
十进制转BCD码 BCD=DEC/1016+DEC%10; (两位BCD)
这里很关键,不然10会显示16,下面解释为何显示16
由于读取寄存器返回的是BCD码,0X10十进制是16,所以将BCD转为10进制。BCD/16*10+BCD%16 很好理解。BCD码将10变成16,因此先除以16,再乘以10就表示几个10了,这是十位。个位直接对16取余。其实这相当于16的几次方相加,这个几次方对于十进制也是相同的。BCD转十进制,就是求出这个几次方
关于秒显示从9变成16解释说明
LCD_ShowNum(2,1,second,2);
这样写,到9之后加一就显示16
0000 1001这是9,加上1变成10,0001 0000这是10的BCD码。但程序默认转化为十六进制0X10就是十进制16,所以用LCD1602十进制显示函数时显示16。
有初学者一定不明白,写入0X03为何就显示3呢。这就要从寄存器说起了,DS1302寄存器存储数据使用BCD码,0X03表示十进制3,读取寄存器数据就是0X03,所以用LCD1602显示没问题。
但是当秒加到9(0000 1001)(注意芯片秒寄存器最高位为0时,芯片动作,每秒加一),下一秒加到10,由于BCD码,会将1进到第5位 (BIT4位)(0001 0000)此时表示10秒,因为秒寄存器BIT4-7位表示10秒。而0001 0000用十六进制表示16 0X10,读出这个数据显示就是16。
三、Proteus仿真
有关Proteus需要再写
四、详细代码
代码如下(示例):
#include <regx52.h>
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;//LCD1602引脚定义
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
//LCD1602函数
void LCD_Delay();
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
//DS1302函数
void DS1302_Init();
void DS1302_WriteByte(unsigned char command,Data);
unsigned char DS1302_ReadByte(unsigned char command);int main()
{unsigned char second;unsigned char min;unsigned char hour;LCD_Init();DS1302_Init();LCD_ShowString(1,1,"RTC");DS1302_WriteByte(0x80,0x55);//0X55转化为BCD就是55while(1){second=DS1302_ReadByte(0x81);min=DS1302_ReadByte(0X83);hour=DS1302_ReadByte(0X85);LCD_ShowNum(2,7,second/16*10+second%16,2);//BCD转为十进制LCD_ShowChar(2,6,'-');LCD_ShowNum(2,4,min/16*10+min%16,2);LCD_ShowChar(2,3,'-');LCD_ShowNum(2,1,hour/16*10+hour%16,2);}return 0;
}
void DS1302_Init()
{DS1302_CE=0;DS1302_SCLK=0;
}
/**
*@brief DS1302Ð写入命令和数据
*@param 命令确定哪个寄存器
*@retval
*/
void DS1302_WriteByte(unsigned char command,Data)
{int i;DS1302_CE=1;for(i=0;i<8;i++){DS1302_IO=command&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}for(i=0;i<8;i++){DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}DS1302_CE=0;
}
/**
*@brief DS1302读一个字节
*@param
*@retval
*/
unsigned char DS1302_ReadByte(unsigned char command)
{int i;unsigned char Data=0x00;DS1302_CE=1;for(i=0;i<8;i++){DS1302_IO=command&(0x01<<i);DS1302_SCLK=0;DS1302_SCLK=1;//写入数据,即上升沿到来}for(i=0;i<8;i++){DS1302_SCLK=1;//很关键,将写命令的第8个脉冲宽度延长,满足15个脉冲DS1302_SCLK=0;//读取DS1302数据,下降沿输出if(DS1302_IO==1) //当数据输出为1时,保存下来,第几位就左移几位Data|=(0x01<<i);//输出为0不用处理}DS1302_IO=0;DS1302_CE=0;return Data;}
/*** @brief LCD1602延时,12MHz1ms* @param * @retval */
void LCD_Delay()
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}/*** @brief LCD1602写命令* @param Command * @retval */
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief LCD1602写数据* @param Data * @retval */
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief LCD1602设置RAM指针位置* @param Line :1~2* @param Column :1~16* @retval ?*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));//RAM指针默认最高位为1,从0X00开始}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));//RAM指针从0X40开始}
}/*** @brief LCD1602* @param ?* @retval ?*/
void LCD_Init()
{LCD_WriteCommand(0x38);//LCD1602 显示16*2LCD_WriteCommand(0x0c);//LCD1602开显示光标不亮LCD_WriteCommand(0x06);//LCD1602指针自动加一光标加一LCD_WriteCommand(0x01);//清屏
}
//显示字符
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}
//显示字符串
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{LCD_SetCursor(Line,Column);while(*String!='\0')//指针解引用贼秀{LCD_WriteData(*String++);}
}
/**
*@brief
*@param 返回X的Y次方
*@retval
*/
int LCD_Pow(int X,int Y)
{unsigned char i;int Result=1;for(i=0;i<Y;i++){Result*=X;}return Result;
}/*** @brief LCD1602十进制显示数字* @param Line :1~2* @param Column :1~16* @param Number :0~65535* @param Length :1~5* @retval */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');//涉及ASCLL码,有需要再写}
}# 总结
以上就是今天要讲的内容,本文仅仅简单介绍了51单片机与DS1302结合使用。
51单片机DS1302时钟芯片应用Proteus仿真相关推荐
- (给自己看)51单片机DS1302时钟芯片
老规矩先上DS1302.c的代码 #include <regx52.h>//首先 DS1302_Init(); // DS1302_SetTime();//再在while中DS1302_R ...
- 基于51单片机的八路电压表采集Proteus仿真(源码+仿真+原理图+全套资料)
资料编号:110 程序语言:C语言 仿真软件:Proteus8.9版本 功能讲解如下: 利用单片机及其外围器件(A/D转换器等)实现一款简易电压表,实现以下功能: 1 电压表能够进行8路模拟电压测 ...
- 51单片机12864大液晶屏proteus仿真
51单片机竞赛设计实例程序44例(Proteus仿真资料),可以做参赛设计的参考,可以用来做毕业设计,也可以做项目参考,平时的练习项目,带源码,可以说费了很多时间才集齐的,希望对你们有帮助,闯客网技术 ...
- 基于51单片机智能导盲拐杖Proteus仿真
功能介绍: 采用51单片机作为主控CPU,采用HC-SR04超声波模块测量障碍物距离,LCD1602显示屏显示当前的障碍物距离,并且可以设置报警的阈值,通过传感器测量障碍物的距离的远近来进行相关报警, ...
- 基于51单片机的自动售货机Proteus仿真(源码+仿真+设计报告)
资料编号:137 视频讲解: 137-基于51单片机的自动售货机Proteus仿真(源码+仿真+设计报告) 功能介绍: 基本原理:通过矩阵键盘来选择货物的种类与数量过后自动售货机提示投币.自动售货机的 ...
- 基于51单片机的简易数字计算器Proteus仿真(源码+仿真+全套资料)
资料编号:115 全套资料齐全,功能说明: 该计算器系统51 系列的单片机进行的数字计算器系统设计,可以完成计算器的键盘输入, 进行加. 减.乘.除的简单四则运算,并在 LCD屏幕上相应的显示结果. ...
- 基于51单片机ds1302时钟、ds18b20、lcd12864的恒温器
目录 项目:基于51单片机ds1302时钟.ds18b20的恒温器 功能说明: 运行流程: 效果展示: 供电方式: 用途: 提高: 附: ...
- 蓝桥杯单片机DS1302时钟芯片驱动代码注释
蓝桥杯单片机DS1302时钟芯片驱动代码之前的疑惑注释了下 /* DS1302 芯片包含一个 实时时钟/日历和 31 字节的静态 RAM. 与时钟/RAM 通讯只需要三根线: CE,I/O (数据线) ...
- 【011】基于51单片机的低频信号发生proteus仿真与实物设计
一.资料内容 (1).基于51单片机的低频信号发生proteus仿真设计一份: (2).基于51单片机的低频信号发生proteus仿真设计keli源代码一份: (3).基于51单片机的低频信号发生A ...
最新文章
- 英伟达发布史上最强GPU,却叫停了自动驾驶车路测
- OCRNet: 目标区域上下文信息的特征表达 | ECCV 2020
- Vue2.0 + ElementUI 手写权限管理系统后台模板(一)——简述
- 架构师已死(转自UML软件工程组织)
- 会员连锁配置以及金额走向
- Java多线程系列(九):CountDownLatch、Semaphore等4大并发工具类详解
- 新疆特岗计算机考试题,2020新疆特岗教师笔试资料领取(小学信息技术)
- linux怎么让cat运行,使用lolcat让你的Linux命令行出现七彩虹
- linux-优化内核参数 /etc/sysctl.conf
- 在crontab中利用scp命令自动备份文件
- 我买了个阿里云服务器并在上面部署了一个项目
- editplus3编辑器颜色修改
- Atitit 学习方法 -------体系化学习方法 Excel 科目,分类,专业 三级分类。。 知识点。。 课程就是每一个知识点的详细化。。 比如经济学 类别	专业	xx概论知识点 3、金
- pycharm 无法安装模块 nothing to show
- 安卓蓝牙USB连接热敏打印机二
- 使用Pytorch来拟合函数
- 计算机科学中的计算机思维在本质上源自于,计算思维对学习计算机知识有何作用?...
- android 平板怎么截图,平板电脑怎样截图
- 希捷硬盘无法安全弹出如何解决?
- android api 和版本对应表汇总