DS1302时钟 STM32移植

13 篇文章 7 订阅
                                        DS1302时钟  STM32移植

原来自己画板子做了一个点阵屏。现在想把它用来显示时间,于是就移植了这个DS1302,为什么不用DS3231,因为便宜,我有。我这个带网络校正时间的,所以精度要求不高,DS1302足够。

在移植的时候遇到了几个问题,首先是把STC8A的程序放带STM32里读不出来数据,一直 显示ff。考虑到是IO管脚即要输入又要输出。这个需要配置。

配置之后继续读发现可以读出来数据了,但是有的是对的,有的是错的。也就是说数据乱码的,首先考虑的是时序的问题,再三检查之后确定程序没问题。最后发现是配置输入输出的时候的问题。

读不出来数据即读出来是0xff ?
答: 配置输入输出模式。

void DS1302_IO_OUT(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;                       //定义一个设置IO的结构体
	
	RCC_APB2PeriphClockCmd(DS1302_Port_RCC,ENABLE);    //使能PB端口时钟
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;                 //准备设置PB4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   		   //上拉输入,默认状态是高电平
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度
	GPIO_Init(GPIOB, &GPIO_InitStructure);            		   //设置PB4
}
}
void DS1302_IO_IN(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;                       //定义一个设置IO的结构体
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(DS1302_Port_RCC,ENABLE);    //使能PB端口时钟
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;                 //准备设置PB4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   		   //上拉输入,默认状态是高电平
	//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度
	GPIO_Init(GPIOB, &GPIO_InitStructure);            		   //设置PB4
}
}

这是一种配置方法,还有一种是寄存器配置,更简单。

#define DS1302_DAT_INPUT()     {GPIOB->CRL&= 0X0FFFFFFF;GPIOB->CRL|= 0x80000000;}  //输入
#define DS1302_DAT_OUTPUT()    {GPIOB->CRL&= 0X0FFFFFFF;GPIOB->CRL|= 0x30000000;}  //输出

读出来的数据是1S正确1S错误?
答: 这种情况我百度搜的说是要把三个引脚各加1个10K的上拉电阻,我用面包板接上之后发现没有变化,最后发现在管脚初始化的时候要配置为开漏(GPIO_Mode_Out_OD)。 我是只在IO这个管脚接一个10K电阻,然后配置为开漏模式,而不是原来的推挽。

现在读出来数据正常。
贴几张图片。

在这里插入图片描述
在这里插入图片描述

下面给出代码:
DS1302.h

#ifndef DS1302
#define DS1302

#define DS1302_Port_RCC RCC_APB2Periph_GPIOB //时钟
#define DS1302_PIN GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9 //引脚
#define DS1302_PORT GPIOB //端口

#define DS1302_IO_IN_STA  GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) //PB9控制KEY1,读取电平状态,可以判断KEY1是否按下

#define DS1302_DAT_INPUT()     {GPIOB->CRL&= 0X0FFFFFFF;GPIOB->CRL|= 0x80000000;}  //输入
#define DS1302_DAT_OUTPUT()    {GPIOB->CRL&= 0X0FFFFFFF;GPIOB->CRL|= 0x30000000;}  //输出

#define DS1302_IO PBout(7)  // 数据线
#define DS1302_CE PBout(8)  // 片选
#define DS1302_SCLK PBout(9)  // 时钟

extern uchar DS1302_Time_Buffer[7];//存放时间的数组

void DS1302_Init(void);//初始化
void DS1302_Read_Time(void);//读取时间
void DS1302_Modify_Time(void); // 修改时间写到寄存器中
//void DS1302_Time_Stop();//暂停时间
//void DS1302_Time_Start();//开始时间
//uchar DS1302_Read_Data(uchar addr);
//void DS1302_Modify_Time();

#endif


DS1302.c

#include<All.h>

uchar  Write_Addr_Buffer[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//写入地址
uchar  Read_Addr_Buffer[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//读取地址
uchar DS1302_Time_Buffer[7]={00,0x00,0x16,0x01,0x09,0x02,0x20};//秒,分,时,日,月,周,年
void DS1302_IO_OUT(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;                       //定义一个设置IO的结构体
	
	RCC_APB2PeriphClockCmd(DS1302_Port_RCC,ENABLE);    //使能PB端口时钟
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;                 //准备设置PB4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   		   //上拉输入,默认状态是高电平
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度
	GPIO_Init(GPIOB, &GPIO_InitStructure);            		   //设置PB4
}

void DS1302_Gpio_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(DS1302_Port_RCC,ENABLE);//系统时钟使能

	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //定义管脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//管脚输出模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度
	GPIO_Init(DS1302_PORT,&GPIO_InitStructure); //初始化端口
	
	//DS1302_DAT_OUTPUT();
	DS1302_IO_OUT();
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //定义管脚
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//管脚输出模式
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度
//	GPIO_Init(DS1302_PORT,&GPIO_InitStructure); //初始化端口
	
}

void DS1302_IO_IN(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;                       //定义一个设置IO的结构体
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(DS1302_Port_RCC,ENABLE);    //使能PB端口时钟
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;                 //准备设置PB4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   		   //上拉输入,默认状态是高电平
	//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度
	GPIO_Init(GPIOB, &GPIO_InitStructure);            		   //设置PB4
}

/*********************************
 * @函数名:DS1302_Write_Reg
 * @描   述:写数据命令
 * @说   明:
 * @参   数:addr  要写入的寄存器的地址 dat 要写入的数据
 * @返回值:无 
 *********************************/
void DS1302_Write_Reg(uchar addr,uchar dat)
{
	uchar  i;
    DS1302_CE=0;
	delay_us(20);
	DS1302_SCLK=0;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
	// DS1302_IO=addr&0x01;//先发送低位
		if(addr&0x01)
			DS1302_IO = 1;
		else
			DS1302_IO =0;
		addr>>=1;
		DS1302_SCLK=1;//上升沿读取数据
		delay_us(20);
		DS1302_SCLK=0;
		delay_us(20);
	}
	for(i=0;i<8;i++)
	{
	 //   DS1302_IO=dat&0x01;//先发送低位
		if(dat&0x01)
			DS1302_IO = 1;
		else
			DS1302_IO =0;
		dat>>=1;
		DS1302_SCLK=1;//上升沿读取数据
		delay_us(20);
		DS1302_SCLK=0;
		delay_us(20);
	}
	 DS1302_SCLK=1;//上升沿读取数据
	delay_us(20);
	delay_us(20);
	DS1302_CE=0;
	delay_us(20);
}
/*********************************
 * @函数名:DS1302_Read_Data
 * @描   述:读数据
 * @说   明:
 * @参   数:addr  要读出的寄存器的地址 
 * @返回值:dat  读出的数据
 *********************************/
uchar DS1302_Read_Data(uchar addr)
{
    uchar  i;
	uchar  dat1,dat;
    DS1302_CE=0;
	delay_us(20);
	DS1302_SCLK=0;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
	// DS1302_IO=addr&0x01;//先发送低位
		if(addr&0x01)
			DS1302_IO = 1;
		else
			DS1302_IO =0;
		addr>>=1;
		DS1302_SCLK=1;//上升沿读取数据
		delay_us(20);
		DS1302_SCLK=0;
		delay_us(20);
	}
	 DS1302_IO_IN();     // 切换为输入模式
	//DS1302_DAT_INPUT();
	for(i=0;i<8;i++)
	{
		dat1=DS1302_IO_IN_STA;
//		if(DS1302_IO_IN_STA == 1)
//			dat1 = 1;
//		else
//			dat1 = 0;
		dat=(dat>>1)|(dat1<<7);
		DS1302_SCLK=1;//上升沿读取数据
        delay_us(20);
		DS1302_SCLK=0;
		delay_us(20);
	}
	 DS1302_SCLK=1;//上升沿读取数据
	delay_us(20);
	//DS1302_DAT_OUTPUT();  // 切换为输出模式
	DS1302_IO_OUT();
	delay_us(20);
	DS1302_CE=0;
     delay_us(20);
	 DS1302_IO=0;//不能少
	return dat;
}
/*********************************
 * @函数名:DS1302_Init
 * @描   述:初始化
 * @说   明:  修改时间也可以用这个  掉电走时特别奇怪(有疑问)
 * @参   数:无 
 * @返回值:无 
 *********************************/
void DS1302_Init(void)
{
	uchar  i;
	uchar dat; //读取第一个RAM的值
	DS1302_Gpio_Init(); // 管脚初始化
	//掉电走时处理
	dat = DS1302_Read_Data (0xc1); //读第一个RAM寄存器
	u1_printf("读出来的值是%x\r\n", dat);
	if(dat  !=  0xaa) //如果这个寄存器不是0xaa 要初始化
	{  
		u1_printf("进图\r\n");
		/*初始化时间时 dat != 0xaa    掉电走时 dat == 0xaa*/
	   DS1302_Write_Reg(0x8e,0x00);//允许写  wp = 0
		DS1302_Write_Reg(0xc0,0xaa); //往第一个RAM写入0xaa
		for(i=0;i<7;i++)  //初始化
		{
		  DS1302_Write_Reg(Write_Addr_Buffer[i],DS1302_Time_Buffer[i]); //写入初始化时间
		}
	  DS1302_Write_Reg(0x8e,0x80);//写保护  wp = 1
	}
	//else  不初始化
}
/*********************************
 * @函数名:DS1302_Read_Time
 * @描   述:读出寄存器的时间
 * @说   明:
 * @参   数:无 
 * @返回值:无 
 *********************************/
void DS1302_Read_Time()
{
   uchar i;
	for(i=0;i<7;i++)
	{
	  DS1302_Time_Buffer[i]=DS1302_Read_Data(Read_Addr_Buffer[i]);//读出时间
	}
	//处理  不计算秒的最高位
	DS1302_Time_Buffer[0] &= 0x7f; //把最高位置0
}
/*********************************
 * @函数名:DS1302_Modify_Time
 * @描   述:修改寄存器中的时间
 * @说   明:
 * @参   数:
 * @返回值:无 
 *********************************/
void DS1302_Modify_Time(void)
{
	uchar  i;
    DS1302_Write_Reg(0x8e,0x00);//允许写
	for(i=0;i<7;i++)
	{
	  DS1302_Write_Reg(Write_Addr_Buffer[i],DS1302_Time_Buffer[i]);
	}
	DS1302_Write_Reg(0x8e,0x80);//写保护
}
/*********************************
 * @函数名:DS1302_Time_Stop
 * @描   述:时间暂停
 * @说   明:秒寄存器的最高位CH 置1 时钟振荡器暂停 置0 时钟开始
 * @参   数:无 
 * @返回值:无 
 *********************************/
void DS1302_Time_Stop()
{
	uchar Second;//定义一个变量获取秒的数据 
	Second=DS1302_Read_Data(0x81);//取出秒的时间
	Second |= 0x80; //把最高位置1 其他的都保持不变 
    DS1302_Write_Reg(0x8e,0x00);//允许写
	DS1302_Write_Reg(0x80,Second);//秒暂停位 保持暂停的时间秒不变
	DS1302_Write_Reg(0x8e,0x80);//禁止写
}
/*********************************
 * @函数名:DS1302_Time_Start
 * @描   述:开始计时
 * @说   明:秒寄存器的最高位CH 置1 时钟振荡器暂停 置0 时钟开始
 * @参   数:无 
 * @返回值:无 
 *********************************/
void DS1302_Time_Start()
{
	uchar Second;//定义一个变量获取秒的数据 
	Second=DS1302_Read_Data(0x81);//取出秒的时间
	Second &= 0x7f; //把最高位置0 其他的都保持不变 
    DS1302_Write_Reg(0x8e,0x00);//允许写
	DS1302_Write_Reg(0x80,Second);//开始计时//second 还是原来的值
	DS1302_Write_Reg(0x8e,0x80);//禁止写
}

就写到这吧,实在没啥文采。
快开学了,加油。

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值