STM32 I2C从机发送数据

         

stm32 I2C主机发送功能在网上有很多例程,调试也很容易,从机发送数据的介绍很少,鉴于本人刚开始调试单片机程序不久,花了一整天也没调试通,最后在部门领导的帮助下,通过示波器及单步调试程序,查看寄存器状态值,终于实现了。下面主要介绍下从机发送数据注意事项。(附带例程)

1、相信使用I2C的都知道,从机是不能主动发送数据的,开始条件都是由主机生成。

 

2、根据参考文档,I2C默认是从机模式,只有在生成起始条件后,才会从从机模式自动切换到主机模式。所以作为从机模式使用时不能生成起始条件。

 

3、附图1,为从机发送器的传送时序图,截图于参考手册,图中说明部分讲述了怎样能清除事件,这点很重要,每次事件是都要去清除才可以去检测下一个事件,否则很可能检测不到其他事件,我当初就是死在这上面的。

 

4、需要的数据发送完成了,根据附图1和2可知,主机需要发送一个NACK,从机有NACK应答,当你以为这样可以的时候就大错特错了。文档中有句话,要在读倒数第二个字节之后发送,而非所有字节发送完成再发送。仔细看附图1中说明部分[EV3TxE=1,写DR将清除该事件;移位寄存器非空。],如果不清除该事件的话,那对不起,你根本就检测不到EV3-2事件。所以在需要传输的数据传输完时,再向DR寄存器中写入一个数据后发送NACK就行了,这个数据是我们不需要的,写什么不重要,目的是为了清除事件(EV3)罢了(也可以在最后一个数据之前发送NACK,就不需要写入无用数据了,这里没有测试其他办法就不赘述了)


 

 

附图1:从发送器的传送序列图


附图2: 主接收器传送序列图


 

 

附bsp_i2c.c源码:

/**  ******************************************************************************

  * @file   bsp_i2c.c

  * @author Eason

  * @version V1.0

  * @date   2014-09-15

  * @brief  I2C应用函数接口

 ******************************************************************************

  * @attention

  *

  * 实验平台:野火 iSO-MINISTM32 开发板

  * 固件库版本V3.5

 *****************************************************************************

  */

 

#include"bsp_i2c.h"

 

/* Private typedef-----------------------------------------------------------*/

typedef enum{FAILED = 0, PASSED = !FAILED} TestStatus;

 

/* Private define------------------------------------------------------------*/

#defineI2C1_SLAVE_ADDRESS7     0x30

#defineI2C2_SLAVE_ADDRESS7     0x24

#defineBufferSize              4

#defineClockSpeed              300000

 

/* Privatevariables ---------------------------------------------------------*/

u8I2C1_Buffer_Tx[BufferSize] = {1,20,50,100};

u8I2C2_Buffer_Rx[BufferSize] = {0};

u8 TxIdx = 0,RxIdx = 0;

volatileTestStatus TransferStatus = FAILED;

 

/******************************************************************************

* FunctionName  : I2C_GPIO_Config

* Description     : Configuresthe different GPIO ports.

* Input          : None

* Output         : None

* Return         : None

******************************************************************************/

void I2C_GPIO_Config(void)

{

       GPIO_InitTypeDefGPIO_InitStructure;

 

         /* Enable peripheral clocks--------------------------------------------------*/

       /*GPIOB Periph clock enable */

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

       /*I2C1 and I2C2 Periph clock enable */

       RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1| RCC_APB1Periph_I2C2, ENABLE);

 

       /*Configure I2C1 pins: SCL and SDA ----------------------------------------*/

       GPIO_InitStructure.GPIO_Pin=  GPIO_Pin_6 | GPIO_Pin_7; //选择待设置的GPIO管脚

       GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;      //管脚速率50MHz

       GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_OD;  //复用开漏输出

       GPIO_Init(GPIOB,&GPIO_InitStructure);

 

       /*Configure I2C2 pins: SCL and SDA ----------------------------------------*/

       GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10 | GPIO_Pin_11;

       GPIO_Init(GPIOB,&GPIO_InitStructure);

}

 

/******************************************************************************

* FunctionName  : I2C_Master_Init

* Description    : I2C Master initialize.

* Input          : None

* Output         : None

* Return         : None

******************************************************************************/

voidI2C_Master_Init(void)

{

         I2C_InitTypeDef  I2C_InitStructure;

         /* I2C1 configuration------------------------------------------------------*/

       I2C_InitStructure.I2C_Mode= I2C_Mode_I2C;

       I2C_InitStructure.I2C_DutyCycle= I2C_DutyCycle_2;

       I2C_InitStructure.I2C_OwnAddress1= I2C1_SLAVE_ADDRESS7;

       I2C_InitStructure.I2C_Ack= I2C_Ack_Enable;

       I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;

       I2C_InitStructure.I2C_ClockSpeed= ClockSpeed;

       I2C_Init(I2C1,&I2C_InitStructure);

 

         I2C_Cmd(I2C1, ENABLE);

}

 

/******************************************************************************

* FunctionName  : I2C_Slave_Init

* Description     :I2C Slave initialize.

* Input          : None

* Output         :None

* Return         : None

******************************************************************************/

voidI2C_Slave_Init(void)

{

         I2C_InitTypeDef  I2C_InitStructure;

       /*I2C2 configuration ------------------------------------------------------*/

         I2C_InitStructure.I2C_Mode =I2C_Mode_I2C;

       I2C_InitStructure.I2C_DutyCycle= I2C_DutyCycle_2;

       I2C_InitStructure.I2C_OwnAddress1= I2C2_SLAVE_ADDRESS7;

       I2C_InitStructure.I2C_Ack= I2C_Ack_Enable;

       I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;

       I2C_InitStructure.I2C_ClockSpeed= ClockSpeed;

       I2C_Init(I2C2,&I2C_InitStructure);

        

         I2C_Cmd(I2C2, ENABLE);

}

 

voidI2C_Mode_Init(void)

{

         I2C_GPIO_Config();

         I2C_Master_Init();

         I2C_Slave_Init();

}

/******************************************************************************

* FunctionName  : Buffercmp

* Description    : Compares two buffers.

* Input          : - pBuffer1, pBuffer2: buffers to becompared.

*                : - BufferLength: buffer'slength

* Output         : None

* Return         : PASSED: pBuffer1 identical topBuffer2

*                  FAILED: pBuffer1 differs frompBuffer2

******************************************************************************/

TestStatusBuffercmp(u8* pBuffer1, u8* pBuffer2, u16 BufferLength)

{

  while(BufferLength--)

  {

    if(*pBuffer1 != *pBuffer2)

    {

      return FAILED;

    }

   

    pBuffer1++;

    pBuffer2++;

  }

 

  return PASSED; 

}

 

/*******************************************************************************

* FunctionName  : I2C_Transmission

* Description    : Data Transmission.

* Input          : None

* Output         : None

* Return         : None

******************************************************************************/

voidI2C_Transmission(void)

{

  I2C_GenerateSTART(I2C1, ENABLE);

  while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));  

  /* Send I2C2 slave Address for read*/

  I2C_Send7bitAddress(I2C1,I2C2_SLAVE_ADDRESS7, I2C_Direction_Receiver);

 

    /* Test on I2C2 EV1 and clear it */

  while(!I2C_CheckEvent(I2C2,I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED));

    /* Test on I2C1 EV6 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

 

  /* Send data */

  while (RxIdx < BufferSize)

  {

    /* Send I2C2 data */

    I2C_SendData(I2C2,I2C1_Buffer_Tx[TxIdx++]);

   /* Test on I2C1 EV7 and clear it */

         while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));

         while(!I2C_CheckEvent(I2C2,I2C_EVENT_SLAVE_BYTE_TRANSMITTED)); 

    /* Store received data on I2C1 */

    I2C2_Buffer_Rx[RxIdx++] =I2C_ReceiveData(I2C1);         

  }

  I2C_SendData(I2C2, 0);  //此处写DR寄存器目的是为了清除EV3事件

 

  RxIdx = 0;

  TxIdx = 0;

  I2C_AcknowledgeConfig(I2C1,DISABLE); //主机发送NACK 

  while(!I2C_CheckEvent(I2C2,I2C_EVENT_SLAVE_ACK_FAILURE));

  while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));

    /*Clear I2C2 AF flag */

  I2C_ClearFlag(I2C2, I2C_FLAG_AF);

 

  /* Send I2C1 STOP Condition */

  I2C_GenerateSTOP(I2C1, ENABLE);

 

  /* Check the corectness of written data */

  TransferStatus = Buffercmp(I2C1_Buffer_Tx,I2C2_Buffer_Rx,BufferSize);

}

 



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值