我正打算在STM32F446RE中通过I2C作为从机传输到主机,但我无法实现。
当没有代码在MCU上运行时,我可以看到主机要求我在示波器上写。但是当我使用此代码时:
if(HAL_I2C_Slave_Receive_IT(&I2CxHandle, (uint8_t*)&T2, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
while(HAL_I2C_Slave_Transmit_IT(&I2CxHandle, (uint8_t*)&T1, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
SDA升高而SCL降低
此外,当我删除“接收”行并在大约100ms的末尾添加延迟时,主服务器仅在有限的时间(不是固定的时间,有时是3-4s,有时几乎是一秒钟)内接收消息,但它不应该这样做是因为它不考虑来自主服务器的请求。
有什么主意吗?我尚未检查任何标志,原因是我不知道该怎么做。
完整代码:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#define I2C_ADDRESS 0x2E
I2C_HandleTypeDef I2CxHandle;
static GPIO_InitTypeDef GPIO_InitStruct;
static void SystemClock_Config(void);
static void Error_Handler(void);
int main(void)
{
HAL_Init();
/* Configure the system clock to 180 MHz */
SystemClock_Config();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Configure LED2 */
BSP_LED_Init(LED2);
/*##-1- Configure the I2C peripheral #######################################*/
I2CxHandle.Instance = I2Cx;
I2CxHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2CxHandle.Init.ClockSpeed = 100000;
I2CxHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2CxHandle.Init.DutyCycle = I2C_DUTYCYCLE_2;
I2CxHandle.Init.GeneralCallMode = I2C_GENERALCALL_ENABLE;
I2CxHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2CxHandle.Init.OwnAddress1 = I2C_ADDRESS;
I2CxHandle.Init.OwnAddress2 = 0;
if(HAL_I2C_Init(&I2CxHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
HAL_Delay(100);
while(1)
{
if(HAL_I2C_Slave_Receive_IT(&I2CxHandle, (uint8_t*)&T2, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
while(HAL_I2C_Slave_Transmit_IT(&I2CxHandle, (uint8_t*)&T1, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
T1++;
//HAL_Delay(100);
}
}
static void Error_Handler(void)
{
/* Turn LED2 ON if error */
//BSP_LED_On(LED2);
while(1)
{
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follows:
* System Clock source = PLL (HSI)
* SYSCLK(Hz) = 180000000
* HCLK(Hz) = 180000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSI Frequency(Hz) = 16000000
* PLL_M = 16
* PLL_N = 360
* PLL_P = 2
* PLL_Q = 7
* PLL_R = 6
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
* @param None
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSI Oscillator and activate PLL with HSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 0x10;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 360;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
RCC_OscInitStruct.PLL.PLLR = 6;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Activate the OverDrive to reach the 180 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief I2C error callbacks
* @param I2cHandle: I2C handle
* @note This example shows a simple way to report transfer error, and you can
* add your own implementation.
* @retval None
*/
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
/* Toggle LED2: error */
while(1)
{
// BSP_LED_On(LED2);
// HAL_Delay(500);
//BSP_LED_Off(LED2);
//HAL_Delay(500);
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif