diff options
Diffstat (limited to 'Projects/P-NUCLEO-WB55.Nucleo/Examples_LL/I2C/I2C_OneBoard_AdvCommunication_DMAAndIT_Init/Src/main.c')
-rw-r--r-- | Projects/P-NUCLEO-WB55.Nucleo/Examples_LL/I2C/I2C_OneBoard_AdvCommunication_DMAAndIT_Init/Src/main.c | 990 |
1 files changed, 990 insertions, 0 deletions
diff --git a/Projects/P-NUCLEO-WB55.Nucleo/Examples_LL/I2C/I2C_OneBoard_AdvCommunication_DMAAndIT_Init/Src/main.c b/Projects/P-NUCLEO-WB55.Nucleo/Examples_LL/I2C/I2C_OneBoard_AdvCommunication_DMAAndIT_Init/Src/main.c new file mode 100644 index 000000000..5355dd141 --- /dev/null +++ b/Projects/P-NUCLEO-WB55.Nucleo/Examples_LL/I2C/I2C_OneBoard_AdvCommunication_DMAAndIT_Init/Src/main.c @@ -0,0 +1,990 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file Examples_LL/I2C/I2C_OneBoard_AdvCommunication_DMAAndIT_Init/Src/main.c + * @author MCD Application Team + * @brief This example describes how to send/receive bytes over I2C IP using + * the STM32WBxx I2C LL API. + * Peripheral initialization done using LL unitary services functions. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ +/** + * @brief Timeout value + */ +#if (USE_TIMEOUT == 1) +#define DMA_SEND_TIMEOUT_TC_MS 5 +#define I2C_SEND_TIMEOUT_TC_MS 2 +#define I2C_SEND_TIMEOUT_STOP_MS 5 +#endif /* USE_TIMEOUT */ + +/** + * @brief I2C devices settings + */ +/* Timing register value is computed with the STM32CubeMX Tool, + * Fast Mode @400kHz with I2CCLK = 64 MHz, + * rise time = 100ns, fall time = 10ns + * Timing Value = (uint32_t)0x00C0216C + */ +#define I2C_TIMING 0x00C0216C + +#define SLAVE_CHIP_NAME 0 +#define SLAVE_CHIP_REVISION 1 + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +#if (USE_TIMEOUT == 1) +uint32_t Timeout = 0; /* Variable used for Timeout management */ +#endif /* USE_TIMEOUT */ +__IO uint8_t ubButtonPress = 0; + +/** + * @brief Variables related to Master process + */ +/* aCommandCode declaration array */ +/* [CommandCode][RequestSlaveAnswer] */ +/* {CODE, YES/NO} */ +const char* aCommandCode[4][4] = { + {"CHIP NAME", "YES"}, + {"CHIP REVISION", "YES"}, + {"LOW POWER", "NO"}, + {"WAKE UP", "NO"} + }; + +uint32_t* pMasterTransmitBuffer = (uint32_t*)(&aCommandCode[0][0]); +uint8_t ubMasterNbCommandCode = sizeof(aCommandCode[0][0]); +uint8_t aMasterReceiveBuffer[0xF] = {0}; +__IO uint8_t ubMasterNbDataToReceive = sizeof(aMasterReceiveBuffer); +__IO uint8_t ubMasterNbDataToTransmit = 0; +uint8_t ubMasterCommandIndex = 0; +__IO uint8_t ubMasterReceiveIndex = 0; +__IO uint8_t ubMasterTransferComplete = 0; + +/** + * @brief Variables related to Slave process + */ +const char* aSlaveInfo[] = { + "STM32WB55RG", + "1.2.3"}; + +uint8_t aSlaveReceiveBuffer[0xF] = {0}; +uint8_t* pSlaveTransmitBuffer = 0; +uint8_t ubSlaveInfoIndex = 0xFF; +__IO uint8_t ubSlaveReceiveIndex = 0; +__IO uint8_t ubSlaveReceiveComplete = 0; + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_DMA_Init(void); +static void MX_I2C1_Init(void); +static void MX_I2C3_Init(void); +/* USER CODE BEGIN PFP */ +uint8_t Buffercmp8(uint8_t* pBuffer1, uint8_t* pBuffer2, uint8_t BufferLength); +void FlushBuffer8(uint8_t* pBuffer1); +void LED_On(void); +void LED_Off(void); +void LED_Blinking(uint32_t Period); +void WaitForUserButtonPress(void); +void Handle_I2C_Master_Transmit(void); +void Handle_I2C_Master_TransmitReceive(void); +#if defined(__GNUC__) +extern void initialise_monitor_handles(void); /*rtt*/ +#endif + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + + NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /* System interrupt init*/ + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + MX_I2C1_Init(); + MX_I2C3_Init(); + /* USER CODE BEGIN 2 */ +#if defined(__GNUC__) + initialise_monitor_handles(); /*rtt*/ +#endif + + /* Set LED2 Off */ + LED_Off(); + + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + + /* Wait for User push-button (SW1) press to start transfer */ + WaitForUserButtonPress(); + + /* Clear User push-button (SW1) related variable */ + ubButtonPress = 0; + + if(strncmp(aCommandCode[ubMasterCommandIndex][1], "NO", 2) == 0) + { + /* Handle I2C3 events (Master Transmit only) */ + Handle_I2C_Master_Transmit(); + } + else + { + /* Handle I2C3 events (Master Transmit then Receive) */ + Handle_I2C_Master_TransmitReceive(); + } + + /* Prepare Index to send next command code */ + ubMasterCommandIndex++; + if(ubMasterCommandIndex >= ubMasterNbCommandCode) + { + ubMasterCommandIndex = 0; + } + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); + + /* MSI configuration and activation */ + LL_RCC_MSI_Enable(); + while(LL_RCC_MSI_IsReady() != 1) + { + } + + /* Main PLL configuration and activation */ + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 32, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_Enable(); + LL_RCC_PLL_EnableDomain_SYS(); + while(LL_RCC_PLL_IsReady() != 1) + { + } + + /* Sysclk activation on the main PLL */ + /* Set CPU1 prescaler*/ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + + /* Set CPU2 prescaler*/ + LL_C2_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); + + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + } + + /* Set AHB SHARED prescaler*/ + LL_RCC_SetAHB4Prescaler(LL_RCC_SYSCLK_DIV_1); + + /* Set APB1 prescaler*/ + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + + /* Set APB2 prescaler*/ + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(64000000); + + /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */ + LL_SetSystemCoreClock(64000000); + /* USER CODE BEGIN Smps */ + + /* USER CODE END Smps */ +} + +/** + * @brief I2C1 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C1_Init(void) +{ + + /* USER CODE BEGIN I2C1_Init 0 */ + + /* USER CODE END I2C1_Init 0 */ + + LL_I2C_InitTypeDef I2C_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + /**I2C1 GPIO Configuration + PB8 ------> I2C1_SCL + PB9 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + LL_SYSCFG_EnableFastModePlus(LL_SYSCFG_I2C_FASTMODEPLUS_PB8); + + LL_SYSCFG_EnableFastModePlus(LL_SYSCFG_I2C_FASTMODEPLUS_PB9); + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1); + + /* USER CODE BEGIN I2C1_Init 1 */ + /* Configure Event IT: + * - Set priority for I2C1_EV_IRQn + * - Enable I2C1_EV_IRQn + */ + NVIC_SetPriority(I2C1_EV_IRQn, 0xF); + NVIC_EnableIRQ(I2C1_EV_IRQn); + + /* Configure Error IT: + * - Set priority for I2C1_ER_IRQn + * - Enable I2C1_ER_IRQn + */ + NVIC_SetPriority(I2C1_ER_IRQn, 0xF); + NVIC_EnableIRQ(I2C1_ER_IRQn); + /* USER CODE END I2C1_Init 1 */ + /** I2C Initialization + */ + I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; + I2C_InitStruct.Timing = 0x00000102; + I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; + I2C_InitStruct.DigitalFilter = 0; + I2C_InitStruct.OwnAddress1 = 180; + I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK; + I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; + LL_I2C_Init(I2C1, &I2C_InitStruct); + LL_I2C_EnableAutoEndMode(I2C1); + LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK); + LL_I2C_DisableOwnAddress2(I2C1); + LL_I2C_DisableGeneralCall(I2C1); + LL_I2C_EnableClockStretching(I2C1); + /* USER CODE BEGIN I2C1_Init 2 */ + LL_I2C_EnableIT_ADDR(I2C1); + LL_I2C_EnableIT_NACK(I2C1); + LL_I2C_EnableIT_ERR(I2C1); + LL_I2C_EnableIT_STOP(I2C1); + /* USER CODE END I2C1_Init 2 */ + +} + +/** + * @brief I2C3 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C3_Init(void) +{ + + /* USER CODE BEGIN I2C3_Init 0 */ + + /* USER CODE END I2C3_Init 0 */ + + LL_I2C_InitTypeDef I2C_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + /**I2C3 GPIO Configuration + PC0 ------> I2C3_SCL + PC1 ------> I2C3_SDA + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3); + + /* I2C3 DMA Init */ + + /* I2C3_TX Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMAMUX_REQ_I2C3_TX); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_HIGH); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE); + + /* I2C3_RX Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_3, LL_DMAMUX_REQ_I2C3_RX); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_3, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PRIORITY_HIGH); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_BYTE); + + /* USER CODE BEGIN I2C3_Init 1 */ + LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_2, (uint32_t)(*pMasterTransmitBuffer), (uint32_t)LL_I2C_DMA_GetRegAddr(I2C3, LL_I2C_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2)); + LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_3, (uint32_t)LL_I2C_DMA_GetRegAddr(I2C3, LL_I2C_DMA_REG_DATA_RECEIVE), (uint32_t)&(aMasterReceiveBuffer), LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_3)); + LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_3); + LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_3); + + /* USER CODE END I2C3_Init 1 */ + /** I2C Initialization + */ + I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; + I2C_InitStruct.Timing = 0x00000102; + I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; + I2C_InitStruct.DigitalFilter = 0; + I2C_InitStruct.OwnAddress1 = 0; + I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK; + I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; + LL_I2C_Init(I2C3, &I2C_InitStruct); + LL_I2C_EnableAutoEndMode(I2C3); + LL_I2C_SetOwnAddress2(I2C3, 0, LL_I2C_OWNADDRESS2_NOMASK); + LL_I2C_DisableOwnAddress2(I2C3); + LL_I2C_DisableGeneralCall(I2C3); + LL_I2C_EnableClockStretching(I2C3); + /* USER CODE BEGIN I2C3_Init 2 */ + LL_I2C_EnableDMAReq_RX(I2C3); + LL_I2C_EnableDMAReq_TX(I2C3); + LL_I2C_Enable(I2C3); + /* USER CODE END I2C3_Init 2 */ + +} + +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + + /* Init with LL driver */ + /* DMA controller clock enable */ + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMAMUX1); + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); + + /* DMA interrupt init */ + /* DMA1_Channel2_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA1_Channel2_IRQn); + /* DMA1_Channel3_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA1_Channel3_IRQn); + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + LL_EXTI_InitTypeDef EXTI_InitStruct = {0}; + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + + /**/ + LL_GPIO_ResetOutputPin(LED2_GPIO_Port, LED2_Pin); + + /**/ + LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTC, LL_SYSCFG_EXTI_LINE4); + + /**/ + EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_4; + EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE; + EXTI_InitStruct.LineCommand = ENABLE; + EXTI_InitStruct.Mode = LL_EXTI_MODE_IT; + EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING; + LL_EXTI_Init(&EXTI_InitStruct); + + /**/ + LL_GPIO_SetPinPull(User_button_GPIO_Port, User_button_Pin, LL_GPIO_PULL_UP); + + /**/ + LL_GPIO_SetPinMode(User_button_GPIO_Port, User_button_Pin, LL_GPIO_MODE_INPUT); + + /**/ + GPIO_InitStruct.Pin = LED2_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct); + + /* EXTI interrupt init*/ + NVIC_SetPriority(EXTI4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(EXTI4_IRQn); + +} + +/* USER CODE BEGIN 4 */ + +/** + * @brief Flush 8-bit buffer. + * @param pBuffer1: pointer to the buffer to be flushed. + * @retval None + */ +void FlushBuffer8(uint8_t* pBuffer1) +{ + uint8_t Index = 0; + + for (Index = 0; Index < sizeof(pBuffer1); Index++) + { + pBuffer1[Index] = 0; + } +} + +/** + * @brief Compares two 8-bit buffers and returns the comparison result. + * @param pBuffer1: pointer to the source buffer to be compared to. + * @param pBuffer2: pointer to the second source buffer to be compared to the first. + * @param BufferLength: buffer's length. + * @retval 0: Comparison is OK (the two Buffers are identical) + * Value different from 0: Comparison is NOK (Buffers are different) + */ +uint8_t Buffercmp8(uint8_t* pBuffer1, uint8_t* pBuffer2, uint8_t BufferLength) +{ + while (BufferLength--) + { + if (*pBuffer1 != *pBuffer2) + { + return 1; + } + + pBuffer1++; + pBuffer2++; + } + + return 0; +} +/** + * @brief Turn-on LED2. + * @param None + * @retval None + */ +void LED_On(void) +{ + /* Turn LED2 on */ + LL_GPIO_SetOutputPin(LED2_GPIO_Port, LED2_Pin); +} + +/** + * @brief Turn-off LED2. + * @param None + * @retval None + */ +void LED_Off(void) +{ + /* Turn LED2 off */ + LL_GPIO_ResetOutputPin(LED2_GPIO_Port, LED2_Pin); +} + +/** + * @brief Set LED2 to Blinking mode for an infinite loop (toggle period based on value provided as input parameter). + * @param Period : Period of time (in ms) between each toggling of LED + * This parameter can be user defined values. Pre-defined values used in that example are : + * @arg LED_BLINK_FAST : Fast Blinking + * @arg LED_BLINK_SLOW : Slow Blinking + * @arg LED_BLINK_ERROR : Error specific Blinking + * @retval None + */ +void LED_Blinking(uint32_t Period) +{ + /* Turn LED2 on */ + LL_GPIO_SetOutputPin(LED2_GPIO_Port, LED2_Pin); + + /* Toggle IO in an infinite loop */ + while (1) + { + LL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin); + LL_mDelay(Period); + } +} + + +/** + * @brief Wait for User push-button (SW1) press to start transfer. + * @param None + * @retval None + */ + /* */ +void WaitForUserButtonPress(void) +{ + while (ubButtonPress == 0) + { + LL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin); + LL_mDelay(LED_BLINK_FAST); + } + /* Turn LED2 off */ + LL_GPIO_ResetOutputPin(LED2_GPIO_Port, LED2_Pin); +} + +/** + * @brief This Function handle Master events to perform a transmission process + * @note This function is composed in different steps : + * -1- Configure DMA parameters for Command Code transfer. + * -2- Enable DMA transfer. + * -3- Initiate a Start condition to the Slave device. + * -4- Loop until end of DMA transfer completed (DMA TC raised). + * -5- Loop until end of master transfer completed (STOP flag raised). + * -6- Clear pending flags, Data Command Code are checking into Slave process. + * @param None + * @retval None + */ +void Handle_I2C_Master_Transmit(void) +{ + /* (1) Configure DMA parameters for Command Code transfer *******************/ + pMasterTransmitBuffer = (uint32_t*)(&aCommandCode[ubMasterCommandIndex][0]); + ubMasterNbDataToTransmit = strlen((char *)pMasterTransmitBuffer[0]); + + LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)(*pMasterTransmitBuffer)); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, ubMasterNbDataToTransmit); + + /* (2) Enable DMA transfer **************************************************/ + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + /* (3) Initiate a Start condition to the Slave device ***********************/ + + /* Master Generate Start condition for a write request: + * - to the Slave with a 7-Bit SLAVE_OWN_ADDRESS + * - with a auto stop condition generation when transmit all bytes + * - No specific answer is needed from Slave Device, configure auto-stop condition + */ + LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubMasterNbDataToTransmit, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); + + /* (4) Loop until end of transfer completed (DMA TC raised) *****************/ + +#if (USE_TIMEOUT == 1) + Timeout = DMA_SEND_TIMEOUT_TC_MS; +#endif /* USE_TIMEOUT */ + + /* Loop until DMA transfer complete event */ + while(!ubMasterTransferComplete) + { +#if (USE_TIMEOUT == 1) + /* Check Systick counter flag to decrement the time-out value */ + if (LL_SYSTICK_IsActiveCounterFlag()) + { + if(Timeout-- == 0) + { + /* Time-out occurred. Set LED to blinking mode */ + LED_Blinking(LED_BLINK_SLOW); + } + } +#endif /* USE_TIMEOUT */ + } + + /* (5) Loop until end of master process completed (STOP flag raised) ********/ +#if (USE_TIMEOUT == 1) + Timeout = I2C_SEND_TIMEOUT_STOP_MS; +#endif /* USE_TIMEOUT */ + + /* Loop until STOP flag is raised */ + while(!LL_I2C_IsActiveFlag_STOP(I2C3)) + { +#if (USE_TIMEOUT == 1) + /* Check Systick counter flag to decrement the time-out value */ + if (LL_SYSTICK_IsActiveCounterFlag()) + { + if(Timeout-- == 0) + { + /* Time-out occurred. Set LED2 to blinking mode */ + LED_Blinking(LED_BLINK_SLOW); + } + } +#endif /* USE_TIMEOUT */ + } + + /* (6) Clear pending flags, Data Command Code are checking into Slave process */ + /* End of Master Process */ + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_I2C_ClearFlag_STOP(I2C3); + + /* Display through external Terminal IO the Slave Answer received */ + printf("%s : %s\n\r", (char*)(aCommandCode[ubMasterCommandIndex][0]), (char*)aMasterReceiveBuffer); + + /* Turn LED2 On */ + /* Master sequence completed successfully*/ + LED_On(); + /* Keep LED2 On, 500 MilliSeconds */ + LL_mDelay(500); + LED_Off(); + + /* Clear and Reset process variables and arrays */ + ubMasterTransferComplete = 0; + ubMasterNbDataToTransmit = 0; + ubMasterReceiveIndex = 0; + FlushBuffer8(aMasterReceiveBuffer); +} + +/** + * @brief This Function handle Master events to perform a transmission then a reception process + * @note This function is composed in different steps : + * -1- Configure DMA parameters for Command Code transfer. + * -2- Enable DMA transfer. + * -3- Initiate a Start condition to the Slave device. + * -4- Loop until end of DMA transfer completed (DMA TC raised). + * -5- Loop until end of master transfer completed (TC flag raised). + * -6- Configure DMA to receive data from slave. + * -7- Initiate a ReStart condition to the Slave device. + * -8- Loop until end of master process completed (STOP flag raised). + * -9- Clear pending flags, Data Command Code are checking into Slave process. + * @param None + * @retval None + */ +void Handle_I2C_Master_TransmitReceive(void) +{ + /* (1) Configure DMA parameters for Command Code transfer *******************/ + pMasterTransmitBuffer = (uint32_t*)(&aCommandCode[ubMasterCommandIndex][0]); + ubMasterNbDataToTransmit = strlen((char *)pMasterTransmitBuffer[0]); + + LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)(*pMasterTransmitBuffer)); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, ubMasterNbDataToTransmit); + + /* (2) Enable DMA transfer **************************************************/ + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + /* (3) Initiate a Start condition to the Slave device ***********************/ + + /* Master Generate Start condition for a write request: + * - to the Slave with a 7-Bit SLAVE_OWN_ADDRESS + * - with a no stop condition generation when transmit all bytes + * - A specific answer is needed from Slave Device, configure no-stop condition + */ + LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubMasterNbDataToTransmit, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE); + + /* (4) Loop until end of transfer completed (DMA TC raised) *****************/ + +#if (USE_TIMEOUT == 1) + Timeout = DMA_SEND_TIMEOUT_TC_MS; +#endif /* USE_TIMEOUT */ + + /* Loop until DMA transfer complete event */ + while(!ubMasterTransferComplete) + { +#if (USE_TIMEOUT == 1) + /* Check Systick counter flag to decrement the time-out value */ + if (LL_SYSTICK_IsActiveCounterFlag()) + { + if(Timeout-- == 0) + { + /* Time-out occurred. Set LED to blinking mode */ + LED_Blinking(LED_BLINK_SLOW); + } + } +#endif /* USE_TIMEOUT */ + } + + /* Reset ubMasterTransferComplete flag */ + ubMasterTransferComplete = 0; + + /* (5) Loop until end of master transfer completed (TC flag raised) *********/ + /* Wait Master Transfer completed */ +#if (USE_TIMEOUT == 1) + Timeout = I2C_SEND_TIMEOUT_TC_MS; +#endif /* USE_TIMEOUT */ + + while(LL_I2C_IsActiveFlag_TC(I2C3) != 1) + { +#if (USE_TIMEOUT == 1) + /* Check Systick counter flag to decrement the time-out value */ + if (LL_SYSTICK_IsActiveCounterFlag()) + { + if(Timeout-- == 0) + { + /* Time-out occurred. Set LED to blinking mode */ + LED_Blinking(LED_BLINK_SLOW); + } + } +#endif /* USE_TIMEOUT */ + } + + + /* (6) Configure DMA to receive data from slave *****************************/ + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_3, ubMasterNbDataToReceive); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_3); + + /* (7) Initiate a ReStart condition to the Slave device *********************/ + /* Master Generate Start condition for a write request: + * - to the Slave with a 7-Bit SLAVE_OWN_ADDRESS + * - with a auto stop condition generation when transmit all bytes + */ + LL_I2C_HandleTransfer(I2C3, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubMasterNbDataToReceive, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ); + + /* (8) Loop until end of master process completed (STOP flag raised) ********/ +#if (USE_TIMEOUT == 1) + Timeout = I2C_SEND_TIMEOUT_STOP_MS; +#endif /* USE_TIMEOUT */ + + /* Loop until STOP flag is raised */ + while(!LL_I2C_IsActiveFlag_STOP(I2C3)) + { +#if (USE_TIMEOUT == 1) + /* Check Systick counter flag to decrement the time-out value */ + if (LL_SYSTICK_IsActiveCounterFlag()) + { + if(Timeout-- == 0) + { + /* Time-out occurred. Set LED2 to blinking mode */ + LED_Blinking(LED_BLINK_SLOW); + } + } +#endif /* USE_TIMEOUT */ + } + + /* (9) Clear pending flags, Data Command Code are checking into Slave process */ + /* End of Master Process */ + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3); + LL_I2C_ClearFlag_STOP(I2C3); + + /* Display through external Terminal IO the Slave Answer received */ + printf("%s : %s\n\r", (char*)(aCommandCode[ubMasterCommandIndex][0]), (char*)aMasterReceiveBuffer); + + /* Turn LED2 On */ + /* Master sequence completed successfully*/ + LED_On(); + /* Keep LED2 On, 500 MilliSeconds */ + LL_mDelay(500); + LED_Off(); + + /* Clear and Reset process variables and arrays */ + ubMasterTransferComplete = 0; + ubMasterNbDataToTransmit = 0; + ubMasterReceiveIndex = 0; + FlushBuffer8(aMasterReceiveBuffer); +} +/******************************************************************************/ +/* IRQ HANDLER TREATMENT Functions */ +/******************************************************************************/ +/** + * @brief Function to manage User push-button (SW1) + * @param None + * @retval None + */ +void UserButton_Callback(void) +{ + /* Update User push-button (SW1) variable : to be checked in waiting loop in main program */ + ubButtonPress = 1; +} + +/** + * @brief Function called from I2C IRQ Handler when TXIS flag is set + * Function is in charge of transmit a byte on I2C lines. + * @param None + * @retval None + */ +void Slave_Ready_To_Transmit_Callback(void) +{ + /* Send the Byte requested by the Master */ + LL_I2C_TransmitData8(I2C1, (uint8_t)(*pSlaveTransmitBuffer++)); +} + +/** + * @brief Function called from I2C IRQ Handler when RXNE flag is set + * Function is in charge of retrieving received byte on I2C lines. + * @param None + * @retval None + */ +void Slave_Reception_Callback(void) +{ + /* Read character in Receive Data register. + RXNE flag is cleared by reading data in RXDR register */ + aSlaveReceiveBuffer[ubSlaveReceiveIndex++] = LL_I2C_ReceiveData8(I2C1); + + /* Check Command code */ + if(Buffercmp8((uint8_t*)aSlaveReceiveBuffer, (uint8_t*)(aCommandCode[0][0]), (ubSlaveReceiveIndex-1)) == 0) + { + ubSlaveInfoIndex = SLAVE_CHIP_NAME; + pSlaveTransmitBuffer = (uint8_t*)(aSlaveInfo[ubSlaveInfoIndex]); + } + else if(Buffercmp8((uint8_t*)aSlaveReceiveBuffer, (uint8_t*)(aCommandCode[1][0]), (ubSlaveReceiveIndex-1)) == 0) + { + ubSlaveInfoIndex = SLAVE_CHIP_REVISION; + pSlaveTransmitBuffer = (uint8_t*)(aSlaveInfo[ubSlaveInfoIndex]); + } +} + +/** + * @brief Function called from I2C IRQ Handler when STOP flag is set + * Function is in charge of checking data received, + * LED2 is On if data are correct. + * @param None + * @retval None + */ +void Slave_Complete_Callback(void) +{ + /* Clear and Reset process variables and arrays */ + ubSlaveReceiveIndex = 0; + ubSlaveReceiveComplete = 0; + FlushBuffer8(aSlaveReceiveBuffer); +} + +/** + * @brief DMA transfer complete callback + * @note This function is executed when the transfer complete interrupt + * is generated + * @retval None + */ +void Transfer_Complete_Callback() +{ + /* DMA transfer completed */ + ubMasterTransferComplete = 1; +} + +/** + * @brief DMA transfer error callback + * @note This function is executed when the transfer error interrupt + * is generated during DMA transfer + * @retval None + */ +void Transfer_Error_Callback() +{ + /* Disable DMA1_Channel2_IRQn */ + NVIC_DisableIRQ(DMA1_Channel2_IRQn); + + /* Error detected during DMA transfer */ + LED_Blinking(LED_BLINK_ERROR); +} + +/** + * @brief Function called in case of error detected in I2C IT Handler + * @param None + * @retval None + */ +void Error_Callback(void) +{ + /* Disable I2C1_EV_IRQn */ + NVIC_DisableIRQ(I2C1_EV_IRQn); + + /* Disable I2C1_ER_IRQn */ + NVIC_DisableIRQ(I2C1_ER_IRQn); + + /* Unexpected event : Set LED2 to Blinking mode to indicate error occurs */ + LED_Blinking(LED_BLINK_ERROR); +} + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + + /* USER CODE END Error_Handler_Debug */ +} + +#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 CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |