[STM32G0] 天生残U,I2C双机通信之I2C从机

[复制链接]
1839|16
 楼主| zero949079783 发表于 2023-11-12 18:56 | 显示全部楼层 |阅读模式
本帖最后由 zero949079783 于 2023-11-24 22:51 编辑

天生残U,I2C双机通信之I2C从机
  1. #include "i2c_drv.h"
  2. #include "usart_drv.h"
  3. I2C_HandleTypeDef i2c1;
  4. I2C_HandleTypeDef i2c2;
  5. DMA_HandleTypeDef i2c1_txdma;
  6. DMA_HandleTypeDef i2c1_rxdma;
  7. //uint8_t wdata[16] ={2,2,3,4,5,6,7,8,1,2,3,4,5,6,7,12};        //给从机发送数据
  8. //uint8_t rdata[16] ={0};                                                                        //读取从机的数据
  9. uint16_t i ;
  10. uint8_t rx_flag=0;
  11. uint8_t tx_data[21]={"01234567890abcdef123"};
  12. uint8_t rx_data[20]={0};                                //接收缓冲区必需大于主机发送数据量,否则会一直进入中断

  13. uint8_t tx_data2[21]={"01234567890abcdef123"};
  14. uint8_t rx_data2[20]={0};
  15. //uint8_t reg_data[1];
  16. #define slave_addr (0x01<<1)
  17. #define slave_addr2 (0x02<<1)
  18. void i2c_reset();

  19. void I2C_Drv_Init(void)
  20. {
  21.         uint8_t i;
  22.         i2c1.Instance = I2C1;
  23.         i2c1.Init.Timing=0x00602173;
  24.         //i2c1.Init.Timing = 0xC010EBFF;
  25.         i2c1.Init.OwnAddress1 = slave_addr;                        //从机地址
  26.         i2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  27.         i2c1.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
  28.         i2c1.Init.OwnAddress2 = slave_addr2;
  29.         i2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  30.         i2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;        
  31.         
  32.         HAL_I2C_Init(&i2c1);

  33.         i2c2.Instance = I2C2;
  34.         i2c2.Init.Timing=0x00602173;
  35.         //i2c1.Init.Timing = 0xC010EBFF;
  36.         i2c2.Init.OwnAddress1 = slave_addr;                        //从机地址
  37.         i2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  38.         i2c2.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
  39.         i2c2.Init.OwnAddress2 = slave_addr2;
  40.         i2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  41.         i2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;        
  42.         
  43. //        HAL_I2C_Init(&i2c2);        
  44. //        for(i=0;i<21;i++)
  45. //        {
  46. //                tx_data[i]=21-i;
  47. //        }
  48. //        
  49. //        for(i=0;i<21;i++)
  50. //        {
  51. //                tx_data2[i]=21-i;
  52. //        }        
  53.         
  54.         HAL_I2C_EnableListen_IT(&i2c1);        //启动侦听地址
  55.         
  56.         HAL_I2C_EnableListen_IT(&i2c2);        //启动侦听地址
  57. }

  58. void I2C_Drv_Init2(void)
  59. {


  60.         i2c2.Instance = I2C2;
  61.         i2c2.Init.Timing=0x00602173;
  62.         //i2c1.Init.Timing = 0xC010EBFF;
  63.         i2c2.Init.OwnAddress1 = slave_addr;                        //从机地址
  64.         i2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  65.         i2c2.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
  66.         i2c2.Init.OwnAddress2 = slave_addr2;
  67.         i2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  68.         i2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;        
  69.         
  70.         HAL_I2C_Init(&i2c2);        

  71.         
  72.         HAL_I2C_EnableListen_IT(&i2c2);        //启动侦听地址
  73. }

  74. void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
  75. {
  76.         GPIO_InitTypeDef GPIO_InitTypeDefStructur;
  77.         
  78.         if(hi2c ->Instance == I2C1)
  79.         {
  80.                 __HAL_RCC_I2C1_CLK_ENABLE();
  81.                 __HAL_RCC_GPIOB_CLK_ENABLE();

  82.                 GPIO_InitTypeDefStructur.Pin =GPIO_PIN_8|GPIO_PIN_9;
  83.                 GPIO_InitTypeDefStructur.Mode = GPIO_MODE_AF_OD;
  84.                 GPIO_InitTypeDefStructur.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  85.                 GPIO_InitTypeDefStructur.Pull=GPIO_NOPULL;
  86.                 GPIO_InitTypeDefStructur.Alternate=GPIO_AF6_I2C1;               
  87.                 HAL_GPIO_Init(GPIOB,&GPIO_InitTypeDefStructur);               
  88.                
  89.                 HAL_NVIC_SetPriority(I2C1_IRQn,0,2);
  90.                 HAL_NVIC_EnableIRQ(I2C1_IRQn);        

  91.                 __I2C1_FORCE_RESET();
  92.                 __I2C1_RELEASE_RESET();
  93.                
  94.                 hi2c->Instance->CR1 = I2C_CR1_SWRST;   //复位I2C
  95.                 hi2c->Instance->CR1 = 0;              //解除复位               
  96. //                //I2C RX
  97. //                i2c1_txdma.Instance = DMA1_Channel2;
  98. //                i2c1_txdma.Init.Request = DMA_REQUEST_I2C1_TX;
  99. //                i2c1_txdma.Init.Direction = DMA_MEMORY_TO_PERIPH;
  100. //                i2c1_txdma.Init.PeriphInc = DMA_PINC_DISABLE;
  101. //                i2c1_txdma.Init.MemInc = DMA_MINC_ENABLE;
  102. //                i2c1_txdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  103. //                i2c1_txdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  104. //                i2c1_txdma.Init.Mode = DMA_NORMAL;
  105. //                i2c1_txdma.Init.Priority = DMA_PRIORITY_MEDIUM;

  106. //                __HAL_LINKDMA(hi2c,hdmatx,i2c1_txdma);        
  107. //                HAL_DMA_Init(&i2c1_txdma);
  108. //               
  109. //                //I2C RX
  110. //                i2c1_rxdma.Instance = DMA1_Channel3;
  111. //                i2c1_rxdma.Init.Request = DMA_REQUEST_I2C1_RX;
  112. //                i2c1_rxdma.Init.Direction = DMA_PERIPH_TO_MEMORY;
  113. //                i2c1_rxdma.Init.PeriphInc = DMA_PINC_DISABLE;
  114. //                i2c1_rxdma.Init.MemInc = DMA_MINC_ENABLE;
  115. //                i2c1_rxdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  116. //                i2c1_rxdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  117. //                i2c1_rxdma.Init.Mode = DMA_NORMAL;
  118. //                i2c1_rxdma.Init.Priority = DMA_PRIORITY_MEDIUM;


  119. //                __HAL_LINKDMA(hi2c,hdmarx,i2c1_rxdma);               
  120. //                HAL_DMA_Init(&i2c1_rxdma);
  121. //                HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
  122. //                HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);               
  123.         }
  124.         if(hi2c ->Instance == I2C2)
  125.         {
  126.                 __HAL_RCC_I2C2_CLK_ENABLE();
  127.                 __HAL_RCC_GPIOA_CLK_ENABLE();

  128.                 GPIO_InitTypeDefStructur.Pin =GPIO_PIN_11|GPIO_PIN_12;
  129.                 GPIO_InitTypeDefStructur.Mode = GPIO_MODE_AF_OD;
  130.                 GPIO_InitTypeDefStructur.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  131.                 GPIO_InitTypeDefStructur.Pull=GPIO_PULLUP;
  132.                 GPIO_InitTypeDefStructur.Alternate=GPIO_AF6_I2C2;               
  133.                 HAL_GPIO_Init(GPIOA,&GPIO_InitTypeDefStructur);               
  134.                
  135.                 HAL_NVIC_SetPriority(I2C2_IRQn,0,1);
  136.                 HAL_NVIC_EnableIRQ(I2C2_IRQn);        

  137.                 __I2C2_FORCE_RESET();
  138.                 __I2C2_RELEASE_RESET();
  139.                
  140.                 hi2c->Instance->CR1 = I2C_CR1_SWRST;   //复位I2C
  141.                 hi2c->Instance->CR1 = 0;
  142.         }               
  143. }

  144. void i2c_reset()
  145. {
  146.     /* 开漏输出,关闭I2C输入通道,并尝试将总线拉高 */
  147.     GPIO_InitTypeDef GPIO_InitStruct;
  148.     GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
  149.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  150.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  151.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  152.     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_SET);

  153.     // SCL PB8 拉高
  154.     for (uint8_t i = 0; i < 10; i++) {

  155.         if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
  156.         {
  157.             //rt_kprintf("retry %d\n", i);
  158.             break;
  159.         }
  160.         /* 该延时循环的周期和时长,请根据你的实际主机对I2C通讯出错的处理来修改 */
  161.         HAL_Delay(10);
  162.     }

  163.     /* 归还总线控制权 */
  164.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
  165.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  166.     /* 复位I2C */
  167.     i2c1.Instance->CR1 |= I2C_CR1_SWRST;
  168.     i2c1.Instance->CR1 &= ~I2C_CR1_SWRST;

  169.     /* 重新初始化I2C */
  170.    I2C_Drv_Init();
  171. }
  172. //侦听完成
  173. void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
  174. {
  175.         if(hi2c ->Instance == I2C1)
  176.         {
  177.                 HAL_I2C_EnableListen_IT(&i2c1);        //启动侦听地址
  178.                 u1_printf("I2C1侦听地址完成\r\n");
  179.         }
  180.         else if(hi2c ->Instance == I2C2)
  181.         {
  182.                 HAL_I2C_EnableListen_IT(&i2c2);        //启动侦听地址
  183.                 u1_printf("I2C2侦听地址完成\r\n");
  184.         }        

  185. }

  186. void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
  187. {
  188.         if(hi2c ->Instance == I2C1)
  189.         {
  190.                 if((AddrMatchCode == slave_addr) || (AddrMatchCode == slave_addr2))
  191.                 {
  192.                         if(TransferDirection ==I2C_DIRECTION_RECEIVE)        //准备给主机发送数据
  193.                         {
  194.                                         if(rx_data[0]==0x01)
  195.                                         {
  196.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,tx_data,2,I2C_LAST_FRAME);
  197.                                                 //HAL_I2C_Slave_Transmit_IT(&i2c1,tx_data,1);
  198.                                         }
  199.                                         if(rx_data[0]==0x08)
  200.                                         {
  201.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,&tx_data[3],2,I2C_LAST_FRAME);
  202.                                         }
  203.                                         if(rx_data[0]==0x21)
  204.                                         {
  205.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,tx_data,21,I2C_LAST_FRAME);
  206.                                         }                                                
  207.                                         else
  208.                                         {
  209.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,&tx_data[3],2,I2C_LAST_FRAME);
  210.                                         }

  211.                                        
  212.                                 //HAL_I2C_Slave_Transmit_DMA(&i2c1,wdata,16);
  213.                                 //        HAL_I2C_Slave_Transmit_IT(&i2c1,tx_data[1],2);
  214.                         }else if(TransferDirection == I2C_DIRECTION_TRANSMIT )        //准备接收主机的数据
  215.                         {

  216.                                 
  217.                                 HAL_I2C_Slave_Seq_Receive_IT(&i2c1,rx_data,1,I2C_FIRST_FRAME);

  218.                         }
  219.                 }
  220.                
  221.         }
  222.         if(hi2c ->Instance == I2C2)
  223.         {
  224.                 if((AddrMatchCode == slave_addr) || (AddrMatchCode == slave_addr2))
  225.                 {
  226.                         if(TransferDirection ==I2C_DIRECTION_RECEIVE)        //准备给主机发送数据
  227.                         {
  228.                                         if(rx_data2[0]==0x01)
  229.                                         {
  230.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,tx_data2,2,I2C_LAST_FRAME);
  231.                                                 //HAL_I2C_Slave_Transmit_IT(&i2c1,tx_data,1);
  232.                                         }
  233.                                         else if(rx_data2[0]==0x08)
  234.                                         {
  235.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,&tx_data2[3],2,I2C_LAST_FRAME);
  236.                                         }
  237.                                         else if(rx_data2[0]==0x09)
  238.                                         {
  239.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,&tx_data2[5],2,I2C_LAST_FRAME);
  240.                                         }                                       
  241.                                         else if(rx_data2[0]==0x21)
  242.                                         {
  243.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,tx_data2,21,I2C_LAST_FRAME);
  244.                                         }                                       
  245.                                         else
  246.                                         {
  247.                                                 HAL_I2C_Slave_Seq_Transmit_IT(&i2c2,&tx_data2[7],2,I2C_LAST_FRAME);
  248.                                         }

  249.                         }else if(TransferDirection == I2C_DIRECTION_TRANSMIT )        //准备接收主机的数据
  250.                         {

  251.                                 
  252.                                 HAL_I2C_Slave_Seq_Receive_IT(&i2c2,rx_data2,1,I2C_FIRST_FRAME);

  253.                         }
  254.                 }
  255.         }        
  256.                         
  257. }

  258. //从机发送完成
  259. void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
  260. {
  261.         if(hi2c ->Instance == I2C1)
  262.         {
  263. //                hi2c ->PreviousState = HAL_I2C_MODE_NONE;
  264.                 u1_printf("从机发送完成\r\n");
  265.         }
  266.         if(hi2c ->Instance == I2C2)
  267.         {
  268. //                hi2c ->PreviousState = HAL_I2C_MODE_NONE;
  269.                 u1_printf("从机发送完成\r\n");
  270.         }        
  271. }

  272. //从机接收完成
  273. void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
  274. {
  275.         if(hi2c ->Instance == I2C1)
  276.         {
  277.                         hi2c ->PreviousState = HAL_I2C_MODE_NONE;
  278. //
  279. //                        u1_printf("从机接收中断完成 %d\r\n",__HAL_I2C_GET_FLAG(hi2c,I2C_FLAG_BUSY));
  280.                 //u1_printf("从机接收完成 %d\r\n",rx_data[0]);
  281.                 rx_flag=0;
  282. //                        if(rx_data[0] == 0x01)
  283. //                        {
  284. //                                HAL_I2C_Slave_Seq_Transmit_IT(&i2c1,tx_data,1,I2C_FIRST_AND_LAST_FRAME);
  285. //                        }

  286.                

  287.                                 u1_printf("rx_data%X\r\n",rx_data[0]);        
  288.                         
  289.                
  290.         }
  291.         else if(hi2c ->Instance == I2C2){

  292.                         u1_printf("OK2\n") ;
  293.                 //u1_printf("从机接收完成 %d\r\n",rx_data[0]);               
  294.         }
  295. }

  296. void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
  297. {
  298.         if(hi2c ->Instance == I2C1)
  299.         {
  300. //                i2c_reset();
  301. //                I2C_Drv_Init();
  302.         }
  303. }


一秒落纱 发表于 2023-11-20 22:14 | 显示全部楼层
怎么说?你说的G0的I2C不好用?
三生万物 发表于 2023-11-21 01:00 | 显示全部楼层
其实这个I2C不如用模拟的,时序搞好,其他都OK
暖了夏天蓝了海 发表于 2023-11-21 03:00 | 显示全部楼层
你说的残,怎么个残法?
冰春彩落下 发表于 2023-11-21 05:00 | 显示全部楼层
是这芯片的I2C的从机模式不能用?
远山寻你 发表于 2023-11-21 07:00 | 显示全部楼层
应该用cubemx来配置一下的话,应该是没问题的吧
江河千里 发表于 2023-11-21 09:00 | 显示全部楼层
都是有BUG的存在,只是有没有弥补方法而已
淡漠安然 发表于 2023-11-21 11:00 | 显示全部楼层
给我的感觉就是这芯片就是为了更换STM32F1的,所以,有的可能这个U也是有I2C的问题吧
别乱了阵脚 发表于 2023-11-21 13:00 | 显示全部楼层
我建议还是楼主用模拟的方式实现I2C从机,但就是挂载不了了
光辉梦境 发表于 2023-11-21 15:00 | 显示全部楼层
哈哈,确实,ST的I2C总是备受争议
夜阑风雨 发表于 2023-11-21 22:00 | 显示全部楼层
你换个芯片呗,他家的I2C好像一直都有BUG吧
 楼主| zero949079783 发表于 2023-11-24 22:48 | 显示全部楼层
淡漠安然 发表于 2023-11-21 11:00
给我的感觉就是这芯片就是为了更换STM32F1的,所以,有的可能这个U也是有I2C的问题吧 ...

是有问题,数据接收少了,就死机
 楼主| zero949079783 发表于 2023-11-24 22:49 | 显示全部楼层
远山寻你 发表于 2023-11-21 07:00
应该用cubemx来配置一下的话,应该是没问题的吧

一样有问题
 楼主| zero949079783 发表于 2023-11-24 22:50 | 显示全部楼层
三生万物 发表于 2023-11-21 01:00
其实这个I2C不如用模拟的,时序搞好,其他都OK

你有没有I2C从机的模拟程序????
Pulitzer 发表于 2024-7-21 07:14 | 显示全部楼层

减小检测部分与电压误差或电流放大器敏感的输入端之间的连接而引入的噪声
童雨竹 发表于 2024-7-21 09:10 | 显示全部楼层

引线越长,它能接收和传送的干扰信号频率就越低
公羊子丹 发表于 2024-7-21 12:09 | 显示全部楼层

引线的长和宽影响它的电阻和电感量
万图 发表于 2024-7-21 13:12 | 显示全部楼层

它们的放置要尽可能靠近
Uriah 发表于 2024-7-21 14:15 | 显示全部楼层

大地的地会通过散热器(用绝缘体与漏极隔开)从这些节点获取能量
帛灿灿 发表于 2024-7-21 16:11 | 显示全部楼层

输入电源电流环路
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

91

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部