I2C trong STM32
Trong STM32F1:
- APB1 bus: chứa các ngoại vi như I2C1, I2C2, USART2/3, SPI2, TIM2–TIM7…
- APB2 bus: chứa các ngoại vi như USART1, SPI1, ADC1/2, TIM1, GPIO…
Mỗi bus này nhận clock riêng
- PCLK1 → clock cho APB1
- PCLK2 → clock cho APB2
Sau đây là các bước để sử dụng I2C dùng thư viện LL trên stm32f103c8t6.
Bước 1: Cấu hình tần số
/**
* @brief I2C devices settings
*/
/* I2C SPEEDCLOCK define to value: Stardard Mode @100kHz */
#define I2C_SPEEDCLOCK 100000
#define I2C_DUTYCYCLE LL_I2C_DUTYCYCLE_2
Bước 2: Định nghĩa hàm hoạt động
void Configure_I2C_Master(void);
void Activate_I2C_Master(void);
void Handle_I2C_Master(void);
/**
* @brief This function configures I2C1 in Master mode.
* @note This function is used to :
* -1- Enables GPIO clock.
* -2- Enable the I2C1 peripheral clock and configures the I2C1 pins.
* -3- Configure I2C1 functional parameters.
* @note Peripheral configuration is minimal configuration from reset values.
* Thus, some useless LL unitary functions calls below are provided as
* commented examples - setting is default configuration from reset.
* @param None
* @retval None
*/
void Configure_I2C_Master(void)
{
LL_RCC_ClocksTypeDef rcc_clocks;
/* (1) Enables GPIO clock **********************/
/* Enable the peripheral clock of GPIOB */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/* (2) Enable the I2C1 peripheral clock *************************************/
/* Enable the peripheral clock for I2C1 */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
/* Configure SCL Pin as : Alternate function, High Speed, Open drain, Pull up */
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_6, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_6, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_6, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_6, LL_GPIO_PULL_UP);
/* Configure SDA Pin as : Alternate function, High Speed, Open drain, Pull up */
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_7, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_7, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_7, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_7, LL_GPIO_PULL_UP);
/* (3) Configure I2C1 functional parameters ********************************/
/* Disable I2C1 prior modifying configuration registers */
LL_I2C_Disable(I2C1);
/* Retrieve Clock frequencies */
LL_RCC_GetSystemClocksFreq(&rcc_clocks);
/* Configure the SCL Clock Speed */
LL_I2C_ConfigSpeed(I2C1, rcc_clocks.PCLK1_Frequency, I2C_SPEEDCLOCK, I2C_DUTYCYCLE);
/* Configure the Own Address1 */
/* Reset Values of :
* - OwnAddress1 is 0x00
* - OwnAddrSize is LL_I2C_OWNADDRESS1_7BIT
*/
//LL_I2C_SetOwnAddress1(I2C1, 0x00, LL_I2C_OWNADDRESS1_7BIT);
/* Enable Clock stretching */
/* Reset Value is Clock stretching enabled */
//LL_I2C_EnableClockStretching(I2C1);
/* Enable General Call */
/* Reset Value is General Call disabled */
//LL_I2C_EnableGeneralCall(I2C1);
/* Configure the 7bits Own Address2 */
/* Reset Values of :
* - OwnAddress2 is 0x00
* - Own Address2 is disabled
*/
//LL_I2C_SetOwnAddress2(I2C1, 0x00);
//LL_I2C_DisableOwnAddress2(I2C1);
/* Enable Peripheral in I2C mode */
/* Reset Value is I2C mode */
//LL_I2C_SetMode(I2C1, LL_I2C_MODE_I2C);
}
/**
* @brief This function Activate I2C1 peripheral (Master)
* @note This function is used to :
* -1- Enable I2C1.
* @param None
* @retval None
*/
void Activate_I2C_Master(void)
{
/* (1) Enable I2C1 **********************************************************/
LL_I2C_Enable(I2C1);
}
/**
* @brief Slave settings
*/
#define SLAVE_OWN_ADDRESS 0x5A // địa chỉ này đã dịch sang trái một bit, vd: địa chỉ thực của slave = 0010 1101
/**
* @brief Master Transfer Request Direction
*/
#define I2C_REQUEST_WRITE 0x00
#define I2C_REQUEST_READ 0x01
/**
* @brief This Function handle Master events to perform a transmission process
* @note This function is composed in different steps :
* -1- Prepare acknowledge for Master data reception.
* -2- Initiate a Start condition to the Slave device.
* -3- Loop until Start Bit transmitted (SB flag raised).
* -4- Send Slave address with a 7-Bit SLAVE_OWN_ADDRESS for a write request.
* -5- Loop until Address Acknowledgement received (ADDR flag raised).
* -6- Clear ADDR flag and loop until end of transfer (ubNbDataToTransmit == 0).
* -6.1 Transmit data (TXE flag raised).
* -7- End of transfer, Data consistency are checking into Slave process.
* @param None
* @retval None
*/
void Handle_I2C_Master(void)
{
/* (1) Prepare acknowledge for Master data reception ************************/
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
/* (2) Initiate a Start condition to the Slave device ***********************/
/* Master Generate Start condition */
LL_I2C_GenerateStartCondition(I2C1);
/* (3) Loop until Start Bit transmitted (SB flag raised) ********************/
#if (USE_TIMEOUT == 1)
Timeout = I2C_SEND_TIMEOUT_SB_MS;
#endif /* USE_TIMEOUT */
/* Loop until SB flag is raised */
while(!LL_I2C_IsActiveFlag_SB(I2C1))
{
#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 */
}
/* (4) Send Slave address with a 7-Bit SLAVE_OWN_ADDRESS for a write request */
LL_I2C_TransmitData8(I2C1, SLAVE_OWN_ADDRESS | I2C_REQUEST_WRITE);
/* (5) Loop until Address Acknowledgement received (ADDR flag raised) *******/
#if (USE_TIMEOUT == 1)
Timeout = I2C_SEND_TIMEOUT_ADDR_MS;
#endif /* USE_TIMEOUT */
/* Loop until ADDR flag is raised */
while(!LL_I2C_IsActiveFlag_ADDR(I2C1))
{
#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 ADDR flag and loop until end of transfer (ubNbDataToTransmit == 0) */
/* Clear ADDR flag value in ISR register */
LL_I2C_ClearFlag_ADDR(I2C1);
#if (USE_TIMEOUT == 1)
Timeout = I2C_SEND_TIMEOUT_TXE_MS;
#endif /* USE_TIMEOUT */
/* Loop until TXE flag is raised */
while(ubNbDataToTransmit > 0)
{
/* (6.1) Transmit data (TXE flag raised) **********************************/
/* Check TXE flag value in ISR register */
if(LL_I2C_IsActiveFlag_TXE(I2C1))
{
/* Write data in Transmit Data register.
TXE flag is cleared by writing data in TXDR register */
LL_I2C_TransmitData8(I2C1, (*pTransmitBuffer++));
ubNbDataToTransmit--;
#if (USE_TIMEOUT == 1)
Timeout = I2C_SEND_TIMEOUT_TXE_MS;
#endif /* USE_TIMEOUT */
}
#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 */
}
/* (7) End of transfer, Data consistency are checking into Slave process *****/
/* Generate Stop condition */
LL_I2C_GenerateStopCondition(I2C1);
/* Turn LED2 On:
* - Expected bytes have been sent
* - Master Tx sequence completed successfully
*/
LED_On();
}
Code được tạo bởi CubeMx
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_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
/** I2C Initialization
*/
LL_I2C_DisableOwnAddress2(I2C1);
LL_I2C_DisableGeneralCall(I2C1);
LL_I2C_EnableClockStretching(I2C1);
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.ClockSpeed = 100000;
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
LL_I2C_Init(I2C1, &I2C_InitStruct);
LL_I2C_SetOwnAddress2(I2C1, 0);
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
All rights reserved