I2C_OneBoard_Communication_PollingAndIT
单板轮询发送带中断。初始化,三步,GPIO开启,I2C时钟引脚,I2C模式配置。Enable开启,init函数包含enable。两个例子。
cpp
/**
* @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);
}
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 = 400000;
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);
}
master发送数据,其中有带timeout和不带的。ll库是纯纯发数据,关于目标地址的内存地址发送和正常发数据一样。这里给两个例子。内存地址8位还是16位,自己定义就是16位拆开先发送低位在发送高位,I2C_MEMADD_SIZE_8BIT这个是hal库定义实际值就是0x01和0x00,自己定义一个同样作用。
cpp
/**
* @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 tranfer, 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 tranfer, Data consistency are checking into Slave process *****/
/* Generate Stop condition */
LL_I2C_GenerateStopCondition(I2C1);
}
void oledMemWrite(I2C_TypeDef *I2Cx, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
{
// 1. 生成起始条件
LL_I2C_GenerateStartCondition(I2Cx);
// 2. 等待总线就绪,准备发送从设备地址(写模式)
while (!LL_I2C_IsActiveFlag_SB(I2Cx))
;
// 3. 发送从设备地址(写模式:地址左移1位,最低位为0)
LL_I2C_TransmitData8(I2Cx, (DevAddress << 1) | 0x00);
// 4. 等待地址发送完毕并收到从设备的应答(ACK)
while(!LL_I2C_IsActiveFlag_ADDR(I2Cx));
LL_I2C_ClearFlag_ADDR(I2Cx);
// 发送内存地址(根据MemAddSize决定发送几个字节)
if(MemAddSize == I2C_MEMADD_SIZE_8BIT)
{
// 8位地址
while(!LL_I2C_IsActiveFlag_TXE(I2Cx));
LL_I2C_TransmitData8(I2Cx, (uint8_t)MemAddress);
}
else // 16位地址
{
// 高字节
while(!LL_I2C_IsActiveFlag_TXE(I2Cx));
LL_I2C_TransmitData8(I2Cx, (MemAddress >> 8) & 0xFF);
// 低字节
while(!LL_I2C_IsActiveFlag_TXE(I2Cx));
LL_I2C_TransmitData8(I2Cx, MemAddress & 0xFF);
}
// 发送数据
for (uint8_t i = 0; i < Size; i++)
{
// 等待上一个字节发送完成(TXE标志置1表示数据寄存器空,可写入新数据)
while (!LL_I2C_IsActiveFlag_TXE(I2Cx))
;
// 发送一个字节数据
LL_I2C_TransmitData8(I2Cx, pData[i]);
}
// 6. 等待最后一个字节发送完成(BTF标志表示数据传输完成)
while (!LL_I2C_IsActiveFlag_BTF(I2Cx))
;
// 7. 生成停止条件
LL_I2C_GenerateStopCondition(I2Cx);
}