OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9568|回复: 10

STM8S驱动DS1302

[复制链接]

8

主题

19

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
233
金钱
233
注册时间
2015-5-12
在线时间
51 小时
发表于 2016-11-15 15:02:04 | 显示全部楼层 |阅读模式
1金钱
代码是自己参考普中科技51驱动写的,时序什么检查了很多遍,基本上都是一样的,但是在oled上显示总是数据全是0,下面是我的代码,大神帮帮忙,找找问题在哪。
头文件代码
#ifndef __DS1302_H_
#define __DS1302_H_
#include "stm8s.h"
extern unsigned char TIME[7]; //加入全局变量
#define DS1302_RST  GPIO_PIN_1 //定
#define DS1302_SCLK GPIO_PIN_2 //定
#define DS1302_DSIO GPIO_PIN_3
#define GPIO_DS1302 GPIOA    //定义要使用的端口A
#define DS1302_RST_OUT   GPIO_Init(GPIO_DS1302, DS1302_RST, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define DS1302_DSIO_OUT  GPIO_Init(GPIO_DS1302, DS1302_DSIO, GPIO_MODE_OUT_PP_HIGH_SLOW) //高速推挽输出高电平
#define DS1302_DSIO_IN   GPIO_Init(GPIO_DS1302, DS1302_DSIO, GPIO_MODE_IN_PU_NO_IT) //上拉输入无中断功能
#define DS1302_SCLK_OUT  GPIO_Init(GPIO_DS1302, DS1302_SCLK, GPIO_MODE_OUT_PP_HIGH_SLOW) //高速推挽输出高电平
#define DS1302_RST_H GPIO_WriteHigh(GPIO_DS1302,DS1302_RST)  //置指定端口位为高电平,该端口必须配置为输出
#define DS1302_RST_L GPIO_WriteLow(GPIO_DS1302,DS1302_RST)   //置指定端口位为低电平,该端口必须配置为输出
#define DS1302_SCLK_H GPIO_WriteHigh(GPIO_DS1302,DS1302_SCLK)  //置指定端口位为高电平,该端口必须配置为输出
#define DS1302_SCLK_L GPIO_WriteLow(GPIO_DS1302,DS1302_SCLK)   //置指定端口位为低电平,该端口必须配置为输出
#define DS1302_DSIO_H GPIO_WriteHigh(GPIO_DS1302,DS1302_DSIO)  //置指定端口位为高电平,该端口必须配置为输出
#define DS1302_DSIO_L GPIO_WriteLow(GPIO_DS1302,DS1302_DSIO)   //置指定端口位为低电平,该端口必须配置为输出
//---定义全局函数---//
void Ds1302Write_byte(unsigned char dat);
//void Ds1302_Init(void);
void Ds1302Write(unsigned char addr, unsigned char dat);
unsigned char Ds1302Read(unsigned char addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局变量--//
#endif


源文件代码
#include "pbdata.h"
unsigned char time_data[7]={14,6,5,31,8,00,00};
unsigned char write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};
unsigned char read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};
unsigned char TIME[7] = {0x13, 0x02, 0x01, 0x01, 0x12, 0, 0};
/********************
DS1302 写字节函数
******************/
void Ds1302Write_byte(unsigned char dat)
{
  unsigned char i;
  DS1302_DSIO_OUT;
  for(i=0;i<8;i++)
  {
        
       if((dat&0x01)>0) //0x01  0000 0001
          DS1302_DSIO_H;
       else
          DS1302_DSIO_L;
        dat>>=1;
        DS1302_SCLK_H;
        delay_us(5);
        DS1302_SCLK_L;
        delay_us(5);
  }
  
}
/*******************************************************************************
* 函 数 名         : Ds1302Write
* 函数功能         : 向DS1302命令(地址+数据)
* 输    入         : addr,dat
* 输    出         : 无
*******************************************************************************/
void Ds1302Write(unsigned char addr, unsigned char dat)
{
        DS1302_DSIO_OUT;
DS1302_RST_L;
  delay_us(1);
DS1302_SCLK_L;//先将SCLK置低电平。
delay_us(1);
DS1302_RST_H; //然后将RST(CE)置高电平。
delay_us(1);
        Ds1302Write_byte(addr);
        Ds1302Write_byte(dat);
        DS1302_RST_L;
        delay_us(1);
      //  DS1302_DSIO_H;
      // DS1302_SCLK_H;
}
/*******************************************************************************
* 函 数 名         : Ds1302Read
* 函数功能     : 读取一个地址的数据
* 输    入         : addr
* 输    出         : dat
*******************************************************************************/
unsigned char Ds1302Read(unsigned char addr)
{
  unsigned char n,dat1,dat=0;
  DS1302_RST_L;
  delay_us(1);
  DS1302_SCLK_L;
  delay_us(1);
  DS1302_RST_H;
  delay_us(1);
  Ds1302Write_byte(addr);
  delay_us(1);
  DS1302_DSIO_IN;
  for(n=0;n<8;n++)
  {
   // DS1302_SCLK_L;
     if(GPIO_ReadInputPin(GPIO_DS1302, DS1302_DSIO)==1)
       dat1=1;//从最低位开始接收
     else
       dat1=0;
     dat = (dat>>1) | (dat1<<7);
     DS1302_SCLK_H;
     delay_us(1);
     DS1302_SCLK_L;
     delay_us(1);
  }
DS1302_RST_L;
delay_us(1); //以下为DS1302复位的稳定时间,必须的。
DS1302_SCLK_H;
delay_us(1);
      //  DS1302_SCLK_H;
        DS1302_DSIO_OUT;
DS1302_DSIO_H;
        delay_us(1);
return dat;
}
/*******************************************************************************
* 函 数 名         : Ds1302Init
* 函数功能     : 初始化DS1302.
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Ds1302Init()
{
unsigned char i,j;
        DS1302_RST_OUT;
        DS1302_DSIO_OUT;
        DS1302_SCLK_OUT;
      //  Ds1302_Init();
         for(i=0;i<7;i++)
          {
            j=time_data[i]/10;
            time_data[i]=time_data[i]%10;
            time_data[i]=time_data[i]+j*16;
           }
Ds1302Write(0x8E,0X00);   //禁止写保护,就是关闭写保护功能
  for(i=0;i<7;i++)
          {
            Ds1302Write(write_add[i],time_data[i]);
           }
Ds1302Write(0x8E,0x80);   //打开写保护功能
}
/*******************************************************************************
* 函 数 名         : Ds1302ReadTime
* 函数功能     : 读取时钟信息
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Ds1302ReadTime()
{
unsigned char n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
  TIME[n] = Ds1302Read(read_add[n]);
}
  
}
主函数
#include "pbdata.h"
//unsigned char TIME[7]; //加入全局变量
void BSP_Configuration(void);
int main(void)
{
  BSP_Configuration();
  OLED_CLS();
  while(1)
  {
      Ds1302ReadTime();
      OLED_ShowNum(2,2,TIME[0]/16);          //分
      OLED_ShowNum(10,2,TIME[0]%16/10);
      OLED_ShowNum(18,2,TIME[0]%16%10);
      
      OLED_ShowNum(2+26,2,TIME[1]/16);          //分
      OLED_ShowNum(10+26,2,TIME[1]%16/10);
      OLED_ShowNum(18+26,2,TIME[1]%16%10);

      OLED_ShowNum(2+26+26,2,TIME[2]/16);          //分
      OLED_ShowNum(10+26+26,2,TIME[2]%16/10);
      OLED_ShowNum(18+26+26,2,TIME[2]%16%10);
      delay_ms(100);
  }
}
void BSP_Configuration(void)
{
  //开启内部始终1分频 16mhz
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
  I2C_Config();
  OLED_Init();
  Ds1302Init();
}
/*断言函数:再编程过程中为程序提供参数检查*/
#ifdef USE_FULL_ASSERT
void assert_failed(u8*file,u32 line)
{
  while(1)
  {
  }
}
#endif
内容大概就是这些,感觉都是对的啊

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2016-11-15 19:44:41 | 显示全部楼层
回复

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2109
金钱
2109
注册时间
2011-9-3
在线时间
119 小时
发表于 2016-11-16 08:44:10 | 显示全部楼层
帮顶。!
回复

使用道具 举报

1

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2013-10-9
在线时间
12 小时
发表于 2017-7-1 00:37:21 | 显示全部楼层
等待下文!
回复

使用道具 举报

0

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2016-5-7
在线时间
7 小时
发表于 2017-12-31 20:47:55 | 显示全部楼层
建议你看下这个链接http://www.geek-workshop.com/thread-2225-1-1.html,然后改下你的Ds1302Write(unsigned char addr, unsigned char dat)
择一城终老,遇一人白首....
回复

使用道具 举报

0

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2016-5-7
在线时间
7 小时
发表于 2017-12-31 20:51:52 | 显示全部楼层
我就是看了那个博主的理解,然后参考STM32的程序修改的,现上我的STM8S103F3程序
择一城终老,遇一人白首....
回复

使用道具 举报

0

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2016-5-7
在线时间
7 小时
发表于 2017-12-31 20:53:28 | 显示全部楼层
#include "DS1302.h"

void Delay_us(u16 ms);
//初始化时间定义
u8 time_buf[8] = {0x20,0x17,0x12,0x31,0x20,0x23,0x55,0x07}; //初始时间2017年12月20号23点59分55秒 星期三


void DS1302_Init(void)//DS1302初始化
{
  DS1302_RST_OUT();
  DS1302_SCLK_OUT();
  DS1302_SDA_OUT();
  
  DS1302_RST_L();
  DS1302_SCLK_L();
  DS1302_SDA_H();
}

void DS1302_Write_Byte(u8 addr, u8 data)//向DS1302写入一个字节数据
{
  u8 i;
  DS1302_RST_L();
  Delay_us(10);
  DS1302_RST_H();
  addr= addr&0xFE;//最低位置零,写数据
  DS1302_SDA_OUT();//写地址、数据
  for(i=8;i>0;i--)
  {
    if(addr&0x01)
      DS1302_SDA_H();
    else
      DS1302_SDA_L();
    DS1302_SCLK_H();//产生时钟
    Delay_us(10);
    DS1302_SCLK_L();
    addr=addr>>1;
  }
  for(i=8;i>0;i--)
  {
    if(data&0x01)
      DS1302_SDA_H();
    else
      DS1302_SDA_L();
    DS1302_SCLK_H();
    Delay_us(10);
    DS1302_SCLK_L();
    data=data>>1;
  }
  DS1302_RST_L();//停止DS1302总线
}

u8 DS1302_Read_Byte(u8 addr)
{
  u8 i,temp;
  DS1302_RST_L();
  Delay_us(10);
  DS1302_RST_H();
  addr= addr|0x01;//最低位置高,读数据
  DS1302_SDA_OUT();//写地址
  for(i=8;i>0;i--)
  {
    if(addr&0x01)
      DS1302_SDA_H();
    else
      DS1302_SDA_L();
    DS1302_SCLK_H();//产生时钟
    Delay_us(10);
    DS1302_SCLK_L();
    addr=addr>>1;
  }
  DS1302_SDA_IN();//读数据
  for(i=8;i>0;i--)
  {
    temp = temp >> 1;
    if(DS1302_DATA_IN())
      temp |= 0x80;
    else
      temp &= 0x7F;
    DS1302_SCLK_H();
    Delay_us(10);
    DS1302_SCLK_L();
  }
  DS1302_RST_L();//停止DS1302总线
  DS1302_SDA_OUT();//读取字节之前,将IO设置为输入口,读取完之后,要将其改回输出口
  return temp;
}

void DS1302_Write_Time(void)//向DS1302写入时间数据
{
  DS1302_Write_Byte(ds1302_control_add, 0x00);       //关闭写保护
  DS1302_Write_Byte(ds1302_sec_add, 0x80);           //暂停时钟
  //DS1302_Write_Byte(ds1302_charger_add, 0xA9);     //涓流充电
  DS1302_Write_Byte(ds1302_year_add,time_buf[1]);    //年
  DS1302_Write_Byte(ds1302_month_add,time_buf[2]);   //月
  DS1302_Write_Byte(ds1302_date_add,time_buf[3]);    //日
  DS1302_Write_Byte(ds1302_hr_add,time_buf[4]);             //时
  DS1302_Write_Byte(ds1302_min_add,time_buf[5]);     //分
  DS1302_Write_Byte(ds1302_sec_add,time_buf[6]);     //秒
  DS1302_Write_Byte(ds1302_day_add,time_buf[7]);     //周
  DS1302_Write_Byte(ds1302_control_add,0x80);        //打开写保护
}

void DS1302_Read_Time(void)//从DS302读出时钟数据  
{
        time_buf[1] = DS1302_Read_Byte(ds1302_year_add);                    //年
        time_buf[2] = DS1302_Read_Byte(ds1302_month_add);             //月
        time_buf[3] = DS1302_Read_Byte(ds1302_date_add);             //日
        time_buf[4] = DS1302_Read_Byte(ds1302_hr_add);                     //时
        time_buf[5] = DS1302_Read_Byte(ds1302_min_add);                     //分
        time_buf[6] = (DS1302_Read_Byte(ds1302_sec_add))&0x7f;       //秒,屏蔽秒的第7位,避免超出59
        time_buf[7] = DS1302_Read_Byte(ds1302_day_add);                     //周        
}

void DS1302_Get_Time(u8 *time)//DS1302向上层返回时间数据
{
  DS1302_Read_Time();
  time[0]=(time_buf[0]>>4);   //年   
  time[1]=(time_buf[0]&0x0f);
   
  time[2]=(time_buf[1]>>4);   
  time[3]=(time_buf[1]&0x0f);
  
  time[4]=(time_buf[2]>>4);   //月  
  time[5]=(time_buf[2]&0x0f);

  time[6]=(time_buf[3]>>4);   //日   
  time[7]=(time_buf[3]&0x0f);
   
  time[8]=(time_buf[7]&0x07); //星期
   
  time[9]=(time_buf[4]>>4);   //时   
  time[10]=(time_buf[4]&0x0f);   

  time[11]=(time_buf[5]>>4);  //分   
  time[12]=(time_buf[5]&0x0f);   

  time[13]=(time_buf[6]>>4);  //秒
  time[14]=(time_buf[6]&0x0f);
}

void Delay_us(u16 ms)
{
  u8 i=0,j;
   
    for(j=ms;j>0;j--)
    {
      for(i=16;i>0;i--)
      {
        nop();
      }
    }
}

#ifndef _DS1302_H_
#define _DS1302_H_
#include <stm8s.h>

/*******************************************************************************         
//              ----------------------------------------------------------------
//              SCLK   接PC5(SCLK)
//              SDA    接PC6(SDA)
//              RST    接PC7 (CE)
//              ----------------------------------------------------------------
*******************************************************************************/
#define DS1302_SCLK GPIO_PIN_5 //SCLK
#define DS1302_SDA GPIO_PIN_6 //SDA
#define DS1302_RST  GPIO_PIN_7 //CE
#define GPIO_DS1302 GPIOC    //定义要使用的端口A
/**********************************************************/
#define DS1302_RST_OUT()   GPIO_Init(GPIO_DS1302, DS1302_RST, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define DS1302_SCLK_OUT()   GPIO_Init(GPIO_DS1302, DS1302_SCLK, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define DS1302_SDA_OUT()   GPIO_Init(GPIO_DS1302, DS1302_SDA, GPIO_MODE_OUT_PP_HIGH_SLOW)//高速推挽输出高电平
#define DS1302_SDA_IN()   GPIO_Init(GPIO_DS1302, DS1302_SDA, GPIO_MODE_IN_PU_NO_IT)//上拉输入
/**********************************************************/
#define DS1302_RST_H()   GPIO_WriteHigh(GPIO_DS1302, DS1302_RST)
#define DS1302_RST_L()   GPIO_WriteLow(GPIO_DS1302, DS1302_RST)

#define DS1302_SCLK_H()   GPIO_WriteHigh(GPIO_DS1302, DS1302_SCLK)
#define DS1302_SCLK_L()   GPIO_WriteLow(GPIO_DS1302, DS1302_SCLK)

#define DS1302_SDA_H()   GPIO_WriteHigh(GPIO_DS1302, DS1302_SDA)
#define DS1302_SDA_L()   GPIO_WriteLow(GPIO_DS1302, DS1302_SDA)
#define DS1302_DATA_IN()        GPIO_ReadInputPin(GPIO_DS1302,DS1302_SDA)
/**********************************************************/
//DS1302地址定义
#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
/**********************************************************/

void DS1302_Init(void);
void DS1302_Write_Byte(u8 addr, u8 data);
u8 DS1302_Read_Byte(u8 addr);
void DS1302_Write_Time(void);
void DS1302_Read_Time(void);
void DS1302_Get_Time(u8 *time);

/**********************************************************/
#endif







择一城终老,遇一人白首....
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2018-1-1 00:46:09 | 显示全部楼层
帮顶
回复

使用道具 举报

2

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2017-11-6
在线时间
15 小时
发表于 2018-1-26 08:25:02 | 显示全部楼层
读一个字节的时序写错了
回复

使用道具 举报

2

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2017-11-6
在线时间
15 小时
发表于 2018-1-26 08:31:41 | 显示全部楼层
scl先置高,然后读取一个位的数据,scl再置低,可以去网上看看DS1302的时序图,是在时钟线scl高位的时候读取数据的
回复

使用道具 举报

4

主题

68

帖子

0

精华

高级会员

Rank: 4

积分
728
金钱
728
注册时间
2016-7-21
在线时间
281 小时
发表于 2021-3-23 17:17:55 | 显示全部楼层
经年殇 发表于 2017-12-31 20:53
#include "DS1302.h"

void Delay_us(u16 ms);

我用你的读出来的数是0,是否可以给整个工程看一下呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 14:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表