首先,DS1302数据读写时序如下图:
51单片机上的程序见附件,将其移植到CC3200上需要做的工作:
1.选择合适的GPIO作为SCLK、I/0、RST,本人选用PIN_50:SCLK(7脚)、PIN_59:I/O(6脚)、PIN_15:RST(5脚),配置相关引脚,定义引脚操作,如下所示:
//RST脚 PIN_15
#define RST_OUT MAP_GPIODirModeSet(GPIOA2_BASE, 0x40, GPIO_DIR_MODE_OUT)//SET RST OUTPUT
#define RST_SET MAP_GPIOPinWrite(GPIOA2_BASE,0x40,0x40)//置高PIN_15
#define RST_CLR MAP_GPIOPinWrite(GPIOA2_BASE,0x40,0) //拉低PIN_15
//I/O引脚 PIN_59
#define IO_OUT MAP_GPIODirModeSet(GPIOA0_BASE, 0x10, GPIO_DIR_MODE_OUT)//SET DSIO OUTPUT
#define IO_SET MAP_GPIOPinWrite(GPIOA0_BASE,0x10,0x10)//置高PIN_59
#define IO_CLR MAP_GPIOPinWrite(GPIOA0_BASE,0x10,0)//拉低PIN_59
#define IO_IN MAP_GPIODirModeSet(GPIOA0_BASE, 0x10, GPIO_DIR_MODE_IN)//SET DSIO INPUT
#define IO_Read MAP_GPIOPinRead(GPIOA0_BASE,0x10)
//SCLK引脚 PIN_50
#define SCLK_OUT MAP_GPIODirModeSet(GPIOA0_BASE, 0x1, GPIO_DIR_MODE_OUT)//SET SCLK OUTPUT
#define SCLK_SET MAP_GPIOPinWrite(GPIOA0_BASE,0x1,0x1)//置高PIN_50
#define SCLK_CLR MAP_GPIOPinWrite(GPIOA0_BASE,0x1,0)//拉低PIN_50
2.将原始延时函数_nop_()替换掉,由于对延时要求不高,所以直接使用UtilsDelay(1),正常的1us延时应该是改为UtilsDelay(27),计算过程见博客《CC3200中1us延时的实现》;
3.读取I/O数据时,若引脚为高电平,则通过函数MAP_GPIOPinRead(GPIOA0_BASE,0x10)读取到的值为引脚的位权,PIN_59引脚读取到的值便为0x10,此时需要对数据进行处理,我采用的简便方法如下:
dat1=IO_Read;
if(dat1)
{
dat1=0x01;
}
else
{
dat1=0x0;
}
也可以定义函数进行统一的操作,函数如下(同学写的,未亲测):
至此,就可以成功通过CC3200读取到DS1302的时间数据。
移植过程中出现的问题:最大的一个问题是一开始读取到的TIME数组的数据都为0,排查许久后才发现原因,就是读取到的某个引脚的高电平不是1,而是该引脚的位权;另外,要注意选择合适的引脚,当初将PIN_60作为RST,结果不成功,应该是引脚复用的问题。
未经许可,严禁转载!
附件1(ds1302_51.h):
#ifndef __DS1302_H_
#define __DS1302_H_
//---包含头文件---//
#include<reg51.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//---定义ds1302使用的IO口---//
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;
//---定义全局函数---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局变量--//
extern uchar TIME[7]; //加入全局变量
#endif
附件2(ds1302_51.c):
#include"ds1302.h"
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0x10, 0x12, 0x02, 0x02, 0x02, 0x13};
/*******************************************************************************
* 函 数 名 : Ds1302Write
* 函数功能 : 向DS1302命令(地址+数据)
* 输 入 : addr,dat
* 输 出 : 无
*******************************************************************************/
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
/*******************************************************************************
* 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/*******************************************************************************
* 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00);//禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80);//打开写保护功能
}
/*******************************************************************************
* 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
附件3(ds1302_3200.h):
/*
* ds1302.h
*
* Created on: 2016年4月26日
* Author: Bug
*/
/*DS1302
*PIN_50:SCLK(7脚)
*PIN_59:I/O(6脚)
*PIN_15:RST(5脚)
*/
#ifndef DS1302_H_
#define DS1302_H_
#include "includes.h"
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//RST脚 PIN_15
#define RST_OUT MAP_GPIODirModeSet(GPIOA2_BASE, 0x40, GPIO_DIR_MODE_OUT)//SET RST OUTPUT
#define RST_SET MAP_GPIOPinWrite(GPIOA2_BASE,0x40,0x40)//置高PIN_15
#define RST_CLR MAP_GPIOPinWrite(GPIOA2_BASE,0x40,0) //拉低PIN_15
//I/O引脚 PIN_59
#define IO_OUT MAP_GPIODirModeSet(GPIOA0_BASE, 0x10, GPIO_DIR_MODE_OUT)//SET DSIO OUTPUT
#define IO_SET MAP_GPIOPinWrite(GPIOA0_BASE,0x10,0x10)//置高PIN_59
#define IO_CLR MAP_GPIOPinWrite(GPIOA0_BASE,0x10,0)//拉低PIN_59
#define IO_IN MAP_GPIODirModeSet(GPIOA0_BASE, 0x10, GPIO_DIR_MODE_IN)//SET DSIO INPUT
#define IO_Read MAP_GPIOPinRead(GPIOA0_BASE,0x10)
//SCLK引脚 PIN_50
#define SCLK_OUT MAP_GPIODirModeSet(GPIOA0_BASE, 0x1, GPIO_DIR_MODE_OUT)//SET SCLK OUTPUT
#define SCLK_SET MAP_GPIOPinWrite(GPIOA0_BASE,0x1,0x1)//置高PIN_50
#define SCLK_CLR MAP_GPIOPinWrite(GPIOA0_BASE,0x1,0)//拉低PIN_50
//---定义全局函数---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局变量--//
extern uchar TIME[7]; //加入全局变量
#endif /* DS1302_H_ */
附件4(ds1302_3200.c):
/*
* DS1302.c
*
* Created on: 2016年4月26日
* Author: Bug
*/
#include"ds1302.h"
#define Delay_1us UtilsDelay(1)
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0x10, 0x12, 0x02, 0x02, 0x02, 0x13};
/*******************************************************************************
* 函 数 名 : Ds1302Write
* 函数功能 : 向DS1302命令(地址+数据)
* 输 入 : addr,dat
* 输 出 : 无
*******************************************************************************/
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
// RST = 0;
RST_CLR;
// _nop_();
Delay_1us;
// SCLK = 0;//先将SCLK置低电平。
SCLK_CLR;
// _nop_();
Delay_1us;
// RST = 1; //然后将RST(CE)置高电平。
RST_SET;
// _nop_();
Delay_1us;
for (n=0; n<8; n++)//开始传送八位地址命令
{
// DSIO = addr & 0x01;//数据从低位开始传送
if(addr & 0x01)
IO_SET;
else
IO_CLR;
addr >>= 1;
// SCLK = 1;//数据在上升沿时,DS1302读取数据
SCLK_SET;
// _nop_();
Delay_1us;
// SCLK = 0;
SCLK_CLR;
// _nop_();
Delay_1us;
}
for (n=0; n<8; n++)//写入8位数据
{
// DSIO = dat & 0x01;
if(dat & 0x01)
IO_SET;
else
IO_CLR;
dat >>= 1;
// SCLK = 1;//数据在上升沿时,DS1302读取数据
SCLK_SET;
// _nop_();
Delay_1us;
// SCLK = 0;
SCLK_CLR;
// _nop_();
Delay_1us;
}
// RST = 0;//传送数据结束
RST_CLR;
// _nop_();
Delay_1us;
}
/*******************************************************************************
* 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
// RST = 0;
RST_CLR;
// _nop_();
Delay_1us;
// SCLK = 0;//先将SCLK置低电平。
SCLK_CLR;
// _nop_();
Delay_1us;
// RST = 1;//然后将RST(CE)置高电平。
RST_SET;
// _nop_();
Delay_1us;
for(n=0; n<8; n++)//开始传送八位地址命令
{
// DSIO = addr & 0x01;//数据从低位开始传送
if(addr & 0x01)
IO_SET;
else
IO_CLR;
addr >>= 1;
// SCLK = 1;//数据在上升沿时,DS1302读取数据
SCLK_SET;
// _nop_();
Delay_1us;
// SCLK = 0;//DS1302下降沿时,放置数据
SCLK_CLR;
// _nop_();
Delay_1us;
}
// _nop_();
Delay_1us;
IO_IN;
for(n=0; n<8; n++)//读取8位数据
{
// dat1 = DSIO;//从最低位开始接收
dat1=IO_Read ;
if(dat1)
{
// UART_PRINT("dat1=%x\n\r",dat1);
dat1=0x01;
}
else
{
dat1=0x0;
}
dat = (dat>>1) | (dat1<<7);
// SCLK = 1;
SCLK_SET;
// _nop_();
Delay_1us;
// SCLK = 0;//DS1302下降沿时,放置数据
SCLK_CLR;
// _nop_();
Delay_1us;
}
// RST = 0;
RST_CLR;
// _nop_(); //以下为DS1302复位的稳定时间,必须的。
Delay_1us;
// SCLK = 1;
SCLK_SET;
// _nop_();
Delay_1us;
IO_OUT;
// DSIO = 0;
IO_CLR;
// _nop_();
Delay_1us;
// DSIO = 1;
IO_SET;
// _nop_();
Delay_1us;
// UART_PRINT("dat=%x\n\r",dat);
return dat;
}
/*******************************************************************************
* 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00);//禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80);//打开写保护功能
}
/*******************************************************************************
* 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
RST_OUT;
IO_OUT;
SCLK_OUT;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}