STM32 HAL库 I2C 学习

发布时间:2024-01-26  

static void MX_I2C1_Init(void)

{

hi2c1.Instance = I2C1;                      设置I2C实体

hi2c1.Init.ClockSpeed = 100000;                         设置clk速率,从而设置TRISE,CCR,DUTY等寄存器

hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;                    设置占空比T low /T high  = 2 (CCR寄存器14位)

hi2c1.Init.OwnAddress1 = 100;               设置地址A0,8位地址

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;  设置为7位地址模式

hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;  禁止双地址

hi2c1.Init.OwnAddress2 = 0;                                     第2地址

hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;   禁止广播

hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;      禁止时钟拉伸

if (HAL_I2C_Init(&hi2c1) != HAL_OK)

{

Error_Handler();

}

}

MX_I2C1_Init调用库函数HAL_I2C_Init()(在stm32f1xx_hal_i2c.c中定义)来初始化I2C接口,需要初始化的数据已经在MX_I2C1_Init中定义了

HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)

{

uint32_t freqrange = 0;

uint32_t pclk1 = 0;

/* Check the I2C handle allocation */

if(hi2c == NULL)

{

return HAL_ERROR;

}

/* Check the parameters */

assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));

assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed));

assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle));

assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1));

assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode));

assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode));

assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2));

assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode));

assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode));

if(hi2c->State == HAL_I2C_STATE_RESET)

{

/* Allocate lock resource and initialize it */

hi2c->Lock = HAL_UNLOCKED;

/*配置相关硬件: GPIO, CLOCK, NVIC */

HAL_I2C_MspInit(hi2c);

}

hi2c->State = HAL_I2C_STATE_BUSY;

/* Disable the selected I2C peripheral */

__HAL_I2C_DISABLE(hi2c);

/* Get PCLK1 frequency */

pclk1 = HAL_RCC_GetPCLK1Freq();

/* Calculate frequency range */

freqrange = I2C_FREQ_RANGE(pclk1);

/*---------------------------- I2Cx CR2 Configuration I2C模块时钟频率 ----------------------*/

/* Configure I2Cx: Frequency range */

hi2c->Instance->CR2 = freqrange;

/*---------------------------- I2Cx TRISE Configuration --------------------*/

/* Configure I2Cx: Rise Time */

hi2c->Instance->TRISE = I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed);

/*---------------------------- I2Cx CCR Configuration ----------------------*/

/* Configure I2Cx: Speed */

hi2c->Instance->CCR = I2C_Configure_Speed(hi2c, pclk1);

/*---------------------------- I2Cx CR1 Configuration ----------------------*/

/* Configure I2Cx: Generalcall and NoStretch mode */

hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode);

/*---------------------------- I2Cx OAR1 Configuration ---------------------*/

/* Configure I2Cx: Own Address1 and addressing mode */

hi2c->Instance->OAR1 = (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1);

/*---------------------------- I2Cx OAR2 Configuration ---------------------*/

/* Configure I2Cx: Dual mode and Own Address2 */

hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2);

/* Enable the selected I2C peripheral */

__HAL_I2C_ENABLE(hi2c);

/* 设置句柄相关状态位*/

hi2c->ErrorCode = HAL_I2C_ERROR_NONE;

hi2c->State = HAL_I2C_STATE_READY;

hi2c->Mode = HAL_I2C_MODE_NONE;

return HAL_OK;

}

库函数HAL_I2C_Init()检查句柄的参数是否有效,然后再调用HAL_I2C_MspInit()(在stm32f1xx_hal_msp.c中定义)进行相关GPIO,时钟,中断方面的设置,然后才根据句柄所带的参数对I2C模块的寄存器进行配置。

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(hi2c->Instance==I2C1)

{

/**I2C1 GPIO Configuration   

PB6     ------> I2C1_SCL

PB7     ------> I2C1_SDA

*/

GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* Peripheral clock enable */

__HAL_RCC_I2C1_CLK_ENABLE();

/* Peripheral interrupt init 此处设置了开启I2C事件中断*/

HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);

/* USER CODE BEGIN I2C1_MspInit 1 */

/* USER CODE END I2C1_MspInit 1 */

}

}

到此I2C的模块已经初始化已经完成,如果有中断发生就会调用中断处理函数I2C1_EV_IRQHandler(void) (在stm32f1xx_it.c中定义),然而调用真正的中断服务函数HAL_I2C_EV_IRQHandler(&hi2c1)(stm32f1xx_hal_i2c.c中定义)

void I2C1_EV_IRQHandler(void)

{

/* USER CODE BEGIN I2C1_EV_IRQn 0 */

/* USER CODE END I2C1_EV_IRQn 0 */

HAL_I2C_EV_IRQHandler(&hi2c1);

/* USER CODE BEGIN I2C1_EV_IRQn 1 */

/* USER CODE END I2C1_EV_IRQn 1 */

}

void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)

{

uint32_t tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;

/* Master or Memory mode selected */

if((hi2c->Mode == HAL_I2C_MODE_MASTER) ||

(hi2c->Mode == HAL_I2C_MODE_MEM))

{

/* I2C in mode Transmitter -----------------------------------------------*/

if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TRA) == SET)

{

tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE);

tmp2 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_BUF);

tmp3 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF);

tmp4 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_EVT);

/* TXE set and BTF reset -----------------------------------------------*/

if((tmp1 == SET) && (tmp2 == SET) && (tmp3 == RESET))

{

I2C_MasterTransmit_TXE(hi2c);

}

/* BTF set -------------------------------------------------------------*/

else if((tmp3 == SET) && (tmp4 == SET))

{

I2C_MasterTransmit_BTF(hi2c);

}

}

/* I2C in mode Receiver --------------------------------------------------*/

else

{

tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE);

tmp2 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_BUF);

tmp3 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF);

tmp4 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_EVT);

/* RXNE set and BTF reset -----------------------------------------------*/

if((tmp1 == SET) && (tmp2 == SET) && (tmp3 == RESET))

{

I2C_MasterReceive_RXNE(hi2c);

}

/* BTF set -------------------------------------------------------------*/

else if((tmp3 == SET) && (tmp4 == SET))

{

I2C_MasterReceive_BTF(hi2c);

}

}

}

/* Slave mode selected */

else

{

tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);

tmp2 = __HAL_I2C_GET_IT_SOURCE(hi2c, (I2C_IT_EVT));

tmp3 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);

tmp4 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TRA);

/* ADDR set --------------------------------------------------------------*/

if((tmp1 == SET) && (tmp2 == SET))

{

I2C_Slave_ADDR(hi2c);

}

/* STOPF set --------------------------------------------------------------*/

else if((tmp3 == SET) && (tmp2 == SET))

{

I2C_Slave_STOPF(hi2c);

}

/* I2C in mode Transmitter -----------------------------------------------*/

else if(tmp4 == SET)

{

tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE);

tmp2 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_BUF);

tmp3 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF);

tmp4 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_EVT);

/* TXE set and BTF reset -----------------------------------------------*/

if((tmp1 == SET) && (tmp2 == SET) && (tmp3 == RESET))

{

I2C_SlaveTransmit_TXE(hi2c);

}

/* BTF set -------------------------------------------------------------*/

else if((tmp3 == SET) && (tmp4 == SET))

{

I2C_SlaveTransmit_BTF(hi2c);

}

}

/* I2C in mode Receiver --------------------------------------------------*/

else

{

tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE);

tmp2 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_BUF);

tmp3 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF);

tmp4 = __HAL_I2C_GET_IT_SOURCE(hi2c, I2C_IT_EVT);

/* RXNE set and BTF reset ----------------------------------------------*/

if((tmp1 == SET) && (tmp2 == SET) && (tmp3 == RESET))

{

I2C_SlaveReceive_RXNE(hi2c);

}

/* BTF set -------------------------------------------------------------*/

else if((tmp3 == SET) && (tmp4 == SET))

{

I2C_SlaveReceive_BTF(hi2c);

}

}

}

}


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>