STM32与DS1302通信问题

2019-03-23 19:02发布

本帖最后由 yangshihai1986 于 2013-12-26 19:25 编辑

各位前辈,大家好,我在写STM32与DS1302通信的时候遇到了一个问题
1,写1302时,写不进,读出的数据为0ff,
源码如下
1302头文件:
#ifndef __DS1302_H__
#define __DS1302_H__
#include<stm32f10x_lib.h>
#include"delay.h"
#define ds1302_sec_add                        0x80                //秒数据地址
#define ds1302_min_add                        0x82                //分数据地址
#define ds1302_hr_add                        0x84                //时数据地址
#define ds1302_date_add                        0x86                //日数据地址
#define ds1302_month_add                0x88                //月数据地址
#define ds1302_day_add                        0x8a                //星期数据地址
#define ds1302_year_add                        0x8c                //年数据地址
#define ds1302_control_add                0x8e                //写保护控制数据地址
#define ds1302_charger_add                0x90                 //慢充电寄存器地址                        
#define ds1302_clkburst_add                0xbe                //时钟突发模式寄存器地址
extern u8 time_buf1[8];//空年月日时分秒周
extern u8 time_buf[8] ;//空年月日时分秒周
void Ds1302_WriteByte(u8 ds1302_addr,u8 ds1302_data);//向DS1302写入一字节数据
u8 Ds1302_ReadByte(u8 ds1302_command);//从DS1302读出一字节数据
void Ds1302_WriteTime(void) ;//向DS1302写入时钟数据
void Ds1302_ReadTime(void)  ;//从DS1302读出时钟数据
void Ds1302_init(void);//DS1302初始化
void Ds1302_display(void);//ds1302时间显示函数
#endif




1302.c文件:
#include<stm32f10x_lib.h>
#include "ds1302.h"
#include"delay.h"
u8 time_buf1[8] = {20,13,12,22,15,9,30,7};//空年月日时分秒周
u8 time_buf[8] ;                         //空年月日时分秒周
/************************************/
/********* DS1302初始化程序 *********/
void Ds1302_init(void)
{
  RCC->APB2ENR|=1<<2;    //使能PORTA时钟
  GPIOA->CRH&=0xfffff0f0; //
  GPIOA->CRH|=0x00000303; //端口A的第8脚和第10脚配置为通用推挽输出
  GPIOA->ODR&=~(1<<8);//SCLK引脚置低
  GPIOA->ODR&=~(1<<10);//RST引脚置低
  Ds1302_WriteByte(ds1302_control_add,0x00);                        //关闭写保护
  Ds1302_WriteByte(ds1302_sec_add,0x00); //振荡器工作允许
  Ds1302_WriteByte(ds1302_control_add,0x80);                        //关闭写保护
}
/*************************************/
/***** 从DS1302中读取1个字节程序 *****/
u8 Ds1302_ReadByte(u8 ds1302_addr)
{
  u8 i,read_data;
  GPIOA->CRH&=0xffffff0f; //
  GPIOA->CRH|=0x00000030; //端口A的第9脚设置为推挽输出
  GPIOA->ODR|=1<<10;//RST引脚置高,启用ds1302数据总线
  delay_us(5);
  ds1302_addr|=0x01;//第0位:为1,表示读,为0表示写
  delay_us(5);
  for(i=0;i<8;i++)
  {
    if((ds1302_addr&0x01)==0)
      GPIOA->ODR&=~(1<<9); //为0
        else
          GPIOA->ODR|=1<<9;           //为1
        GPIOA->ODR|=1<<8;//SCLK时钟信号置高
        delay_us(5);
    GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
        delay_us(5);
        ds1302_addr>>=1; //地址数据右移一位,为下一位读取做准备
  }
   GPIOA->CRH&=0xffffff0f; //
   GPIOA->CRH|=0x00000080; //端口A的第9脚配置为上拉/下拉输入模式,此时可读取外部信号电平
  for(i=0;i<8;i++)
  {
    read_data>>=1;//右移一位,准备接收一位数据
        //read_data&=0x7f;
    if((GPIOA->ODR&0x0200)==0x0200)         //判断PA9口的电平是否为高
          read_data|=0x80; //电平为高
        else
          read_data&=0x7f;//电平为低
        GPIOA->ODR|=1<<8;//SCLK时钟信号置高
        delay_us(5);
    GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
        delay_us(5);        
  }
  GPIOA->ODR&=~(1<<10);//RST置为0,释放ds1302数据总线
  delay_us(5);
  return read_data; //返回采集到的数据
}
/*************************************/
/***** 向DS1302中写入1个字节程序 *****/
void Ds1302_WriteByte(u8 ds1302_addr,u8 ds1302_data)
{

  u8 i;
  GPIOA->ODR&=~(1<<10);//RST置为0
  GPIOA->CRH&=0xffffff0f; //
  GPIOA->CRH|=0x00000030; //端口A的第9脚配置为通用推挽输出
  GPIOA->ODR|=1<<10;//RST置为1,启用ds1302数据总线
  delay_us(5);
  GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
  delay_us(5);
  ds1302_addr&=0xfe;//第0位:为1,表示读,为0表示写
  delay_us(5);
  for(i=0;i<8;i++)
  {
    GPIOA->ODR|=1<<8;//SCLK时钟信号置高
    if((ds1302_addr&0x01)==0) //判断PA9口的数据是否为高
      GPIOA->ODR&=~(1<<9);//为低电平
        else
          GPIOA->ODR|=1<<9;         //为高电平
    GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
        delay_us(5);
        ds1302_addr>>=1;  //地址数据右移一位,为下一位读取做准备
  }
  for(i=0;i<8;i++)
  {
    if((ds1302_data&0x01)==0)  //判断PA9口的数据是否为高
      GPIOA->ODR&=~(1<<9);        //为低电平
        else
          GPIOA->ODR|=1<<9;         //为高电平
        GPIOA->ODR|=1<<8;//SCLK时钟信号置高
        delay_us(5);
    GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
        delay_us(5);
        ds1302_data>>=1; //需写入的数据右移一位,为下一位写入做准备
  }
  GPIOA->ODR&=~(1<<10);//RST置0,释放ds1302数据总线
  delay_us(5);
}
/************************************/
/****** 向DS1302中写入时间程序 ******/
void Ds1302_WriteTime(void)
{
    u8 i,tmp;
        for(i=0;i<8;i++)
            {                  //BCD处理
                tmp=time_buf1/10;
                time_buf=time_buf1%10;
                time_buf=time_buf+tmp*16;
            }
        Ds1302_WriteByte(ds1302_control_add,0x00);                        //关闭写保护
        Ds1302_WriteByte(ds1302_sec_add,0x80);                                //暂停
        Ds1302_WriteByte(ds1302_charger_add,0xa9);                        //涓流充电
        Ds1302_WriteByte(ds1302_year_add,time_buf[1]);                //年
        Ds1302_WriteByte(ds1302_month_add,time_buf[2]);        //月
        Ds1302_WriteByte(ds1302_date_add,time_buf[3]);                //日
        Ds1302_WriteByte(ds1302_day_add,time_buf[7]);                //周
        Ds1302_WriteByte(ds1302_hr_add,time_buf[4]);                //时
        Ds1302_WriteByte(ds1302_min_add,time_buf[5]);                //分
        Ds1302_WriteByte(ds1302_sec_add,time_buf[6]);                //秒
        Ds1302_WriteByte(ds1302_day_add,time_buf1[7]);                //周
        Ds1302_WriteByte(ds1302_control_add,0x80);                        //打开写保护
}
/************************************/
/****** 从DS1302中读出时间程序 ******/
void Ds1302_ReadTime(void)
{
           u8 i,tmp;
        time_buf[1]=Ds1302_ReadByte(ds1302_year_add);                //年
        time_buf[2]=Ds1302_ReadByte(ds1302_month_add);                //月
        time_buf[3]=Ds1302_ReadByte(ds1302_date_add);                //日
        time_buf[4]=Ds1302_ReadByte(ds1302_hr_add);                //时
        time_buf[5]=Ds1302_ReadByte(ds1302_min_add);                //分
        time_buf[6]=(Ds1302_ReadByte(ds1302_sec_add));  //秒
        time_buf[7]=Ds1302_ReadByte(ds1302_day_add);                //周
        for(i=0;i<8;i++)
           {           //BCD处理
                 tmp=time_buf/16;
                 time_buf1=time_buf%16;
                 time_buf1=time_buf1+tmp*10;
           }
}






主函数:
#include<stm32f10x_lib.h>
#include"led.h"
#include "sys.h"
#include "595.h"
#include "Timer.h"
#include "ds1302.h"
#include"delay.h"
// sc8 table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// sc8 table1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
u16 t2;

int main(void)
{
  Stm32_Clock_Init(9);
  led_init();
  delay_init(72);
  HC595_init();
  Ds1302_init();
  Timer2_Init(1000,7199);
  delay_ms(200);
  Ds1302_WriteTime(); //原始年月日数据读入
  delay_ms(200);
  while(1)
  {         
   
        Ds1302_display();
//        display(t2);
  }
}
/********************************/
/***** 定时器2中断服务程序 *****/         
void TIM2_IRQHandler(void)
{                                                                  
        if(TIM2->SR&0X0001)//溢出中断
        {        
            t2++;
                if(t2>=10)
                {
                  t2=0;
                  Ds1302_ReadTime();
                }                                                                                                                                
        }                                   
        TIM2->SR&=~(1<<0);//清除中断标志位            
}
请各位前辈多多指教


此帖出自小平头技术问答
0条回答

一周热门 更多>