STM32F103使用硬件i2c作为从机模式

您所在的位置:网站首页 ev是什么模式 STM32F103使用硬件i2c作为从机模式

STM32F103使用硬件i2c作为从机模式

2024-07-14 15:45| 来源: 网络整理| 查看: 265

一、简单说明

本例子参考了ST官方历程,官方历程的链接如下

http://www.st.com/content/st_com/zh/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-library-expansion/stsw-stm32094.html

关于i2c的协议这里就不做描述了

关于STM32 i2c的模式可以在中文数据手册中查看

手册中已经描述,该模块默认工作在从模式,要想变为主模式,主要生产一个起始条件。(主模式的代码可以参考野火开发板的硬件i2c历程,本例子中也是使用野火开发板硬件i2c作为主机的)

二、i2c从机的配置     I2C_DeInit(I2C1);     /* I2C1 configuration ------------------------------------------------------*/     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//模式     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;     I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS7;//这个就是作为从机的地址,一定要配置正确     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//7位的地址     I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;     I2C_Init(I2C1, &I2C_InitStructure);

上面配置注意的就是从机地址,这就是主机要查询的从机地址

三、i2c从机中断的配置     /* Configure and enable I2Cx event interrupt -------------------------------*/     NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure);     /* Configure and enable I2C1 error interrupt -------------------------------*/     NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;     NVIC_Init(&NVIC_InitStructure); 标准库中的i2c一共有两个中断 一个是事件中断(EV_IRQ)和一个错误中断(ER_IRQ) EV_IRQ的中断只要响应EV1 EV2 EV4 之类的,后面会说明 ER_IRQ的中断只要响应没有应答和起始和停止条件出错等 四、使能中断 /* Enable I2C1 event and buffer interrupts */ I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, ENABLE); /* Enable I2C1 Error interrupts */ I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE); 使能了I2C1的这三个中断,每个中断的作用下面说明 五、中断处理函数 void I2C1_EV_IRQHandler(void) //事件中断处理函数 { switch (I2C_GetLastEvent(I2C1)) //获取i2c1的中断事件 { /* Slave Transmitter ---------------------------------------------------*/ case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: /* 这个和下面那个都是从发送模式下发送数据的,具体两个的区别我也不是很明白,感觉就是移位寄存器空与非 空的区别,准备好数据发送吧 */ I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx++]); break; case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: /* EV3 */ /* Transmit I2C1 data */ I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx++]); break; /* Slave Receiver ------------------------------------------------------*/ case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: /* EV1 */ /* 地址匹配中断,不管从发送和接收都要匹配地址,如下图244、243发送地址之后都会响应EV1 */ break; case I2C_EVENT_SLAVE_BYTE_RECEIVED: /* EV2 */ /* Store I2C1 received data */ /* 这个中断就是响应EV2中断,如下图244,每次主机发送完一个数据就会产生一个EV2的中断 */ I2C1_Buffer_Rx[Rx_Idx++] = I2C_ReceiveData(I2C1); /* 把接收到的中断填充到数组中 */ /* 注意:地址不会填充进来的 */ break; case I2C_EVENT_SLAVE_STOP_DETECTED: /* EV4 */ /* Clear I2C1 STOPF flag */ /* 这个就是正常停止的时候产生的一个停止信号 */ I2C_Cmd(I2C1, ENABLE); /* 我也不清楚这个为什么要这样,如果接收完一串数据之后,不响应主机的情况可以 关闭i2c,然后在处理完数据后再 从新配置i2c,记得是从新配置 */ Rx_Idx=0; i2c_event = EVENT_OPCOD_NOTYET_READ; break; default: break; } } void I2C1_ER_IRQHandler(void) { /* Check on I2C1 AF flag and clear it */ if (I2C_GetITStatus(I2C1, I2C_IT_AF)) { /* 这个就是图243中最后那个没有应答的中断,也就是发送了一串数据后的中断,可以做清零工作 */ I2C_ClearITPendingBit(I2C1, I2C_IT_AF); Tx_Idx = 0; i2c_event = EVENT_OPCOD_NOTYET_READ; } /* Check on I2C1 AF flag and clear it */ if (I2C_GetITStatus(I2C1, I2C_IT_BERR)) //这个就是起始和停止条件出错了 { I2C_ClearITPendingBit(I2C1, I2C_IT_BERR); } } 注意:i2c中断中不要printf打印信息, 否 则会出错

主要是参考了官方的历程,然后自己再调整一下逻辑即可使用。

最后的效果感觉还是挺稳定的,这篇文章主要是给大家抛砖引玉的作用,也记录一下自己调试几天的成果。 ST官网的历程还是挺多的,没遇到的知识可以去官网找找。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3