作者在某STM32的应用中外接了一块DS1302,借鉴原来写过的PIC代码,很快移植成功。在这里与大家分享一下。 (1)硬件 CLK---PA4, DAT--- PA5, RST--- PA6 (2)硬件初始化 CLK与RST均为输出,而DAT是开漏型的输出。因为在这种方式下,IO口的读仍然存在,因此是真正的双向IO模式。 /*DSCK -PA4 DAT PA5 RST DAT*/ #define ds1302Clk GPIO_Pin_4 //与时钟线相连的芯片的管脚 #define ds1302Dat GPIO_Pin_5 //与数据线相连的芯片的管脚 #define ds1302Rst GPIO_Pin_6 //与复位端相连的芯片的管脚 /* PA 4,6,为输出*/ GPIO_InitStructure.GPIO_Pin = ds1302Clk | ds1302Rst ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //PA5配置为开漏模式,此模式下可以实现真下的双向IO GPIO_InitStructure.GPIO_Pin = ds1302Dat; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOA, &GPIO_InitStructure); (3)配置完毕,然后实现的代码就很简单了,从现成的代码移植过来。 #define WrEnDisCmd 0x8e //写允许/禁止指令代码 #define WrEnDat 0x00 //写允许数据 #define WrDisDat 0x80 //写禁止数据 #define OscEnDisCmd 0x80 //振荡器允许/禁止指令代码 #define OscEnDat 0x00 //振荡器允许数据 #define OscDisDat 0x80 //振荡器禁止数据 #define WrMulti 0xbe //写入多个字节的指令代码 #define WrSingle 0x84 //写入单个字节的指令代码 #define RdMulti 0xbf //读出多个字节的指令代码 ////以上这些#define均放在一个ds1302.h文件中。 void SendDat_1302(u8 Dat) { u8 i; u8 cTmp; for(i=0;i<8;i++) { cTmp=Dat&LSB; //数据端等于tmp数据的末位值 if(cTmp) //1 GPIO_SetBits(GPIOA,ds1302Dat); else GPIO_ResetBits(GPIOA,ds1302Dat); Dat>>=1; GPIO_SetBits(GPIOA,ds1302Clk); uDelay(1); GPIO_ResetBits(GPIOA,ds1302Clk); } } /*写入1个或者多个字节,第1个参数是相关命令 #define WrMulti 0xbe //写入多个字节的指令代码 #define WrSingle 0x84 //写入单个字节的指令代码 第2个参数是待写入的值 第3个参数是待写入数组的指针 */ void WriteByte_1302(u8 CmdDat,u8 Num,u8 *pSend) { u8 i=0; GPIO_ResetBits(GPIOA,ds1302Rst); uDelay(1); GPIO_SetBits(GPIOA,ds1302Rst); SendDat_1302(CmdDat); for(i=0;i<Num;i++) { SendDat_1302(*(pSend+i)); } GPIO_ResetBits(GPIOA,ds1302Rst); } /*读出字节,第一个参数是命令 #define RdMulti 0xbf //读出多个字节的指令代码 第2个参数是读出的字节数,第3个是指收数据数组指针 */ void RecByte_1302(u8 CmdDat,u8 Num,u8 *pRec) { u8 i,j,tmp,cTmp; GPIO_ResetBits(GPIOA,ds1302Rst);//复位引脚为低电平 uDelay(1); GPIO_ResetBits(GPIOA,ds1302Clk); uDelay(1); GPIO_SetBits(GPIOA,ds1302Rst); SendDat_1302(CmdDat); //发送命令 for(i=0;i<Num;i++) { for(j=0;j<8;j++) { tmp>>=1; cTmp=GPIO_ReadInputDataBit(GPIOA,ds1302Dat); if(cTmp) tmp|=0x80; GPIO_SetBits(GPIOA,ds1302Clk); uDelay(1); GPIO_ResetBits(GPIOA,ds1302Clk); } *(pRec+i)=tmp; } uDelay(1); GPIO_ResetBits(GPIOA,ds1302Rst);//复位引脚为低电平 } /* 当写保护寄存器的最高位为0时,允许数据写入寄存器。 写保护寄存器可以通过命令字节8E、8F来规定禁止写入/读出。写保护位不能在多字节传送模式下写入。 当写保护寄存器的最高位为1时,禁止数据写入寄存器。 时钟停止位操作:当把秒寄存器的第7位时钟停止位设置为0时起动时钟开始 当把秒寄存器的第7位时钟停止位设置为1时,时钟振荡器停止。 根据传入的参数决定相关命令, 第一个参数:命令字,第2个参数:写入的数据 写允许命令;8EH,00H 写禁止命令;8EH,80H 振荡器允许命令;80H,00H 振荡器禁止命令;80H,80H */ void WrCmd(u8 CmdDat,u8 CmdWord) { u8 CmdBuf[2]; CmdBuf[0]=CmdWord; WriteByte_1302(CmdDat,1,CmdBuf); } main函数中调用如下: u8 Ds1302SendBuf[8]={0x30,0x32,0x01,0x10,0x01,0x01,0x08,33}; //发送数据缓冲区 u8 Ds1302RecBuf[8]; //接收数据缓冲区 WrCmd(WrEnDisCmd,WrEnDat); //写允许 WrCmd(OscEnDisCmd,OscEnDat); //振荡器允许 WriteByte(WrMulti,8,Ds1302SendBuf);//将时间值送到DS1302中 RecByte(RdMulti,8,Ds1302RecBuf); // 读出来看看
STM32与DS1302的接口电路
猜你喜欢
转载自blog.csdn.net/weibo1230123/article/details/80253616
今日推荐
周排行