STM32 I2C从机

来源:互联网 发布:程序员的自我修养 微盘 编辑:程序博客网 时间:2024/05/18 10:27

STM32 I2C slave

I2C Slave配置

  1. I2C默认工作在从模式
  2. 需要在I2C_CR2寄存器设置输入时钟频率!
    初始化代码 I2C2

    /*GPIO与IIC初始化结构体*/  GPIO_InitTypeDef GPIO_InitStructure;  I2C_InitTypeDef I2C_InitStructure;  /*GPIO与IIC时钟使能*/  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE );     //GPIOB时钟使能  RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C2, ENABLE );      //IIC2时钟使能  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10|GPIO_Pin_11 ;   //初始化GPIO.B10(IIC2_SCL),GPIO.B11(IIC2_SDA)  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;           //最高输出速度50Hz  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;             //输入输出模式为复用功能开漏输出  GPIO_Init( GPIOB, &GPIO_InitStructure );                    //根据GPIO初始化结构体初始化GPIOB  I2C_DeInit(I2C2);                                           //复位I2C/*初始化IIC2*/  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                  //设置为IIC模式  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;          //设置IIC的占空比,低电平除以高电平值为2  I2C_InitStructure.I2C_OwnAddress1 = addr;                   //指定第一个设备的地址为7位地址 从设备地址为函数参数addr I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;                 //使能ACK信号  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;   //指定7位地址  I2C_InitStructure.I2C_ClockSpeed = 100000;                  //时钟频率,必须小于等于400KHz  I2C_Init( I2C2, &I2C_InitStructure );   I2C2->CR2&=0xff00;                 **//设置I2C输入时钟频率为4Mhz**  根据时钟树配置I2C2->CR2|=0x04; I2C_Cmd( I2C2, ENABLE );                                 //使能硬件IIC2  I2C_ITConfig(I2C2,I2C_IT_EVT|I2C_IT_BUF,ENABLE); 

地址匹配:

1. ack置1产生应答2. ADDR置位,会产生ITEVFEN中断

数据发送

TRA 位指示I2C处于发送模式还是接收模式,TRA = 1为发送

从发送:

1. 接收地址清除ADDR位后,从发送器发送数据到sda上2. 当ADDR位未被清除或者待发送数据未被写入DR寄存器,SCL会被拉低3.  当收到ack后,TxE置位,产生中断(使能ITEVFEN和ITBUFFEN)。

如果TxE被置位,但在下一个数据发送结束之前没有新数据写入到I2C_DR,BTF会被置位,读SR1写DR可清除BTF位

从接收:

1. 接收地址清除ADDR位后,从接收器从SDA收取数据到DR寄存器中。2. I2C接口在收到每个字节收据后都会做如下操作:3. 若ack位置位,则产生应答4. RxNE置位,产生中断5. 若RxNE置位,DR数据尚未被读出,BTF置位,BTF位未被清除之前,SCL拉低6. 读SR1写DR可清除BTF位

结束通信:

主设备产生停止条件,从机检测到停止条件后,stopf=1,产生中断。
I2c等待读sr1写cr1
中断处理函数

void I2C2_EV_IRQHandler(void){    uint8_t temp;    gwTimeout=0;    if(I2C_GetFlagStatus(I2C2,I2C_FLAG_BERR)){//        I2C_ClearFlag(I2C2,I2C_FLAG_BERR);    }    if(I2C_GetFlagStatus(I2C2,I2C_FLAG_ADDR)){        if(I2C_GetFlagStatus(I2C2,I2C_FLAG_TRA)){            I2C_SendData(I2C2,arryBuffer_Tx[gwOffset++]);        }        else{            gwOffset= I2C_ReceiveData(I2C2);        }    }    if(I2C_GetFlagStatus(I2C2,I2C_FLAG_RXNE)){        arryBuffer_Rx[gwOffset]= I2C_ReceiveData(I2C2);     }    if(I2C_GetFlagStatus(I2C2,I2C_FLAG_TXE))     {          I2C_SendData(I2C2,arryBuffer_Tx[gwOffset]);        gwOffset++;     }     if(I2C_GetFlagStatus(I2C2,I2C_FLAG_STOPF))     {        addr=0;        I2C2->CR1|= 0x0001;//清除I2C_FLAG_STOPF     }                  }