你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32G4 NUCLEO G431RB】+ DS1307驱动仍未成功

[复制链接]
老牛洋车 发布时间:2019-9-13 18:26
    使用GPIO模拟I2C成功驱动DS1302日历模块之后,便尝试继续驱动DS1307日历模块。这两个模块的驱动有些不同,DS1307也许是符合标准I2C通讯的,而DS1302则不需要器件的I2C地址,只要直接对其进行读写操作。下图是两个模块的实物,DS1307模块上还集成了AT24C32flash,本次尚未对其操作。
DS130x_1.jpg

    这是模块的另一面,DS1302上添加了三个上拉电阻。
DS130x_0.jpg

    测试过程不顺利,从网上搜索了多个参考例子,但读出的数据全是零,显然是没有驱动成功。然后又准备改用硬件I2C来驱动,先参照范例程序对I2C的读写操作进行了分析,我将I2C读、写操作的函数放在一起比较,基本上了解其操作过程,下面是对比的结果。
  1. /**
  2.   * @brief  Receives in master mode an amount of data in blocking mode.
  3.             在主模式下以阻塞模式接收大量数据。
  4.   * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  5.   *                the configuration information for the specified I2C.
  6.   * @param  DevAddress Target device address: The device 7 bits address value
  7.   *         in datasheet must be shifted to the left before calling the interface
  8.   * @param  pData Pointer to data buffer
  9.   * @param  Size Amount of data to be sent
  10.   * @param  Timeout Timeout duration
  11.   * @retval HAL status
  12.   */
  13. HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
  14. HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
  15. {
  16.   uint32_t tickstart;

  17.   if (hi2c->State == HAL_I2C_STATE_READY)
  18.   {
  19.     /* Process Locked锁定进程 */
  20.     __HAL_LOCK(hi2c);

  21.     /* Init tickstart for timeout management超时管理开始计时 */
  22.     tickstart = HAL_GetTick();

  23.     if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
  24.     {
  25.       return HAL_ERROR;
  26.     }

  27.     hi2c->State     = HAL_I2C_STATE_BUSY_TX;
  28.     hi2c->Mode      = HAL_I2C_MODE_MASTER;
  29.     hi2c->ErrorCode = HAL_I2C_ERROR_NONE;

  30.     /* Prepare transfer parameters准备传输参数 */
  31.     hi2c->pBuffPtr  = pData;
  32.     hi2c->XferCount = Size;
  33.     hi2c->XferISR   = NULL;

  34.     /* Send Slave Address发送从机地址 */
  35.     /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART
  36.        如果hi2c->xfercount>max戋nbyte戋u size并生成restart,则将nbytes设置为write和reload */
  37.     if (hi2c->XferCount > MAX_NBYTE_SIZE)
  38.     {
  39.       hi2c->XferSize = MAX_NBYTE_SIZE;
  40. //T    I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
  41. //R   I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
  42.     }
  43.     else
  44.     {
  45.       hi2c->XferSize = hi2c->XferCount;
  46. //T    I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
  47. //R    I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
  48.     }

  49.     while (hi2c->XferCount > 0U)
  50.     {
  51.       /* Wait until TXIS flag is set等待Txis标志设置完毕 */
  52. //T      if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
  53.       /* Wait until RXNE flag is set等待rxne标志设置完毕 */
  54. //R   if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
  55.       {
  56.         return HAL_ERROR;
  57.       }

  58.       /* Write data to TXDR将数据写入TXDR */
  59. //T      hi2c->Instance->TXDR = *hi2c->pBuffPtr;
  60.      /* Read data from RXDR */
  61. //R      *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;

  62.       /* Increment Buffer pointer移动缓冲区指针 */
  63.       hi2c->pBuffPtr++;

  64.       hi2c->XferCount--;
  65.       hi2c->XferSize--;

  66.       if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
  67.       {
  68.          /* Wait until TCR flag is set等待设置TCR标志 */
  69.         if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
  70.         {
  71.           return HAL_ERROR;
  72.         }

  73.         if (hi2c->XferCount > MAX_NBYTE_SIZE)
  74.         {
  75.           hi2c->XferSize = MAX_NBYTE_SIZE;
  76.           I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
  77.         }
  78.         else
  79.         {
  80.           hi2c->XferSize = hi2c->XferCount;
  81.           I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
  82.         }
  83.       }
  84.     }

  85.     /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated
  86.        无需检查TC标志,在自动结束模式下自动生成停止 */
  87.     /* Wait until STOPF flag is set等待设置stopf标志 */
  88.     if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
  89.     {
  90.       return HAL_ERROR;
  91.     }

  92.     /* Clear STOP Flag */
  93.     __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);

  94.     /* Clear Configuration Register 2清除配置寄存器2 */
  95.     I2C_RESET_CR2(hi2c);

  96.     hi2c->State = HAL_I2C_STATE_READY;
  97.     hi2c->Mode  = HAL_I2C_MODE_NONE;

  98.     /* Process Unlocked解锁 */
  99.     __HAL_UNLOCK(hi2c);

  100.     return HAL_OK;
  101.   }
  102.   else
  103.   {
  104.     return HAL_BUSY;
  105.   }
  106. }
复制代码



    然后参照范例写了对DS1307进行读写操作的函数,但调试了两天都不成功,不知道是错在了那里,下面是对DS1307进行读写操作的代码。
  1. #define I2C_ADDRESS  DS1307_ADDR

  2. /******************************************************************************************
  3. * 函数名称: DS1307_I2C_Read()
  4. * 功能说明: 从DS1307地址addr开始获取size个字节的数据,获取的数据存储在全局变量DS_Buff中
  5. * 输    入: uint8_t addr        获取数据的开始地址
  6. *                        uint8_t size        要获取的数据个数(1~8)
  7. * 输    出: ui08    0=RET_OK 成功从DS1307获取数据  >0=从DS1307获取数据过程中出现错误
  8. ******************************************************************************************/
  9. uint8_t DS1307_I2C_Read(uint8_t addr,uint8_t size)
  10. {
  11.     DS_Buff[0] = addr;    //将要读取的起始地址发送给DS1307
  12.     while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|1, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
  13.     {
  14.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  15.         {
  16.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS1307WR Error");
  17.                         return 1;
  18.         }
  19.     }
  20.     while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, size, 10000) != HAL_OK)
  21.     {
  22.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  23.         {
  24.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS1307RD Error");
  25.                         return 2;
  26.         }
  27.     }
  28.         return 0;
  29. }

  30. /******************************************************************************************
  31. * 函数名称: DS1307_I2C_Write()
  32. * 功能说明: 从DS1307地址addr开始写入size个字节的数据,数据存储在全局变量DS_Buff中
  33. * 输    入: uint8_t addr        写入数据的开始地址
  34. *                        uint8_t size        要写入的数据个数(1~8)
  35. * 输    出: ui08    0=RET_OK 成功写入数据  >0=从DS1307写入数据过程中出现错误
  36. ******************************************************************************************/
  37. uint8_t DS1307_I2C_Write(uint8_t addr,uint8_t size)
  38. {
  39.     uint8_t i;
  40.         i = DS_Buff[0];
  41.     DS_Buff[0] = addr;    //将要写入的起始地址发送给DS1307
  42.     while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|1, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
  43.     {
  44.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  45.         {
  46.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS1307TX Error");
  47.                         return 1;
  48.         }
  49.     }
  50.         DS_Buff[0] = i;
  51.     while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|1, (uint8_t *)DS_Buff, size, 10000) != HAL_OK)
  52.     {
  53.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  54.         {
  55.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS1307TX Error");
  56.                         return 2;
  57.         }
  58.     }
  59.         return 0;
  60. }
复制代码



    这是初始化DS1307的代码,首先读出秒寄存器数据,判断其是否在工作,若尚未在工作就对其进行初始设置。在这里就出错了,读不出正确数据。
  1. /******************************************************************************************
  2. * 函数名称:        DS1307_Init()
  3. * 功能说明: 用当前日期(yesr,month,day,hour,minute)初始化DS1307
  4. * 输    入: 无
  5. * 输    出: uint8_t        0=RET_OK 初始化成功        1=RET_ERR 初始化出错
  6. ******************************************************************************************/
  7. uint8_t DS1307_Init(void)
  8. {
  9.     uint8_t temp;
  10.        
  11. //        temp = DS1307_Read(0,1);
  12.     temp = DS1307_I2C_Read(0,1);
  13.     if(temp        > 0)
  14.                 LCD_write_ASCII(0,3,1,(uint8_t *)"DS1307 R Error");      //读秒数据,判断DS1307是否在工作
  15.         else
  16.                 LCD_write_ASCII(0,3,1,(uint8_t *)"DS1307 Read OK");
  17.         HAL_Delay(1000);
  18.         LCD_write_value(0,4,5,0,0,temp);
  19.        
  20.         if(DS_Buff[0]>127){
  21. /*       
  22.         DS1307_Reg.yer.b.yer10 = 1;      //年
  23.         DS1307_Reg.yer.b.yer1  = 9;
  24.         DS1307_Reg.mon.b.mon10 = 0;      //月
  25.         DS1307_Reg.mon.b.mon1  = 9;
  26.         DS1307_Reg.dat.b.dat10 = 0;      //日
  27.         DS1307_Reg.dat.b.dat1  = 9;
  28.         DS1307_Reg.day.b.day = 3;        //周
  29.         DS1307_Reg.hur.b.hur10 = 1;      //时
  30.         DS1307_Reg.hur.b.hur1  = 0;
  31.         DS1307_Reg.min.b.min10 = 0;      //分
  32.         DS1307_Reg.min.b.min1  = 0;
  33.         DS1307_Reg.sec.b.sec10 = 0;      //秒
  34.         DS1307_Reg.sec.b.sec1  = 0;
  35.         DS1307_Reg.sec.b.CLK_H = 0;      //开启时钟
  36.         DS1307_Reg.sqw.b.SQWE  = 1;      //使能方波输出
  37.         DS1307_Reg.sqw.b.RS   = 0;       //方波频率选择:1Hz
  38. */
  39.         year = 2019;
  40.                 month = 9;
  41.                 day = 12;
  42.                 week = 4;
  43.                 hour = 12;
  44.                 minute = 30;
  45.                
  46.         DS_Buff[0] = 0;                  //秒
  47.         temp = ((minute/10)<<4|(minute%10));
  48.         DS_Buff[1] = temp;               //分
  49.         temp = ((hour/10)<<4|(hour%10));
  50.         DS_Buff[2] = temp;               //时
  51.         temp = ((day/10)<<4|(day%10));
  52.         DS_Buff[3] = temp;               //日
  53.    
  54.         DS_Buff[4] = week;               //星期
  55.         temp = ((month/10)<<4|(month%10));
  56.             DS_Buff[5] = temp;               //月
  57.         temp = ((year%100)/10<<4|(year%10));
  58.         DS_Buff[6] = temp;               //年
  59.        
  60.         DS_Buff[7] = 32;                 //0010 0000 = 允许按1Hz输出方波

  61. //        return DS1307_Write(0,8);
  62.         return DS1307_I2C_Write(0,8);
  63.     }
  64.         else
  65.                 return 1;
  66. }

  67. /******************************************************************************************
  68. * 函数名称:        DS1307_Config()
  69. * 功能说明: 配置DS1307_OUT中断引脚
  70. * 输    入: 无
  71. * 输    出: 无
  72. ******************************************************************************************/
  73. void DS1307_Config(void)
  74. {
  75. /*
  76.     GPIO_InitTypeDef GPIO_InitStruct;

  77.     GPIO_InitStruct.Pin = DS_OUT;
  78.     GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  79.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  80.     HAL_GPIO_Init(DS_PORT, &GPIO_InitStruct);
  81. */
  82.        
  83.         SI2C_Config();                       //配置I2C
  84. }


  85. /******************************************************************************************
  86. * 函数名称:        DS1307_read_date()
  87. * 功能说明: 读取DS1307日期时间数据
  88. * 输    入: 无
  89. * 输    出: 无
  90. ******************************************************************************************/
  91. void DS1307_read_date(void)
  92. {
  93. //    DS1307_Read(0,7);                                      //读取前7个字节数据
  94.     DS1307_I2C_Read(0,7);                                    //读取前7个字节数据
  95.     second = ((DS_Buff[0]&0x70)>>4)*10 + (DS_Buff[0]&0x0F);//秒,屏蔽秒的第7位的标志
  96.         minute = ((DS_Buff[1]&0x70)>>4)*10 + (DS_Buff[1]&0x0F);//分(取低7位)
  97.         hour = ((DS_Buff[2]&0x10)>>4)*10 + (DS_Buff[2]&0x0F);  //时(取低5位)
  98.         week = (DS_Buff[3]&0x07);                              //周(取低3位)
  99.     day = ((DS_Buff[4]&0x30)>>4)*10 + (DS_Buff[4]&0x0F);   //日(取低6位)
  100.     month = ((DS_Buff[5]&0x10)>>4)*10 + (DS_Buff[5]&0x0F); //月(取低5位)
  101.         year = 2000 + (DS_Buff[6]>>4)*10 + (DS_Buff[6]&0x0F);  //年

  102. }


  103. /******************************************************************************************
  104. * 函数名称:        DS1307_write_date()
  105. * 功能说明: 读取DS1307日期时间数据
  106. * 输    入: 无
  107. * 输    出: 无
  108. ******************************************************************************************/
  109. void DS1307_write_date(void)
  110. {
  111.     uint8_t temp;
  112.        
  113.     DS_Buff[0] = 0;                      //秒
  114.     temp = ((minute/10)<<4|(minute%10));
  115.     DS_Buff[1] = temp;                   //分
  116.     temp = ((hour/10)<<4|(hour%10));
  117.     DS_Buff[2] = temp;                   //时
  118.     temp = ((day/10)<<4|(day%10));
  119.     DS_Buff[3] = temp;                   //日
  120.    
  121.     DS_Buff[4] = week;                   //星期
  122.     temp = ((month/10)<<4|(month%10));
  123.     DS_Buff[5] = temp;                   //月
  124.     temp = ((year%100)/10<<4|(year%10));
  125.     DS_Buff[6] = temp;                   //年
  126.        
  127. //    DS1307_Write(0,7);                   //写入前7个字节数据
  128.     DS1307_I2C_Write(0,7);               //写入前7个字节数据
  129. }
复制代码



收藏 评论4 发布时间:2019-9-13 18:26

举报

4个回答
老牛洋车 回答时间:2019-9-13 20:44:08
rillhu 发表于 2019-9-13 20:19
DS1307应该不是标准的I2C通信协议吧?看看spec,貌似是一个不标准的spi

    DS1302不需要器件地址,直接对芯片进行读写操作,而DS1307则需要首先在I2C总线上输出从设备地址,得到应答后再进行通讯,而且我买的这个模块DS1307与AT24C32两个芯片的SCL和SDA是连通的,也就是挂在同一I2C总线上,需要通过器件地址来操作其中的芯片,所以应该是标准的I2C通讯。
rillhu 回答时间:2019-9-13 20:19:03
DS1307应该不是标准的I2C通信协议吧?看看spec,貌似是一个不标准的spi
老牛洋车 回答时间:2019-9-13 22:25:48
晚上又测试了几个小时,发现了一些问题,修改后仍未完成驱动,看来明天要用逻辑分析仪来观察引脚电平了。
老牛洋车 回答时间:2019-9-14 15:02:20
今天用逻辑分析仪尝试抓取I2C的时序图,竟然没有收到任何信号,说明I2C尚未正确配置好,只好改用范例来测试DS1307。

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版