STM32硬件I2C 调试

本文介绍了STM32F7和STM32F1的I2C通信调试,重点在于RTOS环境下的从机和裸机环境下的主机初始化配置。详细阐述了I2C初始化程序,包括设置时钟速度、地址模式等,并展示了中断及传输函数的使用。通过HAL库函数实现主机发送地址、从机地址匹配中断及后续数据传输的处理。
摘要由CSDN通过智能技术生成

前言

STM32F7和STM32F1的IIC通讯调试,因为F7的环境是FREERTOS,故而选择硬件IIC的方式更不受系统影响。

初始化程序

F767(RTOS)从机

// An highlighted block
I2C_HandleTypeDef  I2C_Handle;  /*	IIC句柄	*/

/*	函数声明 			*/
/**
 * @brief  iic 初始化
 * @param  None
 * @retval None
 */
void IIC_Init(void)
{

	I2C_Handle.Instance = I2C1;
	I2C_Handle.Init.Timing = 0x00000000; //1KHZ
	I2C_Handle.Init.OwnAddress1 = I2C_ADDRESS;	/* 此处设定从机地址1 */
	I2C_Handle.Init.OwnAddress2	= 0xFE;			/* 此处设定从机地址2 */
	I2C_Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; /* 地址模式 */
	I2C_Handle.Init.DualAddressMode	=	I2C_DUALADDRESS_DISABLE;/* 关闭双地址模式 */
	I2C_Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;/*  */
	I2C_Handle.Init.NoStretchMode		=	I2C_NOSTRETCH_DISABLE;/* 禁止延长 */
	I2C_Handle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;/* 无掩码 */
	HAL_I2C_Init(&I2C_Handle);
	
	if(HAL_I2C_EnableListen_IT(&I2C_Handle) != HAL_OK)/* Transfer error in reception process */
			printf("初始化失败\r\n");
	else
		printf("IIC初始化成功\r\n");
}

HAL_I2C_EnableListen_IT()是使能监听中断,作为从机必须要开启该中断才能有效匹配地址。

/**
  * Initializes the Global MSP.
  */	
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
		/*使能I2C时钟*/
	__I2C1_CLK_ENABLE();
	if(hi2c->Instance==I2C1)
	{
		/*使能I2C的IO口时钟*/
		SCL_CLK_ENABLE();
		SDA_CLK_ENABLE();
		/*配置I2C的SCL口*/   
		GPIO_InitStructure.Pin = SCL_PIN;
		GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
		GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
		GPIO_InitStructure.Pull  = GPIO_NOPULL;
		GPIO_InitStructure.Alternate = SCL_AF;
		HAL_GPIO_Init(SCL_PORT, &GPIO_InitStructure);
		/*配置I2C的SDA口*/  
		GPIO_InitStructure.Pin = SDA_PIN;
		GPIO_InitStructure.Alternate = SDA_AF;
		HAL_GPIO_Init(SDA_PORT, &GPIO_InitStructure);
		/* Force the I2C peripheral clock reset */  
		__I2C1_FORCE_RESET(); 
		/* Release the I2C peripheral clock reset */  
		__I2C1_RELEASE_RESET();
		
    	/* I2C1 interrupt Init */
    	HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
    	HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
	}
}

到这里从机初始化配置已经完成,下面是主机的初始化配置。

F103(裸机)主机

I2C_HandleTypeDef I2C_Handle;

HAL_StatusTypeDef I2C_MasterInit(void)
{
  I2C_Handle.Instance = I2C1;
  I2C_Handle.Init.ClockSpeed = 1000; //hz
  I2C_Handle.Init.DutyCycle = I2C_DUTYCYCLE_2;
  I2C_Handle.Init.OwnAddress1 = 0xF0;/* 主机地址 */
  I2C_Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  I2C_Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  I2C_Handle.Init.OwnAddress2 = 0;
  I2C_Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  I2C_Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
	
  if (HAL_I2C_Init(&I2C_Handle) == HAL_OK)
		return HAL_OK;
	else
		return HAL_ERROR;
}


void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{

  GPIO_InitTypeDef GPIO_InitStruct;
	/* Peripheral clock enable */
  __HAL_RCC_I2C1_CLK_ENABLE();
  if(hi2c->Instance==I2C1)
  {
	__HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2C1 GPIO Configuration    
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2C1 interrupt Init */
    HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
    HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
  /* USER CODE BEGIN I2C1_MspInit 1 */
  /* Force the I2C peripheral clock reset */  
	__HAL_RCC_I2C1_FORCE_RESET(); 
	/* Release the I2C peripheral clock reset */  
	__HAL_RCC_I2C1_RELEASE_RESET();

  }

}


中断及传输函数

首先来讲一下IIC通讯的过程,

  • 1、主机发送地址到总线上
  • 2、从机触发地址匹配中断,成功后根据数据类型进行对应的操作
  • 3、主机完成传输并产生stop

第1步,在主机使用传输函数,此处我们使用的是HAL_I2C_Master_Transmit 或者 HAL_I2C_Master_Receive,先以发送“写”为例。

第2步,从机会自动匹配地址,并产生中断,但后续需要我们在中断中处理:

uint8_t DebugReceData ;
/**
  * @brief  Slave Address Match callback.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  TransferDirection: Master request Transfer Direction (Write/Read), value of @ref I2C_XferOptions_definition
  * @param  AddrMatchCode: Address Match Code
  * @retval None
  */
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
  if(AddrMatchCode == I2C_ADDRESS)
  {
    /* First of all, check the transfer direction to call the correct Slave Interface */
    if(TransferDirection == I2C_DIRECTION_TRANSMIT) //写
    {
    	HAL_I2C_Slave_Sequential_Receive_IT(&I2C_Handle, &DebugReceData, 1, I2C_FIRST_AND_LAST_FRAME);//重新开始中断,并接收随后的数据
    }
    else //读
   	{
		HAL_I2C_Slave_Sequential_Transmit_IT(&I2C_Handle, &DebugReceData, 1, I2C_FIRST_AND_LAST_FRAME);//重新开始中断,并发送数据
	}
}
  else
  {
    /* Call Error Handler, Wrong Address Match Code */
    Error_Handler();
  }
}

地址匹配完成后,如果是写命令则会接收后续数据,可以在接收中断函数中处理。

HAL_I2C_SlaveRxCpltCallback();
HAL_I2C_MasterRxCpltCallback();

另外从机还需要增加监听中断的处理,需要重新开启监听功能。

/**
  * @brief  Listen Complete callback.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @retval None
  */
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
	/* 如果要进行丛机接收工作,丛机必须要重新开启监听中断 */
	if(hi2c == &I2C_Handle)
		{
		   HAL_I2C_EnableListen_IT(&I2C_Handle);
		}

  /* Communication is completed */
}

后续待更新…

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值