DS1302与51单片机的问题,大家来帮我看看这个程序吧...不知道哪儿出错了读到的数据总是0xff......求指教!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DS1302与51单片机的问题,大家来帮我看看这个程序吧...不知道哪儿出错了读到的数据总是0xff......求指教!相关的知识,希望对你有一定的参考价值。

#include<reg52.h>
#include<DS1302.h>
#define uint unsigned int
#define uchar unsigned char
#define WRITE_SECOND 0x80
#define WRITE_MINUTE 0x82
#define WRITE_HOUR 0x84
#define WRITE_DATE 0x86
#define WRITE_MONTH 0x88
#define WRITE_WEEKDAY 0x8A
#define WRITE_YEAR 0x8C
#define READ_SECOND 0x81
#define READ_MINUTE 0x83
#define READ_HOUR 0x85
#define READ_DATE 0x87
#define READ_MONTH 0x89
#define READ_WEEKDAY 0x8B
#define READ_YEAR 0x8D
#define WRITE_PROTECT 0x8E

sbit Qian_Wei=P1^0;
sbit Bai_Wei=P1^1;
sbit Shi_Wei=P2^3;
sbit Ge_Wei=P2^6;

uchar code table[]=
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e;

sbit ACC_7 = ACC^7;
sbit SCLK = P3^5;
sbit DIO = P3^6;
sbit RET = P3^4;

void delay(uint z)

uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);


void Write1302(uchar addr,dat)

uchar counter,temp;
RET=0;
SCLK=0;
RET=1;
for(counter=8;counter>0;counter--) //发送地址

SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01);
addr>>=1;
SCLK=1;

for(counter=8;counter>0;counter--) //发送数据

SCLK=0;
temp=dat;
DIO=(bit)(temp&0x01);
dat>>=1;
SCLK=1;

RET=0;


uchar Read1302(uchar addr)

uchar counter,temp,dat1,dat2;
RET=0;
SCLK=0;
RET=1;
for(counter=8;counter>0;counter--) //发送地址

SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01);
addr>>=1;
SCLK=1;

for(counter=7;counter>0;counter--) //读取数据

SCLK=1;
SCLK=0;
ACC_7=DIO;
ACC>>=1;

SCLK=1;
SCLK=0;
ACC_7=DIO;
RET=0;
dat1=ACC;
dat2=dat1>>4; //BCD转十进制
dat1=dat1&0x0f;
dat1=dat1+dat2*10;
return dat1;


void init()

Write1302(WRITE_PROTECT,0X00);
Write1302(WRITE_SECOND,0X56);
//Write1302(WRITE_PROTECT,0X80);


void display(uchar qian,uchar bai,uchar shi,uchar ge)

P0=table[ge];
Ge_Wei=0;
delay(5);
Ge_Wei=1;
P0=0xff;

P0=table[shi];
Shi_Wei=0;
delay(5);
Shi_Wei=1;
P0=0xff;

P0=table[bai];
Bai_Wei=0;
delay(5);
Bai_Wei=1;
P0=0xff;

P0=table[qian];
Qian_Wei=0;
delay(5);
Qian_Wei=1;
P0=0xff;


void main()

uchar num,ge,shi,bai,qian;
init();
while(1)

num=Read1302(READ_SECOND);
qian=num/1000;
bai=num%1000/100;
shi=num%100/10;
ge=num%10;
display(qian,bai,shi,ge);

参考技术A void Write1302(uchar addr,dat)

uchar counter,temp;
RET=0;
SCLK=0;
RET=1;
for(counter=8;counter>0;counter--) //发送地址

SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01);
addr>>=1;
SCLK=1;

for(counter=8;counter>0;counter--) //发送数据

SCLK=0;
temp=dat;
DIO=(bit)(temp&0x01);
dat>>=1;
SCLK=1;

RET=0;


RET=0;不能一直为底追问

什么意思?我该怎么改呢?

参考技术B 我有DS1302在LCD1602上显示的程序,需要不?DS1302主要就是IIC的写法,,尤其是读数据的时候需要注意追问

不用了~多谢了,刚调试出来

参考技术C 程序不想看了,不过要提醒一下1302的数据口要接上啦电阻,一共是三个吧

蓝桥杯单片机设计与开发_基础模块_DS18B20

一、前言

从今天开始,笔者将向大家逐一讲解蓝桥杯的大部分竞赛模块,笔者将基于上一篇文章(蓝桥杯单片机设计与开发_标准模板)中讲解的标准模板编写程序。按照顺序(DS18B20、DS1302、PCF8591、AT24C02、PWM、串口通信、NE555以及超声波测距),为大家做出详细编程指导。

二、DS18B20 温度传感器

DS18B20 又叫温度传感器。笔者将基于蓝桥杯官方给的赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包)进行编程,为大家讲解编程调用各语句的含义,帮助大家编写温度传感器的程序,也便于大家记忆。

1、导入底层驱动代码

首先,创建工程和导入.c文件笔者已在文章(蓝桥杯单片机设计与开发_标准模板)中向大家详细介绍了,这里就不再赘述。
读者可下载赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包),解压后可得到以下图片所示文件。

我们双击打开文件“3-底层驱动代码参考”文件,将得到以下.c.h文件。接下来将包含DS18B20 的文件onewire.c 和 onewire.h 文件拷贝到工程所在文件夹中。

然后双击工程中 Source Group 1,将这两个文件导入,便可以开始编写程序了。

2、DS18B20驱动函数

首先,在编写驱动函数之前,我们需要对底层驱动代码 onewire.c 中的延迟函数 Delay_OneWire() 做出修改,将延迟时间增大 12 倍!。因为比赛使用的IAP15系列单片机速度比STC89C52系列单片机速度快12倍,如果不改时序上将出现问题,无法正常读取温度。
笔者采用一个 for 循环,在 while 循环中重复循环 12 次,达到延迟效果。

void Delay_OneWire(u16 t)  //STC89C52RC

	u8 num;                             //定义计数变量
	while(t--)
		for(num = 0;num <= 12;num++);     //延迟时长扩大12倍

接下来,就开始在 onewire.c 文件中编写温度读取函数。我们可以打开赛点资源数据包中的文件“5-竞赛板芯片资料”。


打开“DS18B20”芯片手册。笔者将借助芯片手册中的资料编写温度读取函数并为大家讲解。

温度读取函数:在编写温度读取函数时,我们只需要通过调用底层驱动函数中的初始化、写入、读取函数。

int rd_temperature(void)   //读取温度函数

	int temp = 0;            //定义温度读取返回值
	u8 tmh,tml;              //定义温度读取高八位和第八位
	
    init_ds18b20();          //设备初始化
	Write_DS18B20(0xcc);     //跳过ROM地址指令
	Write_DS18B20(0x44);     //安装温度转换指令
	
	init_ds18b20();
	Write_DS18B20(0xcc);     //跳过ROM地址指令
	Write_DS18B20(0xbe);     //安装温度读取指令
	
	tml=Read_DS18B20();      //读取低八位
	tmh=Read_DS18B20();      //读取高八位
	
	//将温度高八位和低八位组合成16位int类型
	temp = tmh;
	temp <<= 8;
	temp |= tml;
	
	return temp;             //返回温度读取值

其中,在写入函数 Write_DS18B20() 写入的指令可通过查阅芯片资料手册,不需要死记硬背。


在编写完温度传感器驱动函数后务必要在 onewire.h 文件中声明函数,才可在主函数中调用。

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

int rd_temperature();      //声明函数

#endif

3、主函数调用

在主函数中调用温度传感器驱动函数,首先需要在主函数开头包含驱动 DS18B20 驱动函数的头文件。

#include "STC15F2K60S2.h"   //头文件
#include "onewire.h"        //包含DS18B20驱动头文件

温度数值转换函数
编写温度数据转换函数需要注意的是:读取温度数值需要再乘以 0.0625 转换成十进制温度值。笔者将读取温度值读取到小数点后四位,采用的方法是将乘以 0.0625 后的数据放大 10000 倍,再通过取余除数的方法得到各位小数值。因数值放大到百万级别,因此需要定义长整型数值。
得到各位数后,通过改变缓冲区 dspbuf 的数值,在数码管1~7中显示读取到的温度数值。

void datachange(long int temp)     //读取温度数据转换函数

	temp = temp*0.0625*10000;        //放大10000倍,读取小数点后四位
                    
	dspbuf[1] = temp/1000000;            //取温度的百位数
	dspbuf[2] = temp%1000000/100000;     //取温度的十位数
	dspbuf[3] = temp%100000/10000+11;    //取温度个位数并加上小数点
	dspbuf[4] = temp%10000/1000;         //取温度的小数点第一位
	dspbuf[5] = temp%1000/100;           //取温度的小数点第二位
	dspbuf[6] = temp%100/10;             //取温度的小数点第三位
	dspbuf[7] = temp%10;                 //取温度的小数点第四位

除此之外,笔者将个位数后的小数点显示出来,采取的方法是在定义 tab 数组时,在后面再定义十个小数点点亮的数,即通过将 0~9 对应的高八位减去 8,即可点亮小数点 dp 位。再在数码管显示的缓冲区上加上 11,即可显示带小数点的数字。

u8 code tab[] = 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10;   //定义数组存放数码管数字状态

中断函数
笔者在中断函数中定义每 50ms 产生一次中断,将温度读取标志位置 1,进行温度读取。

bit temp_flag = 0;     //定义温度读取标志位
void timer0() interrupt 1    //定义中断模式1

	static u8 t_20ms = 0;      //定义静态变量计时20ms
	static u8 t_50ms = 0;      //定义静态变量计时50ms
	
	display();                 //数码管显示函数
	
	t_20ms++;                  //计数自增
	t_50ms++;                  //计数自增
	
	if(t_20ms >= 10)           //判断计时时间
	
		t_20ms = 0;              //计数清零
		key_flag = 1;            //按键标志位置1
	
	
	if(t_50ms >= 10)           //判断计时时间
	
		t_50ms = 0;              //计数清零
		temp_flag = 1;           //温度标志位置1
	

main主函数
笔者在主函数开头中定义温度读取开关变量 temp_w,通过与 1 异或,可实功能:按一次 S4 打开温度传感器,每 50ms 读取一次温度;再按一次 S4 关闭温度传感器。

void main()      //主函数

	u8 key_re;     //定义变量读取按键返回值
	u8 temp_w = 0; //定义温度读取开关变量
	
	all_init();    //初始化函数
	Timer0Init();  //定时器0初始化
	
	while(1)
	
		if(key_flag)            //每20ms扫描一次按键
		
			key_flag = 0;         //标志位置0
			key_re = Read_key();  //读取按键
			 
			if(key_re != 0xff)    //判断按键是否按下
			
				//判断按键
				switch(key_re)
				
					//放入需要执行的功能
					case 4: temp_w ^= 1;break;  //按一次按键打开/关闭温度传感器
				
			
		
		
		if((temp_w) && (temp_flag))    //定义温度读取函数
		
			temp_flag = 0;               //清空标志位
			datachange(rd_temperature());  //调用温度读取及转换函数
		
	

至此,本次 DS18B20 温度传感器程序已编写完毕。由于笔者近期事情比较多,更新文章较慢,请各位见谅。接下来几天笔者也将尽量早点将各个模块的编程都更新完毕!欢迎读者在评论区交流!!

以上是关于DS1302与51单片机的问题,大家来帮我看看这个程序吧...不知道哪儿出错了读到的数据总是0xff......求指教!的主要内容,如果未能解决你的问题,请参考以下文章

求lm016l与ds1302 52 单片机实现时钟显示的程序

51单片机 DS1302时钟演示+Proteus仿真

ds1302怎么接单片机

51单片机DS1302+ DS18b20+LCD1602时钟仿真

既然单片机本身有定时器,为啥还需要采用DS1302来定时呢,DS1302的优点是啥呢?

51单片机对DS1302(实时时钟芯片)的仿真