历史上的今天
今天是:2025年08月07日(星期四)
2019年08月07日 | stm32的HAL库i2c从机实现
2019-08-07 来源:eefocus
stm32的i2c默认就是slave模式,本文基于HAL库实现中断方式的接收和发送,首先是初始化gpio和i2c,代码如下:
I2C_HandleTypeDef I2cHandle;
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE() ;
__HAL_RCC_GPIOC_CLK_ENABLE() ;
/**I2C3 GPIO Configuration
PA8 ------> I2C3_SCL
PC9 ------> I2C3_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; //开漏输出(i2c需要这种模式)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C3_CLK_ENABLE();
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(I2C3_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C3_EV_IRQn);
HAL_NVIC_SetPriority(I2C3_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C3_ER_IRQn);
}
void I2c_config()
{
I2cHandle.Instance = I2C3; //此处使用i2c3
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; //7位地址模式
I2cHandle.Init.ClockSpeed = 1000000; //时钟支持最高1M
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; //关闭双地址模式
I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2cHandle.Init.OwnAddress1 = 0X34; //器件地址
I2cHandle.Init.OwnAddress2 = 0;
if(HAL_I2C_Init(&I2cHandle) != HAL_OK) //调用初始化函数
{
/* Initialization Error */
Error_Handler();
}
HAL_I2C_Slave_Receive_IT(&I2cHandle,i2c_slave_recv,I2C_REC_BYTES); //开启从机中断接收
}
i2c3中断回调函数:
void I2C3_ER_IRQHandler() //异常回调
{
HAL_I2C_ER_IRQHandler(&I2cHandle);
}
void I2C3_EV_IRQHandler() //事件回调(接收或发送)
{
HAL_I2C_EV_IRQHandler(&I2cHandle);
}
两个中断对应的中断事件如下图所示:

发送完成、接收完成和错误回调函数:
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
//发送完成回调函数
{
//一些其他操作
}
HAL_I2C_Slave_Receive_IT(&I2cHandle,i2c_slave_recv,I2C_REC_BYTES);
{
//一些其他操作
}
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
//接收完成回调函数
{
//一些其他操作
}
HAL_I2C_Slave_Transmit_IT(&I2cHandle,send_buffer,send_cnt);
{
//一些其他操作
}
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
//错误异常回调函数
}
实际操作时可以在接收完成中断中处理数据然后开启从机发送中断,在发送完成中断中开启从机接收中断,可以实现收发。
目前用HAL库发送必须将send_cnt的字节全部发送完成才行,不然通信会出问题。这个问题需要进一步解决。
上一篇:STM32--HAL库IIC
史海拾趣
|
vs2005上如何开发wince 5.0 应用程序(用的是Windows CE 5.0: Standard Software Development Kit ( 如题目: 我想把开发环境搭建好,已经安装的环境如下: 1.vs2005+sp1 2.Windows CE 5.0: Standard Software Development Kit (SDK)已经安装好了。 现在的问题是创建一个《智能设备应用程序》-》Platform SDK(STANDARDSDK_500)-》创建完成。 ...… 查看全部问答> |
|
USB过滤驱动中,怎样实现禁用U盘???????????????、 怎样实现在u盘插上后,用户无法打开,用户身份在经过验证后,才能打开。 现在用户验证已经没问题,就是不知道怎样先禁止u盘,然后再放行。… 查看全部问答> |
|
STM32F107的手册上说CAN具有512个字节的专用RAM,USB具有1.25K的专用RAM。我想请问下这个专用RAM是各个外设自带的 ...… 查看全部问答> |
|
刚教的单片机要考试了 大侠们帮个忙做几个题目啊!!!!!!! 用简单的汇编语言编程 1.编程计算从1+2+……+50 2.在RAM中有100个字节,起始地址为100H 找出中间的最小值放在700H中 试编写程序 3.是编写程序实现R4 R5指向的RAM单元中的高四位合并起来 放在地址为500H的单元中,期中R5指向的RAM单元的高四位放 ...… 查看全部问答> |
|
我用中断写了个程序输出1KHZ方波,貌似有问题,请高手帮我这个菜鸟看看啊…… #include<iom16v.h>#include<macros.h>#define interrupt_handler pwm:9void pwm(){ PORTB^=BIT(PB0); TCNT1H=0XFF; TCNT1L=0XEF;}void main(){TCCR1B=0X04; TCNT1H=0XFF;TCNT1L=0XEF;TIMSK|=BIT(2);SREG|=BIT(7); DDRB=0 ...… 查看全部问答> |
|
lm3s 引脚死锁原理及解决办法! GPIOAFSEL 寄存器是模式控制选择寄存器。向该寄存器中的任意位写“1”表示选择该GPIO线路为备用硬件控制(功能)所用。由于所有的位都在复位时都会清零,因此在默认的情况下,这些GPIO线路设置GPIO模式。对JTAG/S ...… 查看全部问答> |
|
VISHAY 推出的看视频抽礼品活动正在进行,欢迎参加! https://www.eeworld.com.cn/huodong/201405_Vishay/… 查看全部问答> |




