
最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。 网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面, 如果有不对的地方,欢迎指正,大家互相学习一下! STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。 1,初始化部分:配置时钟和引脚,不使用时钟延长的功能 2,I2C1_IRQHandler 主要处理中断事件 在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。 根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。 (1)发送数据,流程如下 ![]() 这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下 ![]() (2) 接收数据,流程如下 ![]() |
IIC SLAVE mode.zip
下载1.84 KB, 下载次数: 901
我在网上找到你们的代码。我复制了一下。有些问题想了解一下
void I2C_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
/*!< GPIO configuration */
/*!< Configure sEE_I2C pins: SCL */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
GPIO_Init(GPIOA , &GPIO_InitStruct);
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Connect PXx to I2C_SCL*/
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
//下面是IIC中断函数的实现
void I2c_Init(void)
{
I2C_GPIO_Configuration();
I2C_Configuration();
}
void I2C1_IRQHandler(void)
{
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{
printf("发送模式 \r\n");
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;
I2C1->ICR |= I2C_ICR_ADDRCF;
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
}
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{
printf("接收模式 \r\n");
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF;
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
if(Tx_count >= Tx_MAX)
{
Tx_count = 0;
//tx ok
}
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;
Tx_count = 0;
}
}
这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。
void I2C_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*!< sEE_I2C Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
/*!< GPIO configuration */
/*!< Configure sEE_I2C pins: SCL */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
GPIO_Init(GPIOA , &GPIO_InitStruct);
/*!< Configure sEE_I2C pins: SDA */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Connect PXx to I2C_SCL*/
GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}
//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
/* I2C configuration */
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStruct.I2C_DigitalFilter = 0x00;
I2C_InitStruct.I2C_OwnAddress1 = ADDR;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStruct.I2C_Timing = 0xb0420f13; //100Kbits
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStruct);
I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
//---------------------------- Peripheral and DMA interrupts Initialization ------------------
// Initialize I2C1 interrupts
/* Enable the IRQ channel */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* Configure NVIC for I2C1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
//下面是IIC中断函数的实现
void I2c_Init(void)
{
I2C_GPIO_Configuration();
I2C_Configuration();
}
void I2C1_IRQHandler(void)
{
u32 AddCode;
// I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
__IO uint32_t I2CFlagStatus = 0x00000000;
I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
// printf("recv data\r\n");
if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
{
AddCode = (I2C1->ISR & 0xfe0000); //读取ADDCODE 32:17位
printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
if(I2C1->ISR&I2C_ISR_DIR) //tx mode
{
printf("发送模式 \r\n");
Tx_count = 0;
I2C1->ISR |= I2C_ISR_TXE;
I2C1->ICR |= I2C_ICR_ADDRCF;
if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
}
if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
{
printf("接收模式 \r\n");
Rx_count= 0;
I2C1->ICR |= I2C_ICR_ADDRCF;
}
}
else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
{
Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
if(Rx_count>=Rx_MAX)
{
Rx_count=0;
//rx ok
}
printf("Rx_buffer : %s\r\n",Rx_buffer);
}
else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
{
I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
if(Tx_count >= Tx_MAX)
{
Tx_count = 0;
//tx ok
}
}
else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
{
printf("停止检查标志位 \r\n");
I2C1->ICR |= I2C_ICR_STOPCF;
Rx_count = 0;
Tx_count = 0;
}
}