基于stm32f103zet6的DS1302学习

由于硬件出了问题,也就是外部低速晶振没用,震不起来,然后查看了网上的帖子,STM32的RTC果然口碑不怎么样,所以果断换DS1302,在移植的过程中还算顺利,记录下来吧,也算对自己的总结吧!

1、所谓的DS1302


这里面也指明了简单的SPI协议

然后就直接上代码了,注释很详细的!基本实现单行注释

1、主函数main

[html]  view plain  copy
  1. #include "stm32f10x.h"      
  2. #include "SysTick.h"  
  3. #include "Delay.h"  
  4. #include "Usart.h"  
  5. #include "stdio.h"  
  6. #include "DS1302.h"  
  7. /*******由于没有做外设测试的程序是:按键PA0仅一个LED灯                                  ******/  
  8. /*******由于没有做外设测试的程序是:串口采用的是PA9->(T<->T),PA9->(R<->R)*****/  
  9. /*******由于没有做外设测试的程序是:ds1302clk <-> PA4  
  10.                                                                         ds1302dat <-> PA5  
  11.                                                                         ds1302rst <-> PA6                                      *****/  
  12.                                                                           
  13. extern uint8_t write[];  
  14. extern uint8_t read[];  
  15.   
  16. int main(void)  
  17. {  
  18.     //uint8_t time[] = {0,0,12,11,11,1,13};  
  19.     //初始化系统定时器  
  20.     SysTick_Init();  
  21.     USART1_Config();  
  22.     ds1302_GPIO_Configuration();                                                    //一定别忘记了配置GPIO  
  23.     printf("\r\n ("__DATE__ " - " __TIME__ ") \r\n");  
  24.     //ds1302_init(write,time);                                                      //设置1302的初始时间  
  25.     ds1302_data(read);  
  26.     while(1);                                                                                           //这个得加,不然的话会有尾巴是乱码!!!  
  27. }  

[html]  view plain  copy
  1. /*******************************************************************************  
  2. ** 文件名称 : ds1302.c  
  3. ** 编译环境 : RealView MDK-ARM 4.53  
  4. ** 文件作者 :     
  5. ** 功能说明 : ds1302相关函数定义  
  6. ** 软件协议 :模拟SPI协议  
  7. ** 简介           :clk上升沿发送数据,clk下降沿接收数据  
  8.                         :typedef unsigned          char uint8_t;  
  9. **                        
  10. **                               
  11. **  
  12. *******************************************************************************/  
  13. /* 包含头文件 *****************************************************************/  
  14. #include "ds1302.h"  
  15. #include "stdio.h"  
  16. #include "Delay.h"  
  17.   
  18. uint8_t read[] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//读秒、分、时、日、月、周、年的寄存器地址  
  19. uint8_t write[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//写秒、分、时、日、月、周、年的寄存器地址  
  20. /*PA4、PA6为输出*/  
  21. /*PA5配置为开漏模式,此模式下能够实现真正的双向IO口*/  
  22. void ds1302_GPIO_Configuration(void)  
  23. {  
  24.     GPIO_InitTypeDef GPIO_InitStruct;  
  25.   
  26.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
  27.     GPIO_InitStruct.GPIO_Pin = ds1302clk|ds1302rst;         //clk、rst配置为输出  
  28.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  29.     GPIO_Init(GPIOA, &GPIO_InitStruct);  
  30.   
  31.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;               //IO配置为双向  
  32.     GPIO_InitStruct.GPIO_Pin = ds1302dat;  
  33.     GPIO_Init(GPIOA, &GPIO_InitStruct);  
  34.   
  35. }  
  36.   
  37. void write_1302byte(uint8_t dat)                                            //写一个字节的数据sck上升沿写数据  
  38. {  
  39.     uint8_t i = 0;  
  40.     GPIO_ResetBits(GPIOA,ds1302clk);                                        //ds1302clk=0  
  41.       
  42.   Delay_us(2);//延时大约2us  
  43.       
  44.     for(i = 0;i < 8;i ++)  
  45.         {  
  46.             GPIO_ResetBits(GPIOA,ds1302clk);                            //ds1302clk=0;  
  47.             if(dat&0x01)  
  48.                 GPIO_SetBits(GPIOA,ds1302dat);  
  49.             else                                                                                        //ds1302dat=(dat&0x01)  
  50.                 GPIO_ResetBits(GPIOA,ds1302dat);                  
  51.             Delay_us(2);  
  52.             GPIO_SetBits(GPIOA,ds1302clk);                                  //发送一位数据,clk上升沿,//ds1302clk=1  
  53.             dat >>= 1;  
  54.             Delay_us(1);  
  55.         }     
  56.     }  
  57.       
  58. uint8_t read_1302(uint8_t add)                                              //读数据  
  59. {  
  60.     uint8_t i=0;  
  61.     uint8_t Return_dat=0x00;  
  62.     GPIO_ResetBits(GPIOA,ds1302rst);                                    //ds1302rst=0;  
  63.     GPIO_ResetBits(GPIOA,ds1302clk);                                        //ds1302clk=0;  
  64.     Delay_us(3);                                                                                //略微延时2us  
  65.     GPIO_SetBits(GPIOA,ds1302rst);                                      //ds1302rst=1;  
  66.     Delay_us(3);                                                                                //时间要大约3us  
  67.     write_1302byte(add);                                                                //先写寄存器的地址  
  68.     for(i=0;i<8;i++)  
  69.     {  
  70.         GPIO_SetBits(GPIOA,ds1302clk);                                      //ds1302clk=1;  
  71.         Return_dat >>= 1;  
  72.         GPIO_ResetBits(GPIOA,ds1302clk);                                    //ds1302clk=0;//拉低时钟线,以便于数据的读入  
  73.         if(GPIO_ReadInputDataBit(GPIOA,ds1302dat)==1)           //数据线此时为高电平  
  74.         {Return_dat = Return_dat|0x80;}  
  75.     }  
  76.       Delay_us(1);  
  77.       GPIO_ResetBits(GPIOA,ds1302rst);                                //ds1302rst=0;释放总线  
  78.       return Return_dat;  
  79.     }  
  80. void write_1302(uint8_t add,uint8_t dat)                            //向指定寄存器写入一个字节的数据  
  81. {  
  82.     GPIO_ResetBits(GPIOA,ds1302rst);                                        //只有在rst为高电平的时候才能进行数据传输  
  83.     GPIO_ResetBits(GPIOA,ds1302clk);                                        //只有clk为低电平的时候,rst才能被置为高电平  
  84.     //ds1302rst=0;  
  85.     //ds1302clk=0;  
  86.     Delay_us(1);                                                                                //略微延时  
  87.     GPIO_SetBits(GPIOA,ds1302rst);                                          //clk = 0之后,这里将rst拉高,准备传送数据  
  88.     //ds1302rst=1;  
  89.     Delay_us(2);                                                                                //时间大约2us  
  90.     write_1302byte(add);                                                                //先发地址  
  91.     write_1302byte(dat);                                                                //然后发数据  
  92.     GPIO_ResetBits(GPIOA,ds1302rst);                                        //这里释放总线  
  93.     GPIO_ResetBits(GPIOA,ds1302clk);                                        //拉低clk,以备下一次数据发送  
  94.     //ds1302clk=0;  
  95.     //ds1302rst=0;  
  96.     Delay_us(1);  
  97.   
  98. }  
  99. void ds1302_init(uint8_t *write,uint8_t *time)              //初始化1302  
  100. {  
  101.     uint8_t i=0,j=0;  
  102.     write_1302(0x8e,0x00);                                                          //关闭写保护  
  103.     for(i=0;i<7;i++)                                                                     //十进制转BCD码  
  104.     {  
  105.         j=time[i]%10;                                                                           //个位数部分  
  106.         time[i]=(time[i]/10)*16+j;    
  107.     }  
  108.     for(i=0;i<7;i++)                                                                     //进行对时  
  109.     {  
  110.         write_1302(write[i],time[i]);                                           //在对应寄存器上写入对应的十六进制数据  
  111.           
  112.     }  
  113.     write_1302(0x8e,0x80);                                                      //打开写保护  
  114. }  
  115. void ds1302_data(uint8_t *read)                                             //处理数据并通过串口打印  
  116. {  
  117.     uint8_t i=0,g[7],time[7];  
  118. //  static uint8_t s = 1;  
  119.     for(i=0;i<7;i++)  
  120.     {  
  121.         time[i]=read_1302(read[i]);                                             //读数据已经完成  
  122.     }  
  123.     for(i=0;i<7;i++)  
  124.     {  
  125.         g[i]=time[i]%16;                                                                    //秒个位数据:BCD转十进制  
  126.         time[i]=time[i]/16;                                                             //秒十位数据  
  127.     }  
  128.     //此时已转换成10进制数,g[i]里面存放的是秒分时日月周年的各个位数据  
  129.     //而此时的time[i]存放的是十位数据  
  130.                       
  131.         //if(s != (time[0]+g[0]))  
  132.     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]);  
  133.       //s = time[0]+g[0];     
  134. }  
就是这样的简单,然后给出一张效果图

猜你喜欢

转载自blog.csdn.net/weibo1230123/article/details/80303319