/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Uncomment this line to use the board as master, if not it is used as slave */
#define MASTER_BOARD
#define I2C_ADDRESS 0xA0
#define MASTER_REQ_READ 0xA0
#define MASTER_REQ_WRITE 0xA0
/* I2C TIMING Register define when I2C clock source is SYSCLK */
/* I2C TIMING is calculated in case of the I2C Clock source is the SYSCLK = 32 MHz */
//#define I2C_TIMING 0x10A13E56 /* 100 kHz with analog Filter ON, Rise Time 400ns, Fall Time 100ns */
#define I2C_TIMING 0x00B1112E /* 400 kHz with analog Filter ON, Rise Time 250ns, Fall Time 100ns */
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/* STM32L0xx HAL library initialization:
- Configure the Flash prefetch, Flash preread and Buffer caches
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 32 MHz */
SystemClock_Config();
/* Enable the Analog I2C Filter */
HAL_I2CEx_ConfigAnalogFilter(&I2cHandle,I2C_ANALOGFILTER_ENABLE);
#ifdef MASTER_BOARD
/* Configure User push-button */
//BSP_PB_Init(BUTTON_KEY,BUTTON_MODE_GPIO);
/* Wait for User push-button press before starting the Communication */
// while (BSP_PB_GetState(BUTTON_KEY) != GPIO_PIN_RESET)
// {
// }
/* Wait for User push-button release before starting the Communication */
// while (BSP_PB_GetState(BUTTON_KEY) != GPIO_PIN_SET)
// {
// }
while(1)
{
/* Initialize number of data variables */
hTxNumData = TXBUFFERSIZE;
hRxNumData = RXBUFFERSIZE;
/* Update bTransferRequest to send buffer write request for Slave */
bTransferRequest = MASTER_REQ_WRITE;
/*##-2- Master sends write request for slave #############################*/
/*##-3- Master sends number of data to be written ########################*/
do
{
if(HAL_I2C_Mem_Write_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0xA8, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
/* Error_Handler() function is called when error occurs. */
Error_Handler();
}
/* Before starting a new communication transfer, you need to check the current
state of the peripheral; if it抯 busy you need to wait for the end of current
transfer before starting a new one.
For simplicity reasons, this example is just waiting till the end of the
transfer, but application may perform other tasks while transfer operation
is ongoing. */
while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
{
}
/* When Acknowledge failure occurs (Slave don't acknowledge it's address)
Master restarts communication */
}
while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);
HAL_Delay(100);
/*##-7- Master receives aRxBuffer from slave #############################*/
do
{
if(HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0xA8, I2C_MEMADD_SIZE_8BIT, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= HAL_OK)
{
/* Error_Handler() function is called when error occurs. */
Error_Handler();
}
/* Before starting a new communication transfer, you need to check the current
state of the peripheral; if it抯 busy you need to wait for the end of current
transfer before starting a new one.
For simplicity reasons, this example is just waiting till the end of the
transfer, but application may perform other tasks while transfer operation
is ongoing. */
while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
{
}
/* When Acknowledge failure occurs (Slave don't acknowledge it's address)
Master restarts communication */
}
while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);
/* Check correctness of received buffer ##################################*/
if(Buffercmp((uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,hRxNumData))
{
/* Processing Error */
Error_Handler();
}
/* This delay permits to see LED2 toggling */
HAL_Delay(25);
}
#else
while(1)
{
}
#endif /* MASTER_BOARD */
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSI)
* SYSCLK(Hz) = 32000000
* HCLK(Hz) = 32000000
* AHB Prescaler = 1
* APB1 Prescaler = 1
* APB2 Prescaler = 1
* Flash Latency(WS) = 1
* Main regulator output voltage = Scale1 mode
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* 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);
/* Disable Power Control clock */
__HAL_RCC_PWR_CLK_DISABLE();
/* 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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1)!= HAL_OK)
{
/* Initialization Error */
while(1);
}
}
/**
* @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)
{
/** Error_Handler() function is called when error occurs.
* 1- When Slave don't acknowledge it's address, Master restarts communication.
* 2- When Master don't acknowledge the last data transferred, Slave don't care in this example.
*/
if (HAL_I2C_GetError(I2cHandle) != HAL_I2C_ERROR_AF)
{
Error_Handler();
}
}
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
static void Error_Handler(void)
{
/* Error if LED2 is slowly blinking (1 sec. period) */
while(1)
{
//BSP_LED_Toggle(LED2);
HAL_Delay(1000);
}
}
/**
* @brief Compares two buffers.
* @param pBuffer1, pBuffer2: buffers to be compared.
* @param BufferLength: buffer's length
* @retval 0 : pBuffer1 identical to pBuffer2
* >0 : pBuffer1 differs from pBuffer2
*/
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while (BufferLength--)
{
if ((*pBuffer1) != *pBuffer2)
{
return BufferLength;
}
pBuffer1++;
pBuffer2++;
}
return 0;
}
/**
* @brief Flushes the buffer
* @param pBuffer: buffers to be flushed.
* @param BufferLength: buffer's length
* @retval None
*/
static void Flush_Buffer(uint8_t* pBuffer, uint16_t BufferLength)
{
while (BufferLength--)
{
*pBuffer = 0;
pBuffer++;
}
}
#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) */
/**
* @brief I2C MSP Initialization
* This function configures the hardware resources used in this example:
* - Peripheral's clock enable
* - Peripheral's GPIO Configuration
* - DMA configuration for transmission request by peripheral
* - NVIC configuration for DMA interrupt request enable
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;
/*##-1- Configure the I2C clock source. The clock is derived from the SYSCLK #*/
RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2Cx;
//RCC_PeriphCLKInitStruct.I2c1ClockSelection = RCC_I2CxCLKSOURCE_SYSCLK;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
/*##-4- Configure the NVIC for I2C ########################################*/
/* NVIC for I2Cx */
HAL_NVIC_SetPriority(I2Cx_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(I2Cx_IRQn);
}
/**
* @brief I2C MSP De-Initialization
* This function frees the hardware resources used in this example:
* - Disable the Peripheral's clock
* - Revert GPIO, DMA and NVIC configuration to their default state
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
{