四旋翼无人机从0到1的实现(十三)无人机MCU驱动→I2C

Author:家有仙妻谢掌柜
Date:2021/2/18

今年会更新一个系列,小四轴无人机从功能设计→思维导图→原理图设计→PCBLayout→焊接PCB→程序代码的编写→整机调试一系列,以此记录自己的成长历程!
这个小四轴无人机是大学时期学习制作的,加上现在工作学习对嵌入式的理解更加深入,因此想要重新梳理一下小四轴,之后在此基础上实现大四轴的飞控设计,这些都将在工作之余完成!

//小四轴无人机设计MCU与MPU6500进行通信,用到I2C
#include "i2c.h"

volatile uint32_t _time_out = LONG_TIMEOUT;
/*******************************************************************************
 * fuction	i2c_init
 * brief	i2c配置初始化
 * param	无
 * return	无
 *******************************************************************************/ 
void i2c_init(void)
{
    
    
	/*结构体变量定义*/
	GPIO_InitTypeDef  GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitStructure;
	/*开启引脚时钟*/
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE); //开的是IO口的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);//开的是I2C的时钟
	/*开启引脚复用功能PA9/PA10*/
  GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_4);
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource7, GPIO_AF_4);
	/*引脚的配置PA9/PA10*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOF,&GPIO_InitStructure);	
  /*I2C的配置*/
	I2C_InitStructure.I2C_Mode =  I2C_Mode_I2C;                              //I2C  模式
	I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
	I2C_InitStructure.I2C_DigitalFilter = 0x00;
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_Timing = SENSOR_I2C_TIMING;     //宏定义 0x00200404
	I2C_Init(I2C2,&I2C_InitStructure);	
	I2C_Cmd(I2C2, ENABLE);	
}
/*******************************************************************************
 * fuction	i2c_timeout_callback
 * brief	I2C通信超时复位函数
 * param	无
 * return	超时标志 //  成功  失败  超时  做一个枚举
 *******************************************************************************/ 
I2C_StatusTypDef i2c_timeout_callback(void)
{
    
    
	I2C2->CR1|=I2C_CR1_SWRST;              //   I2C复位
	return I2C_TIMEOUT;	
}
/*******************************************************************************
 * fuction	i2c_reg_write
 * brief	从主机寄存器写一个字节数据
 * param	从机地址  寄存器地址  数据
 * return	成功或失败 //  成功  失败  超时  做一个枚举
 *******************************************************************************/ 
I2C_StatusTypDef i2c_reg_write(uint8_t Device_address,uint8_t reg_address,uint8_t data)
{
    
    
	_time_out = LONG_TIMEOUT;
	/* 测试I2C是否空闲   				 */
	/* 不等于RESET就是说明还在忙 */
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_BUSY)!= RESET)//  标志位
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}	
	/* I2C处于空闲状态。则开始I2C通讯进行相关配置  写设备地址 */	
	I2C_TransferHandling(I2C2,Device_address,1,I2C_Reload_Mode,I2C_Generate_Start_Write) ;		//  调用写的库函数
	/*   等待完成*/
	_time_out = LONG_TIMEOUT;
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_TXIS)== RESET)//  标志位 
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}	
	/* I2C处于空闲状态。则开始I2C通讯进行相关配置  写设备寄存器地址 */	
	I2C_SendData(I2C2,reg_address);
	/*   等待发送完成*/
	_time_out = LONG_TIMEOUT;
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_TCR)== RESET)//  标志位 
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}
	/* I2C处于空闲状态。则开始I2C通讯进行相关配置  写设备寄存器数据 */
	I2C_TransferHandling(I2C2,Device_address,1,I2C_AutoEnd_Mode,I2C_No_StartStop);
	/* 发送要写的数据 */
	I2C_SendData(I2C2,data);
	/*   等待停止标志位完成*/
	_time_out = LONG_TIMEOUT;
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_STOPF)== RESET)//  标志位 
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}
	/*   清除停止标志位*/
	I2C_ClearFlag(I2C2,I2C_ICR_STOPCF);

	return  I2C_OK;	
}
/*******************************************************************************
 * fuction	i2c_read
 * brief	从从机寄存器读取一个字节数据
 * param	从机地址  寄存器地址  数据长度  数据存放缓存区
 * return	成功或失败 //  成功  失败  超时  做一个枚举
 *******************************************************************************/ 
I2C_StatusTypDef i2c_read(uint8_t Device_address,uint8_t reg_address,uint8_t Len,uint8_t *buff)
{
    
    
	uint8_t 	Data_Num = 0;
	_time_out = LONG_TIMEOUT;
	/* 测试I2C是否空闲   */
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_BUSY)!= RESET)//  标志位 
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}	
	/* I2C处于空闲状态。则开始I2C通讯进行相关配置  写设备地址 */	
	I2C_TransferHandling(I2C2,Device_address,1,I2C_SoftEnd_Mode,I2C_Generate_Start_Write) ;		//  调用写的库函数
	/*   等待完成*/
	_time_out = LONG_TIMEOUT;
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_TXIS)== RESET)//  标志位 
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}	
	/* I2C处于空闲状态。则开始I2C通讯进行相关配置  写设备寄存器地址 */	
	I2C_SendData(I2C2,reg_address);
	/*   等待发送完成*/
	_time_out = LONG_TIMEOUT;
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_TC)== RESET)//  标志位 
	{
    
    
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}
	/* I2C处于空闲状态。则开始I2C通讯进行相关配置  读取,自动结束 */
	I2C_TransferHandling(I2C2,Device_address,Len,I2C_AutoEnd_Mode,I2C_Generate_Start_Read);
	/*
	for(i=0,i<12,i++){
	}
	*/
	Data_Num = 0;
	/* 等待数据被接收 */      //    Len = 12   Data_Num = 0
	while( Data_Num != Len)
	{
    
    
		_time_out = LONG_TIMEOUT;
		while(I2C_GetFlagStatus(I2C2,I2C_ISR_RXNE)== RESET)//  标志位 
		{
    
    
			if((_time_out--) == 0)
			{
    
    
				return  i2c_timeout_callback(); 
			}
		}
		/* 从I2C2->RXDR寄存器获取数据 */ 	
		*buff = I2C_ReceiveData(I2C2);
		buff++;//指向下一个地址
		Data_Num++;			
	}
	/* 等待STOOPF标志位置位 */
	_time_out = LONG_TIMEOUT;
	while(I2C_GetFlagStatus(I2C2,I2C_ISR_STOPF)== RESET)//  标志位 
	{
    
     
		if((_time_out--) == 0)
		{
    
    
			return  i2c_timeout_callback(); 
		}
	}
	/* 清除STOPCF标志位置位 */
	I2C_ClearFlag(I2C2,I2C_ICR_STOPCF);
	/* 如果读取结束,则返回OK */
	return  I2C_OK;				
}
	 
	
	

#ifndef _I2C_H__
#define _I2C_H__


#include "board_define.h"
#include "var_global.h"
#define SENSOR_I2C_TIMING  0x00200404
#define LONG_TIMEOUT  81920

typedef enum {
    
    
	I2C_OK = 0,
	I2C_ERROR = 1,
	I2C_TIMEOUT = 2
}I2C_StatusTypDef;

void i2c_init(void);
I2C_StatusTypDef i2c_reg_write(uint8_t Device_address,uint8_t reg_address,uint8_t data);
I2C_StatusTypDef i2c_read(uint8_t Device_address,uint8_t reg_address,uint8_t Len,uint8_t *buff);



#endif



猜你喜欢

转载自blog.csdn.net/FutureStudio1994/article/details/113854075