[html] view plain copy
print?
- /*******************************************************************************
- ** 文件名称 : 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%10; //个位数部分
- time=(time/10)*16+j;
- }
- for(i=0;i<7;i++) //进行对时
- {
- write_1302(write,time); //在对应寄存器上写入对应的十六进制数据
-
- }
- 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=read_1302(read); //读数据已经完成
- }
- for(i=0;i<7;i++)
- {
- g=time%16; //秒个位数据:BCD转十进制
- time=time/16; //秒十位数据
- }
- //此时已转换成10进制数,g里面存放的是秒分时日月周年的各个位数据
- //而此时的time存放的是十位数据
-
- //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];
- }
就是这样的简单,然后给出一张效果图
|