STM32F746 模拟I2C读取电子罗盘数据
[复制链接]
本帖最后由 天天好心情亲 于 2015-12-12 14:23 编辑
STM32F746官方没有模拟I2C例程,于是小编自己参考网上的一些大神的资料,自己写了一个模拟I2C读取电子罗盘数据的程序 /***************I2C程序***********************************/#include "stm32f7xx_hal_conf.h"
#define I2C_TIMING 0x40912732
/* I2C1 init function */
void I2C1_Config(void)
{
I2C_HandleTypeDef I2c1Handle;
GPIO_InitTypeDef gpioInitStruct;
__GPIOB_CLK_ENABLE();
__I2C1_CLK_ENABLE();
gpioInitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8;
gpioInitStruct.Mode = GPIO_MODE_OUTPUT_PP;//GPIO_MODE_AF_OD;
gpioInitStruct.Pull = GPIO_PULLUP;
gpioInitStruct.Speed = GPIO_SPEED_HIGH;
gpioInitStruct.Alternate = I2Cx_SCL_SDA_AF;
HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &gpioInitStruct);
I2c1Handle.Instance = I2C1;
I2c1Handle.Init.Timing = DISCOVERY_I2Cx_TIMING;//0x00303D5D;
I2c1Handle.Init.OwnAddress1 = 0;
I2c1Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2c1Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2c1Handle.Init.OwnAddress2 = 0;
I2c1Handle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
I2c1Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2c1Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&I2c1Handle);
/**Configure Analogue filter
*/
HAL_I2CEx_AnalogFilter_Config(&I2c1Handle, I2C_ANALOGFILTER_ENABLE);
I2C1_SCL_H;;
I2C1_SDA_H;;
}
uint32_t I2CStep;
void I2C1_Delay(void)
{
I2CStep=150;
while(I2CStep--);
}
uint8_t I2C1_Start(void)
{
I2C1_SDA_H;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
if(!I2C1_SDA) return 0; // 如果数据线忙,则推退出
I2C1_SDA_L;
return 1;
}
void I2C1_Stop(void)
{
I2C1_SCL_L;
I2C1_Delay();
I2C1_SDA_L;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
I2C1_SDA_H;
I2C1_Delay();
}
void I2C1_Ack(void)
{
I2C1_SCL_L;
I2C1_Delay();
I2C1_SDA_L;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
I2C1_SCL_L;
I2C1_Delay();
}
void I2C1_NAck(void)
{
I2C1_SCL_L;
I2C1_Delay();
I2C1_SDA_H;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
I2C1_SCL_L;
I2C1_Delay();
}
uint8_t I2C1_WaitAck(void)
{
I2C1_SCL_L;
I2C1_Delay();
I2C1_SDA_H;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
if(I2C1_SDA)
{
I2C1_SCL_L;
return 0;
}
I2C1_SCL_L;
return 1;
}
void I2C1_SendByte(uint8_t SendByte) //
{
uint8_t i=8;
while(i--)
{
I2C1_SCL_L;
I2C1_Delay();
if(SendByte&0x80)
I2C1_SDA_H;
else
I2C1_SDA_L;
SendByte<<=1;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
}
I2C1_SCL_L;
}
uint8_t I2C1_ReceiveByte(void) //
{
uint8_t i=8;
uint8_t ReceiveByte=0;
I2C1_SDA_H;
while(i--)
{
ReceiveByte<<=1;
I2C1_SCL_L;
I2C1_Delay();
I2C1_SCL_H;
I2C1_Delay();
if(I2C1_SDA)
{
ReceiveByte|=0x01;
}
}
I2C1_SCL_L;
return ReceiveByte;
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
uint8_t I2C1_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
I2C1_SDA;//SDA设置为输入
for(i=0;i<8;i++ )
{
I2C1_SCL_L;
I2C1_Delay();
I2C1_SCL_H;
receive<<=1;
if(I2C1_SDA)receive++;
I2C1_Delay();
}
if (ack)
I2C1_Ack();//发送nACK
else
I2C1_NAck(); //发送ACK
return receive;
}
/***********************************************************************************
*
* MPU6050用到的函数
*
*
*
**************************************************************************************/
/**************************实现函数********************************************
*函数原型: unsigned char I2C_ReadOneByte(unsigned char rI2C_Add,unsigned char addr)
*功 能: 读取指定设备 指定寄存器的一个值
输入 I2C_Addr 目标设备地址
addr 寄存器地址
返回 读出来的值
*******************************************************************************/
unsigned char I2C_ReadOneByte(unsigned char I2C_Addr,unsigned char addr)
{
unsigned char res=0;
I2C1_Start();
I2C1_SendByte(I2C_Addr); //发送写命令
res++;
I2C1_WaitAck();
I2C1_SendByte(addr); res++; //发送地址
I2C1_WaitAck();
//IIC_Stop();//产生一个停止条件
I2C1_Start();
I2C1_SendByte(I2C_Addr+1); res++; //进入接收模式
I2C1_WaitAck();
res=I2C1_Read_Byte(0);
I2C1_Stop();//产生一个停止条件
return res;
}
/**************************实现函数********************************************
*函数原型: u8 IICreadBytes(u8 dev, u8 reg, u8 length, u8 *data)
*功 能: 读取指定设备 指定寄存器的 length个值
输入 dev 目标设备地址
reg 寄存器地址
length 要读的字节数
*data 读出的数据将要存放的指针
返回 读出来的字节数量
*******************************************************************************/
uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data){
uint8_t count = 0;
I2C1_Start();
I2C1_SendByte(dev); //发送写命令
I2C1_WaitAck();
I2C1_SendByte(reg); //发送地址
I2C1_WaitAck();
I2C1_Start();
I2C1_SendByte(dev+1); //进入接收模式
I2C1_WaitAck();
for(count=0;count
if(count!=length-1)data[count]=I2C1_Read_Byte(1); //带ACK的读数据
else data[count]=I2C1_Read_Byte(0); //最后一个字节NACK
}
I2C1_Stop();//产生一个停止条件
return count;
}
/**************************实现函数********************************************
*函数原型: u8 IICwriteBytes(u8 dev, u8 reg, u8 length, u8* data)
*功 能: 将多个字节写入指定设备 指定寄存器
输入 dev 目标设备地址
reg 寄存器地址
length 要写的字节数
*data 将要写的数据的首地址
返回 返回是否成功
*******************************************************************************/
uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data){
uint8_t count = 0;
I2C1_Start();
I2C1_SendByte(dev); //发送写命令
I2C1_WaitAck();
I2C1_SendByte(reg); //发送地址
I2C1_WaitAck();
for(count=0;count
I2C1_SendByte(data[count]);
I2C1_WaitAck();
}
I2C1_Stop();//产生一个停止条件
return 1; //status == 0;
}
/**************************实现函数********************************************
*函数原型: u8 IICreadByte(u8 dev, u8 reg, u8 *data)
*功 能: 读取指定设备 指定寄存器的一个值
输入 dev 目标设备地址
reg 寄存器地址
*data 读出的数据将要存放的地址
返回 1
*******************************************************************************/
uint8_t IICreadByte(uint8_t dev, uint8_t reg, uint8_t *data){
*data=I2C_ReadOneByte(dev, reg);
return 1;
}
/**************************实现函数********************************************
*函数原型: unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data)
*功 能: 写入指定设备 指定寄存器一个字节
输入 dev 目标设备地址
reg 寄存器地址
data 将要写入的字节
返回 1
*******************************************************************************/
unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data){
return IICwriteBytes(dev, reg, 1, &data);
}
/**************************实现函数********************************************
*函数原型: u8 IICwriteBits(u8 dev,u8 reg,u8 bitStart,u8 length,u8 data)
*功 能: 读 修改 写 指定设备 指定寄存器一个字节 中的多个位
输入 dev 目标设备地址
reg 寄存器地址
bitStart 目标字节的起始位
length 位长度
data 存放改变目标字节位的值
返回 成功 为1
失败为0
*******************************************************************************/
uint8_t IICwriteBits(uint8_t dev,uint8_t reg,uint8_t bitStart,uint8_t length,uint8_t data)
{
uint8_t b;
if (IICreadByte(dev, reg, &b) != 0) {
uint8_t mask = (0xFF << (bitStart + 1)) | 0xFF >> ((8 - bitStart) + length - 1);
data <<= (8 - length);
data >>= (7 - bitStart);
b &= mask;
b |= data;
return IICwriteByte(dev, reg, b);
} else {
return 0;
}
}
/**************************实现函数********************************************
*函数原型: u8 IICwriteBit(u8 dev, u8 reg, u8 bitNum, u8 data)
*功 能: 读 修改 写 指定设备 指定寄存器一个字节 中的1个位
输入 dev 目标设备地址
reg 寄存器地址
bitNum 要修改目标字节的bitNum位
data 为0 时,目标位将被清0 否则将被置位
返回 成功 为1
失败为0
*******************************************************************************/
uint8_t IICwriteBit(uint8_t dev, uint8_t reg, uint8_t bitNum, uint8_t data){
uint8_t b;
IICreadByte(dev, reg, &b);
b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
return IICwriteByte(dev, reg, b);
}
//------------------End of File----------------------------
|