基于stm32f103zet6的DS1302学习
2013-03-16 10:40
204 查看
由于硬件出了问题,也就是外部低速晶振没用,震不起来,然后查看了网上的帖子,STM32的RTC果然口碑不怎么样,所以果断换DS1302,在移植的过程中还算顺利,记录下来吧,也算对自己的总结吧!
1、所谓的DS1302
这里面也指明了简单的SPI协议
然后就直接上代码了,注释很详细的!基本实现单行注释
1、主函数main
/*******************************************************************************
** 文件名称 : ds1302.c
** 编译环境 : RealView MDK-ARM 4.53
** 文件作者 :
** 功能说明 : ds1302相关函数定义
** 软件协议 :模拟SPI协议
** 简介 :clk上升沿发送数据,clk下降沿接收数据
:typedef unsigned char uint8_t;
**
**
**
*******************************************************************************/
/* 包含头文件 *****************************************************************/
#include "ds1302.h"
#include "stdio.h"
#include "Delay.h"
uint8_t read[] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//读秒、分、时、日、月、周、年的寄存器地址
uint8_t write[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//写秒、分、时、日、月、周、年的寄存器地址
/*PA4、PA6为输出*/
/*PA5配置为开漏模式,此模式下能够实现真正的双向IO口*/
void ds1302_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = ds1302clk|ds1302rst; //clk、rst配置为输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; //IO配置为双向
GPIO_InitStruct.GPIO_Pin = ds1302dat;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void write_1302byte(uint8_t dat) //写一个字节的数据sck上升沿写数据
{
uint8_t i = 0;
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0
Delay_us(2);//延时大约2us
for(i = 0;i < 8;i ++)
{
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0;
if(dat&0x01)
GPIO_SetBits(GPIOA,ds1302dat);
else //ds1302dat=(dat&0x01)
GPIO_ResetBits(GPIOA,ds1302dat);
Delay_us(2);
GPIO_SetBits(GPIOA,ds1302clk); //发送一位数据,clk上升沿,//ds1302clk=1
dat >>= 1;
Delay_us(1);
}
}
uint8_t read_1302(uint8_t add) //读数据
{
uint8_t i=0;
uint8_t Return_dat=0x00;
GPIO_ResetBits(GPIOA,ds1302rst); //ds1302rst=0;
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0;
Delay_us(3); //略微延时2us
GPIO_SetBits(GPIOA,ds1302rst); //ds1302rst=1;
Delay_us(3); //时间要大约3us
write_1302byte(add); //先写寄存器的地址
for(i=0;i<8;i++)
{
GPIO_SetBits(GPIOA,ds1302clk); //ds1302clk=1;
Return_dat >>= 1;
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0;//拉低时钟线,以便于数据的读入
if(GPIO_ReadInputDataBit(GPIOA,ds1302dat)==1) //数据线此时为高电平
{Return_dat = Return_dat|0x80;}
}
Delay_us(1);
GPIO_ResetBits(GPIOA,ds1302rst); //ds1302rst=0;释放总线
return Return_dat;
}
void write_1302(uint8_t add,uint8_t dat) //向指定寄存器写入一个字节的数据
{
GPIO_ResetBits(GPIOA,ds1302rst); //只有在rst为高电平的时候才能进行数据传输
GPIO_ResetBits(GPIOA,ds1302clk); //只有clk为低电平的时候,rst才能被置为高电平
//ds1302rst=0;
//ds1302clk=0;
Delay_us(1); //略微延时
GPIO_SetBits(GPIOA,ds1302rst); //clk = 0之后,这里将rst拉高,准备传送数据
//ds1302rst=1;
Delay_us(2); //时间大约2us
write_1302byte(add); //先发地址
write_1302byte(dat); //然后发数据
GPIO_ResetBits(GPIOA,ds1302rst); //这里释放总线
GPIO_ResetBits(GPIOA,ds1302clk); //拉低clk,以备下一次数据发送
//ds1302clk=0;
//ds1302rst=0;
Delay_us(1);
}
void ds1302_init(uint8_t *write,uint8_t *time) //初始化1302
{
uint8_t i=0,j=0;
write_1302(0x8e,0x00); //关闭写保护
for(i=0;i<7;i++) //十进制转BCD码
{
j=time[i]%10; //个位数部分
time[i]=(time[i]/10)*16+j;
}
for(i=0;i<7;i++) //进行对时
{
write_1302(write[i],time[i]); //在对应寄存器上写入对应的十六进制数据
}
write_1302(0x8e,0x80); //打开写保护
}
void ds1302_data(uint8_t *read) //处理数据并通过串口打印
{
uint8_t i=0,g[7],time[7];
// static uint8_t s = 1;
for(i=0;i<7;i++)
{
time[i]=read_1302(read[i]); //读数据已经完成
}
for(i=0;i<7;i++)
{
g[i]=time[i]%16; //秒个位数据:BCD转十进制
time[i]=time[i]/16; //秒十位数据
}
//此时已转换成10进制数,g[i]里面存放的是秒分时日月周年的各个位数据
//而此时的time[i]存放的是十位数据
//if(s != (time[0]+g[0]))
printf("20%d%d年%d%d月%d%d日%d%d:%d%d:%d%d 星期%d\r\n",time[6],g[6],time[4],g[4],time[3],g[3],time[2],g[2],time[1],g[1],time[0],g[0],g[5]);
//s = time[0]+g[0];
}
就是这样的简单,然后给出一张效果图
1、所谓的DS1302
这里面也指明了简单的SPI协议
然后就直接上代码了,注释很详细的!基本实现单行注释
1、主函数main
#include "stm32f10x.h" #include "SysTick.h" #include "Delay.h" #include "Usart.h" #include "stdio.h" #include "DS1302.h" /*******由于没有做外设测试的程序是:按键PA0仅一个LED灯 ******/ /*******由于没有做外设测试的程序是:串口采用的是PA9->(T<->T),PA9->(R<->R)*****/ /*******由于没有做外设测试的程序是:ds1302clk <-> PA4 ds1302dat <-> PA5 ds1302rst <-> PA6 *****/ extern uint8_t write[]; extern uint8_t read[]; int main(void) { //uint8_t time[] = {0,0,12,11,11,1,13}; //初始化系统定时器 SysTick_Init(); USART1_Config(); ds1302_GPIO_Configuration(); //一定别忘记了配置GPIO printf("\r\n ("__DATE__ " - " __TIME__ ") \r\n"); //ds1302_init(write,time); //设置1302的初始时间 ds1302_data(read); while(1); //这个得加,不然的话会有尾巴是乱码!!! }
/*******************************************************************************
** 文件名称 : ds1302.c
** 编译环境 : RealView MDK-ARM 4.53
** 文件作者 :
** 功能说明 : ds1302相关函数定义
** 软件协议 :模拟SPI协议
** 简介 :clk上升沿发送数据,clk下降沿接收数据
:typedef unsigned char uint8_t;
**
**
**
*******************************************************************************/
/* 包含头文件 *****************************************************************/
#include "ds1302.h"
#include "stdio.h"
#include "Delay.h"
uint8_t read[] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//读秒、分、时、日、月、周、年的寄存器地址
uint8_t write[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//写秒、分、时、日、月、周、年的寄存器地址
/*PA4、PA6为输出*/
/*PA5配置为开漏模式,此模式下能够实现真正的双向IO口*/
void ds1302_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = ds1302clk|ds1302rst; //clk、rst配置为输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; //IO配置为双向
GPIO_InitStruct.GPIO_Pin = ds1302dat;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void write_1302byte(uint8_t dat) //写一个字节的数据sck上升沿写数据
{
uint8_t i = 0;
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0
Delay_us(2);//延时大约2us
for(i = 0;i < 8;i ++)
{
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0;
if(dat&0x01)
GPIO_SetBits(GPIOA,ds1302dat);
else //ds1302dat=(dat&0x01)
GPIO_ResetBits(GPIOA,ds1302dat);
Delay_us(2);
GPIO_SetBits(GPIOA,ds1302clk); //发送一位数据,clk上升沿,//ds1302clk=1
dat >>= 1;
Delay_us(1);
}
}
uint8_t read_1302(uint8_t add) //读数据
{
uint8_t i=0;
uint8_t Return_dat=0x00;
GPIO_ResetBits(GPIOA,ds1302rst); //ds1302rst=0;
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0;
Delay_us(3); //略微延时2us
GPIO_SetBits(GPIOA,ds1302rst); //ds1302rst=1;
Delay_us(3); //时间要大约3us
write_1302byte(add); //先写寄存器的地址
for(i=0;i<8;i++)
{
GPIO_SetBits(GPIOA,ds1302clk); //ds1302clk=1;
Return_dat >>= 1;
GPIO_ResetBits(GPIOA,ds1302clk); //ds1302clk=0;//拉低时钟线,以便于数据的读入
if(GPIO_ReadInputDataBit(GPIOA,ds1302dat)==1) //数据线此时为高电平
{Return_dat = Return_dat|0x80;}
}
Delay_us(1);
GPIO_ResetBits(GPIOA,ds1302rst); //ds1302rst=0;释放总线
return Return_dat;
}
void write_1302(uint8_t add,uint8_t dat) //向指定寄存器写入一个字节的数据
{
GPIO_ResetBits(GPIOA,ds1302rst); //只有在rst为高电平的时候才能进行数据传输
GPIO_ResetBits(GPIOA,ds1302clk); //只有clk为低电平的时候,rst才能被置为高电平
//ds1302rst=0;
//ds1302clk=0;
Delay_us(1); //略微延时
GPIO_SetBits(GPIOA,ds1302rst); //clk = 0之后,这里将rst拉高,准备传送数据
//ds1302rst=1;
Delay_us(2); //时间大约2us
write_1302byte(add); //先发地址
write_1302byte(dat); //然后发数据
GPIO_ResetBits(GPIOA,ds1302rst); //这里释放总线
GPIO_ResetBits(GPIOA,ds1302clk); //拉低clk,以备下一次数据发送
//ds1302clk=0;
//ds1302rst=0;
Delay_us(1);
}
void ds1302_init(uint8_t *write,uint8_t *time) //初始化1302
{
uint8_t i=0,j=0;
write_1302(0x8e,0x00); //关闭写保护
for(i=0;i<7;i++) //十进制转BCD码
{
j=time[i]%10; //个位数部分
time[i]=(time[i]/10)*16+j;
}
for(i=0;i<7;i++) //进行对时
{
write_1302(write[i],time[i]); //在对应寄存器上写入对应的十六进制数据
}
write_1302(0x8e,0x80); //打开写保护
}
void ds1302_data(uint8_t *read) //处理数据并通过串口打印
{
uint8_t i=0,g[7],time[7];
// static uint8_t s = 1;
for(i=0;i<7;i++)
{
time[i]=read_1302(read[i]); //读数据已经完成
}
for(i=0;i<7;i++)
{
g[i]=time[i]%16; //秒个位数据:BCD转十进制
time[i]=time[i]/16; //秒十位数据
}
//此时已转换成10进制数,g[i]里面存放的是秒分时日月周年的各个位数据
//而此时的time[i]存放的是十位数据
//if(s != (time[0]+g[0]))
printf("20%d%d年%d%d月%d%d日%d%d:%d%d:%d%d 星期%d\r\n",time[6],g[6],time[4],g[4],time[3],g[3],time[2],g[2],time[1],g[1],time[0],g[0],g[5]);
//s = time[0]+g[0];
}
就是这样的简单,然后给出一张效果图
相关文章推荐
- 基于stm32f103zet6的RTC学习
- 基于stm32f103zet6之nor flash的学习
- 基于stm32f103zet6的FAT16文件系统学习3(初步分析ff9a)
- 基于stm32f103zet6的IIC学习
- 基于stm32f103zet6的FAT16文件系统学习4(管理SD卡,读取图片,字库)
- 基于stm32f103zet6之NRF905无线模块的学习
- 基于stm32f103zet6之最小系统的制作
- 基于stm32f103zet6点亮LED之启动文件
- (转) 基于STM32F103ZET6的UART通讯实现
- IAR环境下STM32+IAP方案的实现(基于STM32F103ZET6的UART通讯实现)
- [置顶] 基于stm32f103zet6的FAT16文件系统学习2(初步移植ff9a)
- 基于stm32f103zet6的串口学习
- 基于stm32f103zet6的看门狗学习
- 基于stm32f103zet6的定时器的学习3(定时器产生4路PWM)
- 基于stm32f103zet6的外部中断学习
- 基于stm32f103zet6之我的彩屏
- 基于stm32f103zet6的定时器的学习1(理论知识)
- 基于stm32f103zet6之使用FSMC驱动TFT的学习
- 基于stm32f103zet6的FAT16文件系统学习1(初识FAT16)
- 基于stm32f103zet6的内存管理的学习