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

使用HAL库硬件I2C时如何设置器件地址?

[复制链接]
hujjj 提问时间:2019-9-18 15:32 /
    我使用的模块是包含了DS1307的AT24C32两个I2C通讯的芯片,开始准备启用硬件I2C,但测试了多天都没有成功,后来只要改为GPIO模拟I2C才成功驱动这两个芯片。现在我仍想继续尝试用硬件I2C,但一直不知道如何在操作前设定器件的地址,我使用的是HAL库,在此请各位指教,谢谢!
收藏 评论16 发布时间:2019-9-18 15:32

举报

16个回答
ldptest 回答时间:2019-9-18 17:20:23
是指设置从地址码? 无标题.jpg
/* I2C1 init function */
void MX_I2C1_Init(void)
{

  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

}



还是访问器件的地址?
HAL_I2C_Mem_Write(&hi2c1,ADDRESS,DC,I2C_MEMADD_SIZE_8BIT,&Byte,1,I2C_TIMEOUT);
hujjj 回答时间:2019-9-18 17:39:52
谢谢回复!是从器件的地址。
那是不是每次读写不同的器件之前都要调用I2C_Init()函数?
morphlings2014 回答时间:2019-9-19 09:30:35
使用库函数读写的时候就能设置地址,不需要初始化那里设置,HAL_I2C_Mem_Read(i2c_handler, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, Buffer, Length, 1000);可以看到第二哥参数是设备地址,第三个就是寄存器地址。
hujjj 回答时间:2019-9-19 09:57:35
morphlings2014 发表于 2019-9-19 09:30
使用库函数读写的时候就能设置地址,不需要初始化那里设置,HAL_I2C_Mem_Read(i2c_handler, Addr, (uint16_ ...

谢谢指教,在再试试看。
回答时间:2019-9-19 11:19:12
参考代码如下,我测试没有问题的。DS1307
         uint8_t data1[7],data[8];        
         uint8_t ch;

         ch = 0x00;

         if(HAL_I2C_Master_Transmit(&hi2c1,0xD0,(uint8_t*)&ch,1,10000) != HAL_OK)
         {
                   return;
         }

         if(HAL_I2C_Master_Receive(&hi2c1,0xD0,data1,7,10000) != HAL_OK)
         {
                   return;
         }      
hujjj 回答时间:2019-9-19 11:55:18
    按照四楼老师的提示使用HAL_I2C_Mem_Read()函数似乎可以读出数据了,但不知为何,读出的第一个数据没有问题,而后面的数据则不正确,还在继续测试中。下面是读数据时的时序图:
    发出器件地址和内存地址的时序是正确的
I2C_MEM_Read_00.jpg


    连续读入了7个字节的数据
I2C_MEM_Read_01.jpg

    但读入的数据却不同于DS1307内存数据,DS1307中有时间和日期数据,而读出的却只是1或0.
I2C_MEM_Read_02.jpg

    这是读连续7个字节的时序图
I2C_MEM_Read_03.jpg


    读写DS1307的函数如下:
/******************************************************************************************
* 函数名称: DS1307_I2C_Read()
* 功能说明: 读DS1307的日历数据,并转换为各自的变量值
* 输    入: 无
* 输    出: 0 = 成功从DS1307获取数据  >0 = 从DS1307获取数据过程中出现错误
******************************************************************************************/
void DS1307_I2C_Read(void)
{
    while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
// while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
    {
        if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
        {
            LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Read_Error!");
        }
    }
    second = ((DS_Buff[0]&0x70)>>4)*10 + (DS_Buff[0]&0x0F);//秒,屏蔽秒的第7位的标志
minute = ((DS_Buff[1]&0x70)>>4)*10 + (DS_Buff[1]&0x0F);//分(取低7位)
hour = ((DS_Buff[2]&0x30)>>4)*10 + (DS_Buff[2]&0x0F);  //时(取低5位)
week = (DS_Buff[3]&0x07);                              //周(取低3位)
    day = ((DS_Buff[4]&0x30)>>4)*10 + (DS_Buff[4]&0x0F);   //日(取低6位)
    month = ((DS_Buff[5]&0x10)>>4)*10 + (DS_Buff[5]&0x0F); //月(取低5位)
year = 2000 + (DS_Buff[6]>>4)*10 + (DS_Buff[6]&0x0F);  //年
}
/******************************************************************************************
* 函数名称: DS1307_I2C_Write()
* 功能说明: 将当前的日历数据写入DS1307
* 输    入: 无
* 输    出: 0 = 成功写入数据  >0 = DS1307写入数据过程中出现错误
******************************************************************************************/
void DS1307_I2C_Write(void)
{
    uint8_t temp;
    DS_Buff[0] = 0;                      //秒
    temp = ((minute/10)<<4|(minute%10));
    DS_Buff[1] = temp;                   //分
    temp = ((hour/10)<<4|(hour%10));
    DS_Buff[2] = temp;                   //时
    DS_Buff[3] = week;                   //星期
    temp = ((day/10)<<4|(day%10));
    DS_Buff[4] = temp;                   //日
    temp = ((month/10)<<4|(month%10));
    DS_Buff[5] = temp;                   //月
    temp = ((year%100)/10<<4|(year%10));
    DS_Buff[6] = temp;                   //年
    while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
//    while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
    {
        if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
        {
            LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Write_Erro!");
//   return 2;
        }
    }
// return 0;
}


toofree 回答时间:2019-9-19 12:50:07
从图上看,读时序似乎没有问题。
你看一下你的写时序逻辑是什么要样的吧
hujjj 回答时间:2019-9-19 14:31:43
安 发表于 2019-9-19 11:19
参考代码如下,我测试没有问题的。DS1307
         uint8_t data1[7],data[8];        
         uint8_t c ...

    按照您的代码示例,确实能够对DS1307进行读写操作,不知为何我原来用这个函数时,这个参数却出现在第2个字节,第1个字节是0xF0(见下图):

    第一个字节是0xF0,第二个字节才是地址参数0xD0,以至于我以为这个地址参数是要读取的内存地址呢。
I2CWriteAddrss_4.jpg


    下面是一个完整的读出7个字节内容的时序:
DS1307_I2C_22.jpg


    这是放大后的时序:
DS1307_I2C_20.jpg


    这是读出的内容:
DS1307_I2C_21.jpg


    从目前测试的情况看,用HAL_I2C_Receive()和HAL_I2C_Transmit()函数对DS1307进行操作是没有问题了,但用HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()函数对DS1307进行操作却还存在问题,还需要继续测试排错。
    另外有个疑问:用HAL_I2C_Receive()和HAL_I2C_Transmit()函数是不是只能从0字节开始读写操作,不能对某个指定的字节进行操作?


hujjj 回答时间:2019-9-19 14:42:23
下面是分别用HAL_I2C_Receive()和HAL_I2C_Transmit()函数,HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()函数对DS1307进行操作的函数:

  1. /******************************************************************************************
  2. * 函数名称: DS1307_I2C_Transmit(uint8_t size)
  3. * 功能说明: 写数据到DS1307
  4. * 输    入: size 数据个数(要写入数据在全局数组DS_Buff中)
  5. * 输    出: 0 = 成功写入  1 = 写数据过程中出现错误
  6. ******************************************************************************************/
  7. uint8_t DS1307_I2C_Transmit(uint8_t size)
  8. {
  9.    
  10.         DS1307_DataToBuff();      //将时间及日期数据转换到Buff数组中
  11.         if(HAL_I2C_Master_Transmit(&hi2c1,0xD0,(uint8_t*)DS_Buff ,size,10000) != HAL_OK)
  12.     {
  13.         return 1;
  14.     }
  15.         return 0;
  16. }

  17. /******************************************************************************************
  18. * 函数名称: DS1307_I2C_Receive(uint8_t size)
  19. * 功能说明: 从DS1307读出数据
  20. * 输    入: size 数据个数(读出的数据在全局数组DS_Buff中)
  21. * 输    出: 0 = 成功读出  1 = 读数据过程中出现错误
  22. ******************************************************************************************/
  23. uint8_t DS1307_I2C_Receive(uint8_t size)
  24. {
  25.     if(HAL_I2C_Master_Receive(&hi2c1,0xD0,DS_Buff,7,10000) != HAL_OK)
  26.     {
  27.         return 1;
  28.     }
  29.     if(size == 1){               //检查DS1307是否需要初始化
  30.                 if(DS_Buff[0]>127){
  31.             year = 2019;
  32.                     month = 9;
  33.                     day = 18;
  34.                     week = 3;
  35.                     hour = 9;
  36.                     minute = 1;
  37.                
  38.             DS1307_DataToBuff();
  39.                         DS1307_I2C_Transmit(8);
  40.                 }
  41.         }
  42.         else{
  43.             DS1307_BuffToData();
  44.     }
  45.         return 0;       
  46. }
  47.                  
  48. /******************************************************************************************
  49. * 函数名称: DS1307_I2C_Read()
  50. * 功能说明: 读DS1307的日历数据,并转换为各自的变量值
  51. * 输    入: 无
  52. * 输    出: 0 = 成功从DS1307获取数据  >0 = 从DS1307获取数据过程中出现错误
  53. ******************************************************************************************/
  54. void DS1307_I2C_Read(void)
  55. {

  56.     while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
  57. //        while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
  58.     {
  59.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  60.         {
  61.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Read_Error!");
  62.         }
  63.     }

  64.         DS1307_BuffToData();
  65.        
  66. }

  67. /******************************************************************************************
  68. * 函数名称: DS1307_I2C_Write()
  69. * 功能说明: 将当前的日历数据写入DS1307
  70. * 输    入: 无
  71. * 输    出: 0 = 成功写入数据  >0 = DS1307写入数据过程中出现错误
  72. ******************************************************************************************/
  73. void DS1307_I2C_Write(void)
  74. {
  75.     DS1307_DataToBuff();           //时间日期数据转换存入Buff数组中
  76.        
  77.     while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
  78. //    while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
  79.     {
  80.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  81.         {
  82.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Write_Erro!");
  83. //                        return 2;
  84.         }
  85.     }
  86. //        return 0;
  87. }

  88. /******************************************************************************************
  89. * 函数名称: DS1307_Chick()
  90. * 功能说明: 检查DS1307是否已经初始化,若未初始化则用特写日期进行初始化
  91. * 输    入: 无
  92. * 输    出: 无
  93. ******************************************************************************************/
  94. void DS1307_Check(void)
  95. {

  96. //        LCD_write_ASCII(0,3,1,(uint8_t *)"Check_Begin...");
  97.     while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
  98.     while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
  99.     {
  100.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  101.                 {
  102.                     LCD_write_ASCII(0,3,1,(uint8_t *)"CheckReadErro!");
  103.                 }
  104.         }
  105.         LCD_write_value(0,4,3,0,1,DS_Buff[0]);
  106.         if(DS_Buff[0]> 127){
  107.         year = 2019;
  108.                 month = 9;
  109.                 day = 18;
  110.                 week = 3;
  111.                 hour = 9;
  112.                 minute = 1;
  113.                
  114.         DS1307_DataToBuff();

  115.         while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
  116. //        while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 8, 10000) != HAL_OK)
  117.         {
  118.             if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  119.             {
  120.                 LCD_write_ASCII(0,3,1,(uint8_t *)"CheckWriteErr!");
  121.             }
  122.         }
  123.         }
  124. }

  125. /******************************************************************************************
  126. * 函数名称: DS1307_DataToBuff()
  127. * 功能说明: 将时间日期变量数据转换到数组Buff中
  128. * 输    入: 无
  129. * 输    出: 无
  130. ******************************************************************************************/
  131. void DS1307_DataToBuff(void)
  132. {
  133.     uint8_t temp;
  134.         DS_Buff[0] = 0;                  //秒
  135.     temp = ((minute/10)<<4|(minute%10));
  136.     DS_Buff[1] = temp;               //分
  137.     temp = ((hour/10)<<4|(hour%10));
  138.     DS_Buff[2] = temp;               //时

  139.     DS_Buff[3] = week;               //星期

  140.     temp = ((day/10)<<4|(day%10));
  141.     DS_Buff[4] = temp;               //日
  142.     temp = ((month/10)<<4|(month%10));
  143.     DS_Buff[5] = temp;               //月
  144.     temp = ((year%100)/10<<4|(year%10));
  145.     DS_Buff[6] = temp;               //年
  146.     DS_Buff[7] = 32;                 //0010 0000 = 允许按1Hz输出方波
  147. }


  148. /******************************************************************************************
  149. * 函数名称: DS1307_BuffToData()
  150. * 功能说明: 将数组Buff数据转换到时间日期变量中
  151. * 输    入: 无
  152. * 输    出: 无
  153. ******************************************************************************************/
  154. void DS1307_BuffToData(void)
  155. {
  156.     second = ((DS_Buff[0]&0x70)>>4)*10 + (DS_Buff[0]&0x0F);//秒,屏蔽秒的第7位的标志
  157.     minute = ((DS_Buff[1]&0x70)>>4)*10 + (DS_Buff[1]&0x0F);//分(取低7位)
  158.            hour = ((DS_Buff[2]&0x30)>>4)*10 + (DS_Buff[2]&0x0F);  //时(取低5位)
  159.            week = (DS_Buff[3]&0x07);                              //周(取低3位)
  160.     day = ((DS_Buff[4]&0x30)>>4)*10 + (DS_Buff[4]&0x0F);   //日(取低6位)
  161.     month = ((DS_Buff[5]&0x10)>>4)*10 + (DS_Buff[5]&0x0F); //月(取低5位)
  162.     year = 2000 + (DS_Buff[6]>>4)*10 + (DS_Buff[6]&0x0F);  //年
  163. }

复制代码
12下一页

所属标签

相似问题

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