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

【STM32G4 NUCLEO G431RB】+ I2C通讯终于完成

[复制链接]
hujjj 发布时间:2019-9-20 21:19
    之前完成了GPIO模拟I2C驱动DS1307和AT24C32之后,便继续测试如何使用硬件I2C。在热心版主和坛友的帮助下,经过几天的反复测试,硬件I2C也基本完成,在阻塞方式下完成了对DS1307和AT24C32的操作,下图为测试过程:
I2C_Bus_Ok.jpg

    屏幕下部的日期和时间是从DS1307芯片读取的,利用systick的毫秒中断进行秒计时,每分钟读取一次DS1307的日期数据,并用秒、分、时数据对AT24C32进行一次先读后写的操作,读出的数据(也就是上次写入的数据)显示在倒数第三行,当前写入的数据显示在倒数第二行。对DS1307读取数据交替采用HAL_I2C_Master_Receive()和HAL_I2C_Mem_Read()函数,读写的代码如下:
  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.     uint8_t addr = 0;
  10.         DS1307_DataToBuff();      //将时间及日期数据转换到Buff数组中
  11.         HAL_I2C_Master_Transmit(&hi2c1,0xD0,&addr,1,10000);//发送起始地址
  12.        
  13.         if(HAL_I2C_Master_Transmit(&hi2c1,0xD0,(uint8_t*)DS_Buff ,size,10000) != HAL_OK)
  14.     {
  15.         return 1;
  16.     }
  17.         return 0;
  18. }

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

  61.     while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
  62. //        while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
  63.     {
  64.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  65.         {
  66.             LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Read_Error!");
  67.         }
  68.     }

  69.         DS1307_BuffToData();
  70.        
  71. }

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

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

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

  120.         while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
  121. //        while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 8, 10000) != HAL_OK)
  122.         {
  123.             if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  124.             {
  125.                 LCD_write_ASCII(0,3,1,(uint8_t *)"CheckWriteErr!");
  126.             }
  127.         }
  128.         }
  129. }

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

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

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


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

  169. /******************************************************************************************
  170. * 函数名称: AT24C32_I2C_Read()
  171. * 功能说明: 读取AT24C32的数据(存放在DS_Buff数组中)
  172. * 输    入: adrr(起始地址),size(读取的字节长度)
  173. * 输    出: 无
  174. ******************************************************************************************/
  175. void AT24C32_I2C_Read(uint16_t addr,uint8_t size)
  176. {

  177.     while (HAL_I2C_Mem_Read(&hi2c1,0x00A0,addr,I2C_MEMADD_SIZE_16BIT,(uint8_t*)DS_Buff,size,10000) != HAL_OK)
  178.     {
  179.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  180.         {
  181.             LCD_write_ASCII(0,3,1,(uint8_t *)"AT_Read_Error!");
  182.         }
  183.     }

  184. }

  185. /******************************************************************************************
  186. * 函数名称: AT24C32_I2C_Write(uint16_t addr,uint8_t size)
  187. * 功能说明: 写入数据到AT24C32(要写入的数据存放在DS_Buff数组中)
  188. * 输    入: adrr(起始地址),size(写入的字节长度)
  189. * 输    出: 无
  190. ******************************************************************************************/
  191. void AT24C32_I2C_Write(uint16_t addr,uint8_t size)
  192. {
  193.     while (HAL_I2C_Mem_Write(&hi2c1,0x00A0,addr,I2C_MEMADD_SIZE_16BIT,(uint8_t*)DS_Buff,size,10000) != HAL_OK)
  194.     {
  195.         if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
  196.         {
  197.             LCD_write_ASCII(0,3,1,(uint8_t *)"AT_Write_Erro!");
  198.         }
  199.     }

  200. }
复制代码





收藏 1 评论4 发布时间:2019-9-20 21:19

举报

4个回答
Litthins 回答时间:2019-9-22 22:01:27
DS1307和DS1302区别大吗?
hujjj 回答时间:2019-9-23 12:10:18
有区别,DS1307要依靠器件地址来选定,也就是说可以挂在标准的I2C总线上使用,而DS1302则不需要器件地址,直接发送要操作的内存(寄存器)地址就行,按我的理解就是在这个总线上只能一个器件。
香醋 回答时间:2019-9-23 13:50:32
顶一下~~!
kongxiangtong28 回答时间:2019-11-16 12:08:07
您好,能给我发一下G4的pack吗?官网下载老是提示错误,谢谢

所属标签

STM32团队

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


最新内容

相似技术帖

官网相关资源

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