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

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

[复制链接]
hujjj 发布时间: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个回答
hujjj 回答时间: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
hujjj 回答时间:2019-9-13 22:25:48
晚上又测试了几个小时,发现了一些问题,修改后仍未完成驱动,看来明天要用逻辑分析仪来观察引脚电平了。
hujjj 回答时间:2019-9-14 15:02:20
今天用逻辑分析仪尝试抓取I2C的时序图,竟然没有收到任何信号,说明I2C尚未正确配置好,只好改用范例来测试DS1307。

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

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