实验开发板为CT107D蓝桥官方板,编译环境为MDK5
采用蓝桥官方驱动改写
目录
一、DS1302时钟芯片
二、DS18B20温度传感器
- SCLK:串行时钟,输入,控制数据的输入与输出;
- I/O:三线接口时的双向数据线;
- CE:输入信号,在读、写数据期间,必须为高。
DS1302的使用主要在于看懂和掌握时序图
第一个字节的数据的第一位:1(读)2(写)
下图为各类数据的地址以及传输的格式(输入输出均用BCD码):
注意:年只有后两位,格式为20xx年。
DS1302具有Burst模式可顺序读或写日历和时间数据而跳过写地址步骤 :
当启用该模式后DS1302会通过数据线按:秒,分,时,日,月,星期,年的顺序输出。
main.h:
#ifndef _MAIN_H
#define _MAIN_H
#include "STC15F2K60S2.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#endif
ds1302.h:
#ifndef __DS1302_H__
#define __DS1302_H__
#include "main.h"
#include
/********************************************************************/
sbit SCK=P1^7;
sbit SD=P2^3;
sbit RST=P1^3;
/********************************************************************/
/*复位脚*/
#define RST_CLR RST=0 /*电平置低*/
#define RST_SET RST=1 /*电平置高*/
/*双向数据*/
#define SDA_CLR SD=0 /*电平置低*/
#define SDA_SET SD=1 /*电平置高*/
#define SDA_R SD /*电平读取*/
/*时钟信号*/
#define SCK_CLR SCK=0 /*时钟信号*/
#define SCK_SET SCK=1 /*电平置高*/
/********************************************************************/
#define ds1302_sec_addr 0x80 //秒数据地址
#define ds1302_min_addr 0x82 //分数据地址
#define ds1302_hr_addr 0x84 //时数据地址
#define ds1302_date_addr 0x86 //日数据地址
#define ds1302_month_addr 0x88 //月数据地址
#define ds1302_day_addr 0x8A //星期数据地址
#define ds1302_year_addr 0x8C //年数据地址
#define ds1302_control_addr 0x8E //写保护命令字单元地址
#define ds1302_charger_addr 0x90 //涓电流充电命令字地址
#define ds1302_clkburst_addr 0xBE //日历、时钟突发模式命令字地址
/********************************************************************/
extern u8 Time[7];
typedef struct time{
u16 year;
u8 mon;
u8 day;
u8 hour;
u8 min;
u8 sec;
u8 week;
}Stime;
/********************************************************************/
/*单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/
/*单字节读出一字节数据*/
extern unsigned char Read_Ds1302_Byte(void);
/********************************************************************/
/********************************************************************/
/*向DS1302单字节写入一字节数据*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
extern void DS1302BurstWrite(unsigned char *dat);
extern void DS1302BurstRead(unsigned char *dat);
extern void Init_DS1302();
//extern void DS1302_TimeIn(Stime *time);
//extern void DS1302_TimeOut(Stime *time);
#endif
/********************************************************************/
// END FILE
/********************************************************************/
ds1302.c:
#include "ds1302.h"
#include "main.h"
/********************************************************************/
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*电平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*电平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/********************************************************************/
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/
Write_Ds1302_Byte(dat); /*写入数据:dat*/
RST_CLR; /*停止DS1302总线*/
}
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/
RST_CLR; /*停止DS1302总线*/
return temp;
}
void DS1302BurstWrite(u8 *dat)
{
u8 i;
RST_SET;
Write_Ds1302_Byte(ds1302_clkburst_addr); //写入Burst模式启动指令
for(i = 0; i < 8; i ++)
{
Write_Ds1302_Byte(*dat ++);
}
RST_CLR;
}
void DS1302BurstRead(u8 *dat)
{
u8 i;
RST_SET;
Write_Ds1302_Byte(0XBF);
for(i = 0; i < 8; i ++)
{
dat[i] = Read_Ds1302_Byte();
}
RST_CLR;
}
void Init_DS1302()
{
u8 Init_Time[] = {
0x50 , 0x59 , 0x23 , 0x16 , 0x03 , 0x06 , 0x19
};
RST_CLR;
SDA_CLR;
Ds1302_Single_Byte_Write(ds1302_control_addr,0x00);
DS1302BurstWrite(Init_Time);
}
新版官方驱动改写(DS1302):
DS1302.h:
#ifndef __DS1302_H
#define __DS1302_H
sbit SCK = P1^7;
sbit SDA_D = P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp);
u8 Read_Ds1302();
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
void DS1302BurstWrite(u8 *Dat);
void DS1302BurstRead(u8 *Dat);
void DS1302Init();
void TimeTranslate();
void TimeDisplay();
u8 HexToBCD(u8 Hex);
u8 BCDToHex(u8 BCD);
#endif
DS1302.c:
#include "Sys.h"
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA_D=temp&0x01;
temp>>=1;
SCK=1;
}
SCK = 0;//记得加上
}
/*******************************/
u8 Read_Ds1302(){
u8 i = 0, temp = 0x00;
for (i=0;i<8;i++) //这段来自于第47行
{
SCK=0;
temp>>=1;
if(SDA_D)
temp|=0x80;
SCK=1;
}
SCK = 0;//记得加上
return (temp);
}
/*******************************/
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )//未使用
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA_D)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA_D=0; _nop_();
SDA_D=1; _nop_();
return (temp);
}/*******************************/
/**************************************************************************
函数功能:DS1302Burst写
入口参数:待写入数组地址
返回值 :无
**************************************************************************/
void DS1302BurstWrite(u8 *Dat){
u8 index = 0;
RST = 1;
Write_Ds1302(0xBE); //写Burst写指令
for(index = 0 ; index < 8; index ++){
//读数据
Write_Ds1302(Dat[index]);
}
RST = 0;
}
/**************************************************************************
函数功能:DS1302Burst读
入口参数:时间存储数组地址
返回值 :无
**************************************************************************/
void DS1302BurstRead(u8 *Dat){
u8 index = 0;
RST = 1;
Write_Ds1302(0xBF); //写Burst读指令
for(index = 0 ; index < 8; index ++){
//读数据
Dat[index] = Read_Ds1302();
}
RST = 0;
}
/**************************************************************************
函数功能:DS1302时间初始化
入口参数:无
返回值 :无
**************************************************************************/
void DS1302Init(){
u8 InitTime[] = { //2019年12月12日 星期四 10:00:00
0x00,0x00,0x10, 0x12, 0x12, 0x04, 0x19
};//秒 分 时 日 月 周 年
RST = 0;
SDA_D = 0;
Write_Ds1302_Byte(0x8E,0x00); //撤销写保护
DS1302BurstWrite(InitTime);
}
/**************************************************************************
函数功能:时间读取
入口参数:无
返回值 :无
**************************************************************************/
void TimeTranslate(){
u8 Time[7] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
DS1302BurstRead(Time);
LocalTime.Sec = Time[0];
LocalTime.Minu = Time[1];
LocalTime.Hour = Time[2];
LocalTime.Day = Time[3];
LocalTime.Month = Time[4];
LocalTime.Week = Time[5];
LocalTime.Year = Time[6];
}
/**************************************************************************
函数功能:将实时时间加载到数码管缓冲区
入口参数:无
返回值 :无
**************************************************************************/
void TimeDisplay(){
TimeTranslate();
SMG_Buff[0] = SMG[LocalTime.Hour >> 4];
SMG_Buff[1] = SMG[LocalTime.Hour & 0x0F];
SMG_Buff[2] = 0xBF;//-
SMG_Buff[3] = SMG[LocalTime.Minu >> 4];
SMG_Buff[4] = SMG[LocalTime.Minu & 0x0F];
SMG_Buff[5] = 0xBF;
SMG_Buff[6] = SMG[LocalTime.Sec >> 4];
SMG_Buff[7] = SMG[LocalTime.Sec & 0x0F];
}
/**************************************************************************
函数功能:十六进制数转BCD码
入口参数:十六进制数
返回值 :BCD码
**************************************************************************/
//u8 HexToBCD(u8 Hex){
// u8 BCD;
// BCD = Hex/10;
// BCD <<= 4;
// BCD |= Hex % 10;
//
// return BCD;
//}
/**************************************************************************
函数功能:BCD码转十六进制数
入口参数:BCD码
返回值 :十六进制数
**************************************************************************/
//u8 BCDToHex(u8 BCD){
// u8 Hex;
// Hex = (BCD >> 4)*10 + (BCD & 0x0F);
//
// return Hex;
//}
/*******************************/
—————————————————————————————————————————————————
由于DS18B20只有一条总线,数据和指令都从这条总线上传输,所以对时间有及其严格的要求
对应于ds18B20.c中的“Start_DS18B20”函数
数据读写时序:
ds18b20.h:
#ifndef _ONEWIRE_H
#define _ONEWIRE_H
#include "main.h"
#define OW_SKIP_ROM 0xcc //每次使用都需要写入
#define DS18B20_CONVERT 0x44 //启动温度转换
#define DS18B20_READ 0xbe //读取指令
//IC引脚定义
sbit DQ = P1^4;
//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
extern bit Start_DS18B20();
#endif
ds18b20.c:
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台
日 期: 2011-8-9
*/
#include "onewire.h"
#include "main.h"
#include "intrins.h"
//单总线延时函数
u8 i;
void Delay_OneWire(unsigned int t) //约等于延时1us
{
do{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(-- t);
}
//DS18B20芯片初始化
bit Init_DS18B20(void) //每次获取温度都需要初始化
{
bit initflag = 0;
EA = 0;
//DQ = 1;
//Delay_OneWire(12);
DQ = 0;
Delay_OneWire(500);
DQ = 1;
Delay_OneWire(60);
initflag = DQ;
//Delay_OneWire(5);
while(!DQ);
EA = 1;
return initflag;
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;
Delay_OneWire(2); //*
DQ = dat&0x01; //如果写1就拉高,0则拉低
Delay_OneWire(60);
DQ = 1;
dat >>= 1;
}
//Delay_OneWire(5);
EA = 1;
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;
// Delay_OneWire(2); //*
dat >>= 1; //使第一位置0
DQ = 1;
if(DQ) //读取第一位
{
dat |= 0x80;
}
Delay_OneWire(60); //一位数据的读写要超过60us
}
EA = 1;
return dat;
}
bit Start_DS18B20()
{
bit ack;
ack = Init_DS18B20();
if(ack == 0)
{
Write_DS18B20(OW_SKIP_ROM);
Write_DS18B20(DS18B20_CONVERT);
}
return ~ack;
}
//另外插入温度的数据处理函数(零下温度未处理)
void Temp_Get() //温度获取
{
bit Ack;
u8 LSB , MSB, index;
u16 temp;
Ack = Init_DS18B20();
if(Ack == 0)
{
Write_DS18B20(OW_SKIP_ROM); //跳过器件选取(ds18b20是可以挂载多个的,由于只用一个所以跳过器件的选取)
Write_DS18B20(DS18B20_READ); //温度读取指令
LSB = Read_DS18B20(); //
MSB = Read_DS18B20();
temp = ((int)MSB << 8) + LSB;
temp >>= 4; //舍弃小数
for(index = 7; index >= 3; index --)
Led_DataBuff[index] = 0xFF; //格式转换
Led_DataBuff[2] = SMG[temp / 10];
Led_DataBuff[1] = SMG[temp % 10];
Led_DataBuff[0] = 0xC6;
}
Start_DS18B20(); //再次启动温度转换模式
}
新版官方驱动改写(One-Wire):
//*************************ONEWIRE**********************//
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "config.h"
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit Start_DS18B20();
bit init_ds18b20(void);
void Temp_Get();
#endif
--------------------------------------------------------
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //IAP15F2K61S2
{
t = t * 7;
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
EA = 1;
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
EA = 1;
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
bit Start_DS18B20()
{
bit ack;
ack = init_ds18b20();
if(!ack)
{
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
}
return ~ack;
}
bit Config_DS18B20()
{
bit ack;
ack = Start_DS18B20();
if(ack == 0)
{
Write_DS18B20(0xCC);
Write_DS18B20(0x4E);//写暂存器指令4E
Write_DS18B20(0x4B);//写高速缓存器TH高温限值75度
Write_DS18B20(0x00);//写高速缓存器TL低温限值0度
Write_DS18B20(0x1F);//写配置寄存器4
//0x1f : 0.5000°C 转换时间93.75ms
//0x3f : 0.2000°C 转换时间187.5ms
//0x5f : 0.1250°C 转换时间375ms
//0x7f : 0.0625°C 转换时间750ms
}
return ~ack;
}
/************FOR_DATA***********/
void Temp_Get()
{
bit ack;
u8 LSB , MSB;
u8 index;
int temp;
ack = init_ds18b20();
if(!ack)
{
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
temp = ((int)MSB << 8) + LSB;
temp >>= 4;
for(index = 0; index < 5; index ++)
{
SMG_Buff[index] = 0xFF;
}
SMG_Buff[5] = SMG_Data[temp / 10];
SMG_Buff[6] = SMG_Data[temp % 10];
SMG_Buff[7] = 0xC6;
}
Start_DS18B20();
}