网上很多STM32的I2C都是基于F系列去实现的,其他的系列的芯片实现很少。
而对于STM32L151系列的I2C从机设计,用STM32CubeMX生成的简单DEMO里,就会有提供库接口实现,比如:
HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
但其实,如果是调用库接口,只能实现从机接收或者是只实现从机发送实现,调用现成接口貌似很难做到既接收有发送(至少个人没有试验出来)。
不过如果使用中断,实现起来就非常简单了。
首先使用STM32CubeMX生成一个简单的I2C demo,设置在MX_I2C1_Init接口里面设置好从机的一些基本信息(从机地址,使用几位从机地址等);
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0x90;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
然后重写I2C1_EV_IRQHandler中断函数,并使能中断;
void I2C1_EV_IRQHandler(void)
{
if (hi2c1.Instance->SR1 & (I2C_FLAG_BERR | I2C_FLAG_ARLO | I2C_FLAG_OVR)) {
HAL_I2C_ER_IRQHandler(&hi2c1);
} else {
HAL_I2C_EV_IRQHandler(&hi2c1);
}
}
至于中断函数就直接使用工具生成的就可以了。
值得注意的是:
STM32L151芯片在工具生成的DEMO里面,从机模式无论是接收还是发送都是一个字节一个字节进行的,如果你需要接收或者是发送多个字节,需要稍微更改一下接收和发送的函数。
static HAL_StatusTypeDef I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c)
{
while(hi2c->XferSize > 0U)
{
/* Wait until TXE flag is set */
if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, 0xffffffff, 0) != HAL_OK)
{
/* Disable Address Acknowledge */
CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
return HAL_ERROR;
}
else
{
return HAL_TIMEOUT;
}
}
/* Write data to DR */
hi2c->Instance->DR = (*hi2c->pBuffPtr++);
hi2c->XferCount--;
hi2c->XferSize--;
}
if((hi2c->XferCount == 0U) && (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN))
{
/* Last Byte is received, disable Interrupt */
__HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF);
/* Set state at HAL_I2C_STATE_LISTEN */
hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
hi2c->State = HAL_I2C_STATE_LISTEN;
/* Call the Tx complete callback to inform upper layer of the end of receive process */
HAL_I2C_SlaveTxCpltCallback(hi2c);
}
return HAL_OK;
}
static HAL_StatusTypeDef I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c)
{
while(hi2c->XferCount != 0U)
{
/* Wait until RXNE flag is set */
if(I2C_WaitOnRXNEFlagUntilTimeout(hi2c, 0xffffffff, 0) != HAL_OK)
{
/* Disable Address Acknowledge */
CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);
if(hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT)
{
return HAL_TIMEOUT;
}
else
{
return HAL_ERROR;
}
}
/* Read data from DR */
(*hi2c->pBuffPtr++) = hi2c->Instance->DR;
hi2c->XferCount--;
if((hi2c->XferCount == 0U) && (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN))
{
/* Last Byte is received, disable Interrupt */
__HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF);
/* Set state at HAL_I2C_STATE_LISTEN */
hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
hi2c->State = HAL_I2C_STATE_LISTEN;
/* Call the Rx complete callback to inform upper layer of the end of receive process */
HAL_I2C_SlaveRxCpltCallback(hi2c);
}
}
return HAL_OK;
}
改造了之后,就可以直接接收/发送多个字节的数据啦啦啦~
上一篇:【STM32 IIC详解】stm32 IIC从机模式(中断方式收发数据)
下一篇:STM32F207上I2C作为从机的硬件中断实现的代码及注释
设计资源 培训 开发板 精华推荐
- 2022 Digi-Key KOL 视频系列:四翼扑翼机(仿生鸟)原理及设计解析
- 深入东芝参考设计库:夯实您的设计库,让您的设计更出彩
- 福禄克有奖直播|新型8.5位数字多用表技术发展及应用
- 下载有礼|ADI 用于多路抽头输出隔离电源的简易解决方案
- 【抢楼】正式开始!来抢TI LM3S811评估板吧!!!
- 打卡世健的ADI之路首站“工业自动化站”,赢Kindle、《新概念模拟电路》
- 有奖直播 | 与英飞凌一同革新您的电动汽车温控系统:集成热管理系统(低压侧)
- 新春寻宝记,泰克送福利!快来开启你的寻宝之旅~
- 有奖直播:赋能移动电源,贝能推出1800W全数字双向电源方案
- 【世健的ADI之路主题游】 第三站:了解物联网前沿器件与方案,打卡赢Kindle、《新概念模拟电路》