找回密码
 立即注册
查看: 66|回复: 4

32G12K128 FreeRTOS 下读取DS1302失败

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-27 17:49:08
已绑定手机

5

主题

15

回帖

131

积分

注册会员

积分
131
发表于 2025-4-15 18:12:22 | 显示全部楼层 |阅读模式
我采用论坛上DS1302的例程,读取DS1302失败。我用逻辑分析仪抓了波形,SPI时钟大约3us,延时应该够了。请问调试经验丰富的人,能否从波形图上看出问题所在。
截图202504151812361855.jpg
截图202504151815504012.jpg
截图202504151817242412.jpg
回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-15 18:18:00 | 显示全部楼层
在STC32G12K128微控制器上使用FreeRTOS实时操作系统读取DS1302实时时钟模块时遇到读取失败的问题,可能涉及多个方面的原因。以下是一些可能的原因及相应的解决方案,供您参考和排查。

1. 硬件连接问题
首先,确保DS1302模块与STC32G12K128微控制器的硬件连接正确无误。DS1302通常需要以下引脚连接:
VCC:电源正极,通常为3.3V或5V。
GND:电源地。
CLK:时钟信号,连接到微控制器的GPIO引脚。
DAT:数据信号,连接到微控制器的GPIO引脚。
RST:复位信号,连接到微控制器的GPIO引脚。

请检查这些引脚是否连接正确,并确保电源电压符合DS1302的要求。

2. 引脚配置与初始化
在软件中,确保正确配置了与DS1302通信的GPIO引脚。通常需要将CLK、DAT和RST引脚配置为输出模式,并在初始化时设置适当的电平状态。例如:
  1. c
  2. void DS1302Init(void) {
  3.     GPIOInitTypeDef GPIOInitStruct;
  4.     // 配置CLK、DAT、RST引脚为输出模式
  5.     GPIOInitStruct.Pin = DS1302CLKPIN | DS1302DATPIN | DS1302RSTPIN;
  6.     GPIOInitStruct.Mode = GPIOMODEOUTPUTPP;
  7.     GPIOInitStruct.Pull = GPIONOPULL;
  8.     GPIOInitStruct.Speed = GPIOSPEEDFREQLOW;
  9.     HALGPIOInit(DS1302GPIOPORT, &GPIOInitStruct);
  10.     // 初始化引脚状态
  11.     HALGPIOWritePin(DS1302GPIOPORT, DS1302RSTPIN, GPIOPINRESET);
  12.     HALGPIOWritePin(DS1302GPIOPORT, DS1302CLKPIN, GPIOPINRESET);
  13.     HALGPIOWritePin(DS1302GPIOPORT, DS1302DATPIN, GPIOPINRESET);
  14. }
复制代码

3. 时序问题
DS1302的通信协议对时序有严格的要求。确保在读取和写入数据时,严格按照DS1302的时序图进行操作。以下是一个简单的读取字节的示例:

```c
uint8t DS1302ReadByte(void) {
    uint8t data = 0;
    uint8t i;

    for (i = 0; i < 8; i++) {
        HALGPIOWritePin(DS1302GPIOPORT, DS1302CLKPIN, GPIOPINSET);
        HALDelay(1); // 适当延时
        data |= HALGPIOReadPin(DS1302GPIOPORT, DS1302DATPIN)

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-4-15 18:28:00 | 显示全部楼层


普中开发板上测过的例程参考下:
26-DS1302时钟.zip (2.17 MB, 下载次数: 3)
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-15 20:41:42 | 显示全部楼层
  1. #define                Protrct_Enable        0x80                //使能写保护
  2. #define                Protect_Disable        0x00                //禁用写保护
  3. #define                Write_Protect        0x8e                //定义写保护寄存器地址
  4. #define                Write_TCS                0x90                //定义写充电寄存器地址
  5. #define                Write_Year                0x8c                //定义写年寄存器地址
  6. #define                Write_Week                0x8a                //定义写星期寄存器地址
  7. #define                Write_Month                0x88                //定义写月寄存器地址
  8. #define                Write_Date                0x86                //定义写日寄存器地址
  9. #define                Write_Hour                0x84                //定义写小时寄存器地址
  10. #define                Write_Minute        0x82                //定义写分钟寄存器地址
  11. #define                Write_Second        0x80                //定义写秒钟寄存器地址
  12. #define                Read_TCS                0x91                //定义读充电寄存器地址
  13. #define                Read_Year                0x8d                //定义读年寄存器地址
  14. #define                Read_Week                0x8b                //定义读星期寄存器地址
  15. #define                Read_Month                0x89                //定义读月寄存器地址
  16. #define                Read_Date                0x87                //定义读日寄存器地址
  17. #define                Read_Hour                0x85                //定义读小时寄存器地址
  18. #define                Read_Minute                0x83                //定义读分钟寄存器地址
  19. #define                Read_Second                0x81                //定义读秒钟寄存器地址
  20. #define                TCS_OFF                        0xa0                //设置DS1302充电方式为关闭
  21. #define                TCS_1D2K                0xa5                //设置DS1302充电方式为1个二极管,2K电阻
  22. #define                TCS_1D4K                0xa6                //设置DS1302充电方式为1个二极管,4K电阻
  23. #define                TCS_1D8K                0xa7                //设置DS1302充电方式为1个二极管,8K电阻
  24. #define                TCS_2D2K                0xa9                //设置DS1302充电方式为2个二极管,2K电阻
  25. #define                TCS_2D4K                0xaa                //设置DS1302充电方式为2个二极管,4K电阻
  26. #define                TCS_2D8K                0xab                //设置DS1302充电方式为2个二极管,8K电阻
  27. #define                Init_Year                0x19                //初始化年
  28. #define                Init_Week                0x03                //初始化星期
  29. #define                Init_Month                0x08                //初始化月
  30. #define                Init_Date                0x28                //初始化日
  31. #define                Init_Hour                0x14                //初始化小时
  32. #define                Init_Minute                0x13                //初始化分钟
  33. #define                Init_Second                0x00                //初始化秒钟
复制代码
  1. /*----------------------------DS1302写数据----------------------------*/
  2. //void Write_DS1302 (unsigned char addr,unsigned char dat)
  3. //{
  4. //        unsigned char i,temp;                                //声明移位次数、临时变量
  5. //        DS1302_RST=0;                                                //拉低DS1302_RST,禁止DS1302数据传输
  6. //        DS1302_CLK=0;                                                //拉低DS1302_CLK
  7. //        DS1302_RST=1;                                                //DS1302_RST为高,使能DS1302数据传输
  8. //        for(i=8;i>0;i--)                                        //循环移位8次
  9. //        {
  10. //                DS1302_CLK=0;                                        //拉低DS1302_CLK
  11. //                temp=addr;                                                //把地址赋值给临时变量
  12. //                DS1302_DAT=(bit)(temp&0x01);        //每次传输低字节,数据放到数据端口
  13. //                DS1302_CLK=1;                                        //拉高DS1302_CLK,锁存数据
  14. //                addr>>=1;                                                //地址右移一位
  15. //        }
  16. //        for(i=8;i>0;i--)                                        //循环移位8次
  17. //        {
  18. //                DS1302_CLK=0;                                        //拉低DS1302_CLK
  19. //                temp=dat;                                                //把数据赋值给临时变量
  20. //                DS1302_DAT=(bit)(temp&0x01);        //只取最低一位
  21. //                DS1302_CLK=1;                                        //拉高DS1302_CLK,锁存数据
  22. //                dat>>=1;                                                //右移一位
  23. //        }
  24. //        DS1302_CLK=0;                                                //拉低DS1302_CLK
  25. //        DS1302_RST=0;                                                //拉低DS1302_RST,禁止DS1302数据传输
  26. //}
  27. /*----------------------------DS1302读数据----------------------------*/
  28. unsigned char Read_DS1302(unsigned char addr)
  29. {
  30.         unsigned char i,temp,dat,dat1;
  31.         DS1302_RST=0;                                                //拉低DS1302_RST,禁止DS1302数据传输
  32.         DS1302_CLK=0;                                                //拉低DS1302_CLK
  33.         DS1302_RST=1;                                                //DS1302_RST为高,使能DS1302数据传输
  34.         for(i=8;i>0;i--)                                        //循环移位8次
  35.         {
  36.                 DS1302_CLK=0;                                        //拉低DS1302_CLK
  37.                 temp=addr;                                                //把地址赋值给临时变量
  38.                 DS1302_DAT=(bit)(temp&0x01);        //每次传输低位
  39.                 DS1302_CLK=1;                                        //拉高DS1302_CLK,锁存数据
  40.                 addr>>=1;                                                //addr右移一位
  41.         }
  42.         P3M0=P3M0&0x3d;
  43.         for(i=8;i>0;i--)                                        //循环移位8次
  44.         {
  45.                 ACC>>=1;                                                //ACC右移一位
  46.                 DS1302_CLK=1;                                        //先拉高DS1302_CLK
  47.                 DS1302_CLK=0;                                        //拉低DS1302_CLK,准备读取数据
  48.                 ACC_7=DS1302_DAT;                                //读取数据,ACC_7为存放数据变量的最高位一位
  49.         }
  50.         P3M0=P3M0|0x02;
  51.         DS1302_CLK=0;                                                //拉低DS1302_CLK
  52.         DS1302_RST=0;                                                //拉低DS1302_RST,禁止DS1302数据传输
  53.         dat=ACC;                                                        //把ACC赋值给dat
  54.         dat1=dat&0xf0;                                                //数据进制转换, 提取高四位
  55.         dat1>>=4;                                                        //移动到低四位,作为十位
  56.         dat=dat&0x0f;                                                //提取低四位,作为个位
  57.         dat=dat+dat1*10;                                        //得到的十进制数
  58.         return dat;                                                        //返回十进制值
  59. }
  60. /*----------------------------初始化DS1302----------------------------*/
  61. //void Init_DS1302(void)
  62. //{
  63. //        Write_DS1302(Write_Protect,Protect_Disable);        //禁用写保护
  64. //        Write_DS1302(Write_TCS,TCS_2D8K);                                //初始化充电方式
  65. //        Write_DS1302(Write_Year,Init_Year);                                //初始化年
  66. //        Write_DS1302(Write_Week,Init_Week);                                //初始化星期
  67. //        Write_DS1302(Write_Month,Init_Month);                        //初始化月
  68. //        Write_DS1302(Write_Date,Init_Date);                                //初始化日
  69. //        Write_DS1302(Write_Hour,Init_Hour);                                //初始化小时
  70. //        Write_DS1302(Write_Minute,Init_Minute);                        //初始化分钟
  71. //        Write_DS1302(Write_Second,Init_Second);                        //初始化秒钟
  72. //        Write_DS1302(Write_Protect,Protrct_Enable);                //使能写保护
  73. //}
复制代码


DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:10
  • 最近打卡:2025-04-27 17:49:08
已绑定手机

5

主题

15

回帖

131

积分

注册会员

积分
131
发表于 2025-4-16 12:46:46 | 显示全部楼层
感谢楼上各位老师,问题解决了。最初我是参考这个帖子DS1302 自用代码 (通用) - 老鸟反刍/吐槽,新手乐园,毕业设计 国芯技术交流网站 - AI32位8051交流社区,移植代码的。读时间寄存器参考了这段代码。//========================================================================
//                                                                                                 读取时间
// ***********************************************************************
//========================================================================        
void Ds1302ReadTime()
{
        unsigned char n;
        unsigned char dd[10]="";
        for (n=0; n<7; n++)
        {
                TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
        }
        for (n=0; n<7; n++)
        {
                TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
        }
        Year=BCD_DEC(TIME[6]);
        Week=BCD_DEC(TIME[5]);
        Month=BCD_DEC(TIME[4]);
        day=BCD_DEC(TIME[3]);
        Hour=BCD_DEC(TIME[2]);
        Minute=BCD_DEC(TIME[1]);
        Second=BCD_DEC(TIME[0]);
} 我做了一些改动,我用addr =0x81 读秒寄存器,每读一次地址加2. 结果读第二轮时,没有把地址恢复到0x81.  经过这次教训,我也感觉这段代码重复读2次,似乎没有必要,没有对读出来的时间寄存器的数据做时间有效性的校验,读取多次,也只是使用最后一次的数据。提高不了读取成功的机率。除非芯片本身固有的特性,第二轮读取的数据成功几率更高。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 23:28 , Processed in 0.117329 second(s), 76 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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