[STM32H5] 【STM32 Nucleo-64测评】+测试I3C的动态连接机制

[复制链接]
 楼主| suncat0504 发表于 2024-7-26 21:14 | 显示全部楼层 |阅读模式
<
本帖最后由 suncat0504 于 2024-7-26 21:16 编辑

作为替代I2C的新总线方式,I3C依旧使用2个总线。但相对比I2C,I3C总线的特点如下:

1、支持总线上多个主设备
2、支持目标电压是3.3V、1.8V、1.2V,甚至更低。
3、支持软中断
4、支持热拔插
5、支持动态地址
6、支持4种通信模式(SDR、HDR-DDR、HDR-TSL、HDR-TSP)



其中。支持动态地址这一点,就很好。以往使用的I2C设备,基本上都是地址固定的。比如常见的0.96英寸的OLED屏,就是固定使用0x3C地址的。动态分配地址,意味着,在同一个总线了,可以同时接入相同的I3C设备,而不用担心地址冲突导致的通讯失败。作为体验,这次我使用STM32H533中的两个I3C外设,实现动态连接、收发数据。其实,只能使用自身的外设测试I3C,也是因为我手里没有其它可用的I3C设备。





因为是向下兼容的,虽然依旧是使用2根线完成的通讯,I3C使用了更为复杂的通讯协议,由于协议内容很多,我也是在学习中,这里就不废话了。直接上测试程序测试。

本次测试使用CubeIDE作为开发工具,根据STM32H533开发板的电路图及它本身的特点,使用PB6、PB7作为第一组I3C设备,PC6、PC7作为第二组I3C设备。

1.png

在主程序中,不断检查开发板上的用户按钮(占用PC13),以及检查I3C纵向上是否设备要求连接。当按钮按下的时候,程序控制从I3C设备发出连接请求。当主I3C设备在收到连接请求后,会开始分配动态地址(这个地址是你自己乐意随意设置的),并建立热连接。

实测结果很不错,很容易就建立起动态连接了。测试程序没有使用串口输出调试信息,而是使用的OLED输出调试结果。

没有按下用户按钮时的状态:
2.png
按下用户后的状态:


3.png




可以看到,在动态完成连接后,主设备I3C1给I3C2分配了一个地址50,就是0x32。这个地址使我们预先设置好,让I3C1分配给其他设备的地址之一。

    // 设备1
    TargetDesc_TypeDef TargetDesc1 = { "TARGET_ID1", DEVICE_ID1, 0x0000000000000000, 0x00, TARGET1_DYN_ADDR, };


    // 设备2
    TargetDesc_TypeDef TargetDesc2 = { "TARGET_ID2", DEVICE_ID2, 0x0000000000000000, 0x00, TARGET2_DYN_ADDR, };


    // 目标描述符数组
    TargetDesc_TypeDef *aTargetDesc[2] = {
    &TargetDesc1, /* DEVICE_ID1 */
    &TargetDesc2 /* DEVICE_ID2 */
};


// 从机请求地址分配的回调函数
void HAL_I3C_TgtReqDynamicAddrCallback(I3C_HandleTypeDef *hi3c, uint64_t targetPayload) {
    printf("从机请求地址分配。");
    GUI_ShowString(0, 16, (uint8_t*) "ReqAddr", 8, 1);


    /* Update Payload on aTargetDesc */
    aTargetDesc[uwTargetCount]->TARGET_BCR_DCR_PID = targetPayload;


    /* Send associated dynamic address */
    HAL_I3C_Ctrl_SetDynAddr(hi3c, aTargetDesc[uwTargetCount++]->DYNAMIC_ADDR);
}


主程序代码如下:
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * [url=home.php?mod=space&uid=288409]@file[/url]           : main.c
  5. * [url=home.php?mod=space&uid=247401]@brief[/url]          : Main program body
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2024 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "main.h"
  21. #include "gui.h"
  22. #include "oled.h"

  23. #define I3C_IDX_FRAME_1         0U  /* Index of Frame 1 */
  24. #define I3C_IDX_FRAME_2         1U  /* Index of Frame 2 */

  25. I3C_HandleTypeDef hi3c1;
  26. I3C_HandleTypeDef hi3c2;
  27. TIM_HandleTypeDef htim2;

  28. // 与帧上下文相关的上下文缓冲区包含通信的不同缓冲值
  29. I3C_XferTypeDef aContextBuffers[2];

  30. // DAA过程中检测到的目标数量
  31. __IO uint32_t uwTargetCount = 0;

  32. // I3C发送用的缓冲区
  33. uint8_t aTxBuffer[0x0F];

  34. // I3C接收用的缓冲区
  35. uint8_t aRxBuffer[RXBUFFERSIZE];

  36. // HAL用来计算通信的控制数据的缓冲区
  37. uint32_t aControlBuffer[0xF];

  38. /********************/
  39. /* Target Descriptor */
  40. /********************/
  41. TargetDesc_TypeDef TargetDesc1 = { "TARGET_ID1",
  42. DEVICE_ID1, 0x0000000000000000, 0x00,
  43. TARGET1_DYN_ADDR, };

  44. /********************/
  45. /* Target Descriptor */
  46. /********************/
  47. TargetDesc_TypeDef TargetDesc2 = { "TARGET_ID2",
  48. DEVICE_ID2, 0x0000000000000000, 0x00,
  49. TARGET2_DYN_ADDR, };

  50. // 目标描述符数组
  51. TargetDesc_TypeDef *aTargetDesc[2] = { &TargetDesc1, /* DEVICE_ID1 */
  52. &TargetDesc2 /* DEVICE_ID2 */
  53. };

  54. /* Variable to catch HotJoin event */
  55. __IO uint32_t uwHotJoinRequested = 0;

  56. /* Buffer that contain payload data, mean PID, BCR, DCR */
  57. uint8_t aPayloadBuffer[64 * COUNTOF(aTargetDesc)];

  58. // 设置CCC关联数据的数组
  59. uint8_t aDISEC_data[1] = { 0x08 };

  60. /* Variable to display reading data */
  61. uint32_t uwDisplayDelay = 0U;
  62. int16_t Temperature = 0;
  63. int16_t aGyroscope[3] = { 0 };
  64. int16_t aAccelerometer[3] = { 0 };

  65. // 广播用CCC的描述符
  66. I3C_CCCTypeDef aBroadcast_CCC[] = {
  67. // 目标地址      CCC Value           CCC data + defbyte pointer  CCC size + defbyte    Direction        */
  68.         { 0, Broadcast_DISEC, { aDISEC_data, 1 }, LL_I3C_DIRECTION_WRITE }, { 0,
  69.                 Broadcast_RSTDAA, { NULL, 0 }, LL_I3C_DIRECTION_WRITE }, };

  70. UART_HandleTypeDef huart1;

  71. void SystemClock_Config(void);
  72. static void MX_GPIO_Init(void);
  73. static void MX_I3C1_Init(void);
  74. static void MX_I3C2_Init(void);
  75. static void MX_USART1_UART_Init(void);
  76. static void MX_TIM2_Init(void);
  77. static void EXTI13_IRQHandler_Config(void);
  78. void checkI3CDevice(void);

  79. /**
  80. * @brief  The application entry point.
  81. * @retval int
  82. */
  83. uint8_t flag = 0;

  84. // 设备是否发出过I3C申请信号
  85. uint8_t send_flag = 0;
  86. int main(void) {
  87.     // 复位所有外设,初始化Flash接口和Systick。
  88.     HAL_Init();

  89.     // 设置系统时钟
  90.     SystemClock_Config();

  91.     // 初始化相关外设
  92.     MX_GPIO_Init();
  93.     MX_I3C1_Init();
  94.     MX_I3C2_Init();
  95.     MX_USART1_UART_Init();
  96.     MX_TIM2_Init();
  97.     EXTI13_IRQHandler_Config();

  98.     // 初始化OLED并显示信息
  99.     OLED_Init();
  100.     OLED_Clear(0);
  101.     GUI_ShowString(0, 0, (uint8_t*) "Test STM32H533 I3C", 8, 1);

  102.     HAL_Delay(100);

  103.     // 允许hi3c1接受其他设备的动态连接请求(中断方式)
  104.     if (HAL_I3C_ActivateNotification(&hi3c1, NULL, HAL_I3C_IT_HJIE) != HAL_OK) {
  105.         /* Error_Handler() function is called when error occurs. */
  106.         Error_Handler();
  107.     }

  108.     while (1) {
  109.         checkI3CDevice();

  110.     }
  111. }

  112. // 检查是否存在I3C设备(由子设备发出请求,主设备响应后,分发地址)
  113. void checkI3CDevice(void) {
  114.     // 等待目标连接上
  115.     while (uwHotJoinRequested == 0U) {
  116.         // 为热连接启动监听
  117.         if (send_flag == 0) {
  118.             // 检查用户按钮是否按下
  119.             if (HAL_GPIO_ReadPin(USER_BUTTON_GPIO_Port, USER_BUTTON_Pin) == 1) {
  120.                 // 由I3C2发出连接请求
  121.                 if (HAL_I3C_Tgt_HotJoinReq_IT(&hi3c2) != HAL_OK) {
  122.                     Error_Handler();
  123.                 } else {
  124.                     send_flag = 1;
  125.                 }
  126.             }
  127.         }
  128.     }

  129.     // 分配动态地址
  130.     if (HAL_I3C_Ctrl_DynAddrAssign_IT(&hi3c1, I3C_ONLY_ENTDAA) != HAL_OK) {
  131.         Error_Handler();
  132.     }

  133.     // 获取状态
  134.     while (HAL_I3C_GetState(&hi3c1) != HAL_I3C_STATE_LISTEN) {

  135.     }

  136.     // 复位,等待捕捉其它I3C设备
  137.     uwHotJoinRequested = 0;
  138. }

  139. /**
  140. * @brief System Clock Configuration
  141. * @retval None
  142. */
  143. void SystemClock_Config(void) {
  144.     RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
  145.     RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };

  146.     /** Configure the main internal regulator output voltage
  147.      */
  148.     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  149.     while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
  150.     }

  151.     /** Initializes the RCC Oscillators according to the specified parameters
  152.      * in the RCC_OscInitTypeDef structure.
  153.      */
  154.     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_CSI;
  155.     RCC_OscInitStruct.CSIState = RCC_CSI_ON;
  156.     RCC_OscInitStruct.CSICalibrationValue = RCC_CSICALIBRATION_DEFAULT;
  157.     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  158.     RCC_OscInitStruct.PLL.PLLSource = RCC_PLL1_SOURCE_CSI;
  159.     RCC_OscInitStruct.PLL.PLLM = 1;
  160.     RCC_OscInitStruct.PLL.PLLN = 50;
  161.     RCC_OscInitStruct.PLL.PLLP = 2;
  162.     RCC_OscInitStruct.PLL.PLLQ = 2;
  163.     RCC_OscInitStruct.PLL.PLLR = 2;
  164.     RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1_VCIRANGE_2;
  165.     RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE;
  166.     RCC_OscInitStruct.PLL.PLLFRACN = 0;
  167.     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
  168.         Error_Handler();
  169.     }

  170.     /** Initializes the CPU, AHB and APB buses clocks
  171.      */
  172.     RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
  173.             | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3;
  174.     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  175.     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  176.     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  177.     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  178.     RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

  179.     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
  180.         Error_Handler();
  181.     }
  182. }

  183. /**
  184. * @brief I3C1 Initialization Function
  185. * @param None
  186. * @retval None
  187. */
  188. static void MX_I3C1_Init(void) {

  189.     I3C_FifoConfTypeDef sFifoConfig = { 0 };
  190.     I3C_CtrlConfTypeDef sCtrlConfig = { 0 };

  191.     hi3c1.Instance = I3C1;
  192.     hi3c1.Mode = HAL_I3C_MODE_CONTROLLER;
  193.     hi3c1.Init.CtrlBusCharacteristic.SDAHoldTime = HAL_I3C_SDA_HOLD_TIME_1_5;
  194.     hi3c1.Init.CtrlBusCharacteristic.WaitTime = HAL_I3C_OWN_ACTIVITY_STATE_0;
  195.     hi3c1.Init.CtrlBusCharacteristic.SCLPPLowDuration = 0x09;
  196.     hi3c1.Init.CtrlBusCharacteristic.SCLI3CHighDuration = 0x09;
  197.     hi3c1.Init.CtrlBusCharacteristic.SCLODLowDuration = 0x59;
  198.     hi3c1.Init.CtrlBusCharacteristic.SCLI2CHighDuration = 0x00;
  199.     hi3c1.Init.CtrlBusCharacteristic.BusFreeDuration = 0x32;
  200.     hi3c1.Init.CtrlBusCharacteristic.BusIdleDuration = 0xf8;
  201.     if (HAL_I3C_Init(&hi3c1) != HAL_OK) {
  202.         Error_Handler();
  203.     }

  204.     /** Configure FIFO
  205.      */
  206.     sFifoConfig.RxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4;
  207.     sFifoConfig.TxFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4;
  208.     sFifoConfig.ControlFifo = HAL_I3C_CONTROLFIFO_DISABLE;
  209.     sFifoConfig.StatusFifo = HAL_I3C_STATUSFIFO_DISABLE;
  210.     if (HAL_I3C_SetConfigFifo(&hi3c1, &sFifoConfig) != HAL_OK) {
  211.         Error_Handler();
  212.     }

  213.     /** Configure controller
  214.      */
  215.     sCtrlConfig.DynamicAddr = 0;
  216.     sCtrlConfig.StallTime = 0x00;
  217.     sCtrlConfig.HotJoinAllowed = ENABLE;
  218.     sCtrlConfig.ACKStallState = DISABLE;
  219.     sCtrlConfig.CCCStallState = DISABLE;
  220.     sCtrlConfig.TxStallState = DISABLE;
  221.     sCtrlConfig.RxStallState = DISABLE;
  222.     sCtrlConfig.HighKeeperSDA = DISABLE;
  223.     if (HAL_I3C_Ctrl_Config(&hi3c1, &sCtrlConfig) != HAL_OK) {
  224.         Error_Handler();
  225.     }
  226. }

  227. /**
  228. * @brief I3C2 Initialization Function
  229. * @param None
  230. * @retval None
  231. */
  232. static void MX_I3C2_Init(void) {

  233.     I3C_FifoConfTypeDef sFifoConfig = { 0 };
  234.     I3C_TgtConfTypeDef sTgtConfig = { 0 };

  235.     hi3c2.Instance = I3C2;
  236.     hi3c2.Mode = HAL_I3C_MODE_TARGET;
  237.     hi3c2.Init.TgtBusCharacteristic.BusAvailableDuration = 0xf8;
  238.     if (HAL_I3C_Init(&hi3c2) != HAL_OK) {
  239.         Error_Handler();
  240.     }

  241.     /** Configure FIFO
  242.      */
  243.     sFifoConfig.RxFifoThreshold = HAL_I3C_RXFIFO_THRESHOLD_1_4;
  244.     sFifoConfig.TxFifoThreshold = HAL_I3C_TXFIFO_THRESHOLD_1_4;
  245.     sFifoConfig.ControlFifo = HAL_I3C_CONTROLFIFO_DISABLE;
  246.     sFifoConfig.StatusFifo = HAL_I3C_STATUSFIFO_DISABLE;

  247.     if (HAL_I3C_SetConfigFifo(&hi3c2, &sFifoConfig) != HAL_OK) {
  248.         Error_Handler();
  249.     }

  250.     /** Configure Target
  251.      */
  252.     sTgtConfig.Identifier = 0xC7;
  253.     sTgtConfig.MIPIIdentifier = DEVICE_ID2;
  254.     sTgtConfig.CtrlRoleRequest = DISABLE;
  255.     sTgtConfig.HotJoinRequest = ENABLE;
  256.     sTgtConfig.IBIRequest = DISABLE;
  257.     sTgtConfig.IBIPayload = DISABLE;
  258.     sTgtConfig.IBIPayloadSize = HAL_I3C_PAYLOAD_EMPTY;
  259.     sTgtConfig.MaxReadDataSize = 0xFF;
  260.     sTgtConfig.MaxWriteDataSize = 0xFF;
  261.     sTgtConfig.CtrlCapability = DISABLE;
  262.     sTgtConfig.GroupAddrCapability = DISABLE;
  263.     sTgtConfig.DataTurnAroundDuration = HAL_I3C_TURNAROUND_TIME_TSCO_LESS_12NS;
  264.     sTgtConfig.MaxReadTurnAround = 0;
  265.     sTgtConfig.MaxDataSpeed = HAL_I3C_GETMXDS_FORMAT_1;
  266.     sTgtConfig.MaxSpeedLimitation = DISABLE;
  267.     sTgtConfig.HandOffActivityState = HAL_I3C_HANDOFF_ACTIVITY_STATE_0;
  268.     sTgtConfig.HandOffDelay = DISABLE;
  269.     sTgtConfig.PendingReadMDB = DISABLE;
  270.     if (HAL_I3C_Tgt_Config(&hi3c2, &sTgtConfig) != HAL_OK) {
  271.         Error_Handler();
  272.     }

  273. }

  274. /**
  275. * @brief TIM2 Initialization Function
  276. * @param None
  277. * @retval None
  278. */
  279. static void MX_TIM2_Init(void) {

  280.     TIM_ClockConfigTypeDef sClockSourceConfig = { 0 };
  281.     TIM_MasterConfigTypeDef sMasterConfig = { 0 };

  282.     /* USER CODE BEGIN TIM2_Init 1 */

  283.     /* USER CODE END TIM2_Init 1 */
  284.     htim2.Instance = TIM2;
  285.     htim2.Init.Prescaler = 0;
  286.     htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  287.     htim2.Init.Period = 100000;   // 100MHz:1mS

  288.     htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  289.     htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  290.     if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
  291.         Error_Handler();
  292.     }
  293.     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  294.     if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
  295.         Error_Handler();
  296.     }
  297.     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  298.     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
  299.     if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig)
  300.             != HAL_OK) {
  301.         Error_Handler();
  302.     }

  303.     // 允许Timer2中断
  304.     HAL_TIM_Base_Start_IT(&htim2);

  305.     HAL_NVIC_EnableIRQ(TIM2_IRQn);

  306. }
  307. /**
  308. * @brief USART1 Initialization Function
  309. * @param None
  310. * @retval None
  311. */
  312. static void MX_USART1_UART_Init(void) {

  313.     huart1.Instance = USART1;
  314.     huart1.Init.BaudRate = 115200;
  315.     huart1.Init.WordLength = UART_WORDLENGTH_8B;
  316.     huart1.Init.StopBits = UART_STOPBITS_1;
  317.     huart1.Init.Parity = UART_PARITY_NONE;
  318.     huart1.Init.Mode = UART_MODE_TX_RX;
  319.     huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  320.     huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  321.     huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  322.     huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  323.     huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  324.     if (HAL_UART_Init(&huart1) != HAL_OK) {
  325.         Error_Handler();
  326.     }
  327.     if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8)
  328.             != HAL_OK) {
  329.         Error_Handler();
  330.     }
  331.     if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8)
  332.             != HAL_OK) {
  333.         Error_Handler();
  334.     }
  335.     if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK) {
  336.         Error_Handler();
  337.     }
  338. }

  339. /**
  340. * @brief GPIO Initialization Function
  341. * @param None
  342. * @retval None
  343. */
  344. static void MX_GPIO_Init(void) {
  345.     GPIO_InitTypeDef GPIO_InitStruct = { 0 };

  346.     /* GPIO Ports Clock Enable */
  347.     __HAL_RCC_GPIOC_CLK_ENABLE();
  348.     __HAL_RCC_GPIOA_CLK_ENABLE();
  349.     __HAL_RCC_GPIOB_CLK_ENABLE();

  350.     /*Configure GPIO pin Output Level */
  351.     HAL_GPIO_WritePin(USER_LED_GPIO_Port, USER_LED_Pin, GPIO_PIN_RESET);

  352.     /*Configure GPIO pin Output Level */
  353.     HAL_GPIO_WritePin(GPIOA, OLED_SCL_Pin | OLED_SDA_Pin, GPIO_PIN_SET);

  354.     // 设置用户按钮使用的GPIO口
  355.     GPIO_InitStruct.Pin = USER_BUTTON_Pin;
  356.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  357.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  358.     HAL_GPIO_Init(USER_BUTTON_GPIO_Port, &GPIO_InitStruct);

  359.     // 设置用户LED按钮使用的GPIO口
  360.     GPIO_InitStruct.Pin = USER_LED_Pin;
  361.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  362.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  363.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  364.     HAL_GPIO_Init(USER_LED_GPIO_Port, &GPIO_InitStruct);

  365.     // 设置OLED使用的接口(模拟方式)
  366.     GPIO_InitStruct.Pin = OLED_SCL_Pin | OLED_SDA_Pin;
  367.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  368.     GPIO_InitStruct.Pull = GPIO_PULLUP;
  369.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  370.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  371. }

  372. /**
  373. * @brief 从机请求地址分配的回调函数
  374. * @par Called functions
  375. * - HAL_I3C_TgtReqDynamicAddrCallback()
  376. * - HAL_I3C_Ctrl_SetDynamicAddress()
  377. * @retval None
  378. */
  379. void HAL_I3C_TgtReqDynamicAddrCallback(I3C_HandleTypeDef *hi3c,
  380.         uint64_t targetPayload) {
  381.     printf("从机请求地址分配。");
  382.     GUI_ShowString(0, 16, (uint8_t*) "ReqAddr", 8, 1);

  383.     /* Update Payload on aTargetDesc */
  384.     aTargetDesc[uwTargetCount]->TARGET_BCR_DCR_PID = targetPayload;

  385.     /* Send associated dynamic address */
  386.     HAL_I3C_Ctrl_SetDynAddr(hi3c, aTargetDesc[uwTargetCount++]->DYNAMIC_ADDR);
  387. }

  388. /**
  389. * @brief  控制器完成动态地址的分配的回调函数
  390. * @param  hi3c : [IN] 包含配置信息的结构体.
  391. * @retval None
  392. */
  393. void HAL_I3C_CtrlDAACpltCallback(I3C_HandleTypeDef *hi3c) {
  394.     printf("完成动态地址的分配。");
  395.     GUI_ShowString(60, 16, (uint8_t*) "Addr OK", 8, 1);
  396. }

  397. /**
  398. * @brief 收到连接请求后代额回调函数.
  399. * @par Called functions
  400. * - HAL_I3C_NotifyCallback()
  401. * @retval None
  402. */
  403. void HAL_I3C_NotifyCallback(I3C_HandleTypeDef *hi3c, uint32_t eventId) {
  404.     if ((eventId & EVENT_ID_HJ) == EVENT_ID_HJ) {
  405.         HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

  406.         // 建立收到连接请求的标志
  407.         printf("收到连接请求!");
  408.         GUI_ShowString(0, 8, (uint8_t*) "Notify", 8, 1);
  409.         uwHotJoinRequested = 1;

  410.     }
  411. }

  412. /**
  413. * @brief 从机(I3C2)连接成功的回调函数.
  414. *        函数目的是为了检查热连接过程是否完成
  415. * @par Called functions
  416. * - HAL_I3C_TgtHotJoinCallback()
  417. * @retval None
  418. */
  419. void HAL_I3C_TgtHotJoinCallback(I3C_HandleTypeDef *hi3c, uint8_t dynamicAddress) {
  420.     // 从机连上
  421.     GUI_ShowString(0, 24, (uint8_t*) "Target Addr=", 8, 1);
  422.     GUI_ShowNum(100, 24, dynamicAddress, 2, 8, 1);
  423.     printf("Slave is OK! Address=%d", dynamicAddress);
  424. }

  425. /**
  426. * @brief  This function is executed in case of error occurrence.
  427. * @retval None
  428. */
  429. void Error_Handler(void) {
  430.     /* USER CODE BEGIN Error_Handler_Debug */
  431.     /* User can add his own implementation to report the HAL error return state */
  432.     __disable_irq();
  433.     while (1) {
  434.     }
  435.     /* USER CODE END Error_Handler_Debug */
  436. }

  437. // 定时器2的溢出中断回调函数
  438. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
  439.     BSP_LED_Toggle(LED2);
  440. }

  441. /* USER CODE BEGIN 4 */
  442. /**
  443. * @brief  Configures EXTI line 13 (connected to PC.13 pin) in interrupt mode
  444. * @param  None
  445. * @retval None
  446. */
  447. static void EXTI13_IRQHandler_Config(void) {
  448.     GPIO_InitTypeDef GPIO_InitStructure;

  449.     /* Enable GPIOC clock */
  450.     __HAL_RCC_GPIOC_CLK_ENABLE();

  451.     /* Configure PC.13 pin as input floating */
  452.     GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING_FALLING; //GPIO_MODE_IT_FALLING;

  453.     GPIO_InitStructure.Pull = GPIO_NOPULL;
  454.     GPIO_InitStructure.Pin = BUTTON_USER_PIN;
  455.     HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

  456.     /* Enable and set line 13 Interrupt to the lowest priority */
  457.     HAL_NVIC_SetPriority(EXTI13_IRQn, 2, 0);
  458.     HAL_NVIC_EnableIRQ(EXTI13_IRQn);
  459. }

  460. void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) {
  461.     // 判断是不是来自PC13的
  462.     if (GPIO_Pin == BUTTON_USER_PIN) {
  463.         /* Toggle LED2 */
  464.         BSP_LED_On(LED2);
  465.     }
  466. }

  467. void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin) {
  468.     // 判断是不是来自PC13的
  469.     if (GPIO_Pin == BUTTON_USER_PIN) {
  470.         /* Toggle LED2 */
  471.         BSP_LED_Off(LED2);
  472.     }
  473. }

  474. #ifdef  USE_FULL_ASSERT
  475. /**
  476.   * @brief  Reports the name of the source file and the source line number
  477.   *         where the assert_param error has occurred.
  478.   * @param  file: pointer to the source file name
  479.   * @param  line: assert_param error line source number
  480.   * @retval None
  481.   */
  482. void assert_failed(uint8_t *file, uint32_t line)
  483. {
  484.   /* USER CODE BEGIN 6 */
  485.   /* User can add his own implementation to report the file name and line number,
  486.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  487.   /* USER CODE END 6 */
  488. }
  489. #endif /* USE_FULL_ASSERT */



kzlzqi 发表于 2024-7-29 15:06 | 显示全部楼层
I3C 允许多个主设备在同一个总线上进行通信,这不同于 I2C 的单主设备模式。
申小林一号 发表于 2024-7-29 22:50 | 显示全部楼层
感谢分享
申小林一号 发表于 2024-7-29 22:51 | 显示全部楼层
感谢分享
纠结的那些年 发表于 2024-7-31 11:56 | 显示全部楼层
I3C 可以支持从 3.3V 到更低电压的目标电压,使其能够在更广泛的电源条件下工作。
AdaMaYun 发表于 2024-7-31 12:59 | 显示全部楼层
I3C依旧使用2个总线,功能更强大稳定性更好
为你转身 发表于 2024-8-31 13:46 | 显示全部楼层
设计上兼顾了I2C的简单性,同时引入了许多新特性以支持更复杂和高效的通信需求。
为你转身 发表于 2024-8-31 13:48 | 显示全部楼层
你提到的 I3C 特性确实使它在许多应用中比 I2C 更具优势。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:大连伊飞特信息技术有限公司软件工程师
简介:本人于1993年毕业于大连理工大学。毕业后从事单片机开发工作5年,之后转入软件开发工作至今。

158

主题

4504

帖子

6

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