Files
Hero-C-Board-Legacy/云台/云台-old/System/MyI2C.c

441 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "MyI2C.h"
/*
*函数简介:软件I2C专用us延时
*参数说明:延时时长,单位1/21us
*返回类型:无
*备注:参数范围:0~4294967295
*/
void MyI2C_Delay_us(uint32_t us)
{
uint32_t temp;
SysTick->LOAD=us; //时间加载我们要延时n倍的us, 1us是一个fac_ua周期所以总共要延时的周期值为二者相乘最后送到Load中。
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开启使能位 开始倒数
do temp=SysTick->CTRL;
while((temp&0x01) && !(temp&(1<<16))); //用来判断 systick 定时器是否还处于开启状态然后在等待时间到达也就是数到0的时候,此时第十六位设置为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器使能位
SysTick->VAL=0x00; //清空计数器
}
/*
*函数简介:软件I2C写SCL电平
*参数说明:软件I2C配置结构体
*参数说明:高低电平,0-低电平 1-高电平
*返回类型:无
*备注:使用前需要先定义结构体并初始化
*备注:由于I2C速度较慢,在更改电平之后需要加入延时
*/
void MyI2C_SCL(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t x)
{
GPIO_WriteBit(MyI2C_InitStructure->MyI2C_SCL_GPIOx,MyI2C_InitStructure->MyI2C_SCL_Pin,(BitAction)(x));
MyI2C_Delay_us(1);//延时
}
/*
*函数简介:软件I2C写SDA电平
*参数说明:软件I2C配置结构体
*参数说明:高低电平,0-低电平 1-高电平
*返回类型:
*备注:使用前需要先定义结构体并初始化
*备注:由于I2C速度较慢,在更改电平之后需要加入延时
*/
void MyI2C_SDA(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t x)
{
GPIO_WriteBit(MyI2C_InitStructure->MyI2C_SDA_GPIOx,MyI2C_InitStructure->MyI2C_SDA_Pin,(BitAction)(x));
MyI2C_Delay_us(1);//延时
}
/*
*函数简介:软件I2C读SDA电平
*参数说明:软件I2C配置结构体
*返回类型:高低电平,0-低电平 1-高电平
*备注:使用前需要先定义结构体并初始化
*备注:由于I2C速度较慢,在电平更改之后需要加入延时,读取时也可以不加
*/
uint8_t MyI2C_Read_SDA(MyI2C_InitTypedef *MyI2C_InitStructure)
{
MyI2C_Delay_us(1);//延时
uint8_t SDA_Status=GPIO_ReadInputDataBit(MyI2C_InitStructure->MyI2C_SDA_GPIOx,MyI2C_InitStructure->MyI2C_SDA_Pin);
return SDA_Status;
}
/*
*函数简介:软件I2C初始化
*参数说明:软件I2C配置结构体
*返回类型:无
*备注:使用前需要先定义结构体并初始化
*/
void MyI2C_Init(MyI2C_InitTypedef *MyI2C_InitStructure)
{
RCC_AHB1PeriphClockCmd(MyI2C_InitStructure->MyI2C_SCL_RCC,ENABLE);//开启SCL时钟
RCC_AHB1PeriphClockCmd(MyI2C_InitStructure->MyI2C_SDA_RCC,ENABLE);//开启SDA时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=MyI2C_InitStructure->MyI2C_SCL_Pin;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(MyI2C_InitStructure->MyI2C_SCL_GPIOx,&GPIO_InitStructure);//配置SCL
GPIO_InitStructure.GPIO_Pin=MyI2C_InitStructure->MyI2C_SDA_Pin;
GPIO_Init(MyI2C_InitStructure->MyI2C_SDA_GPIOx,&GPIO_InitStructure);//配置SDA
MyI2C_SCL(MyI2C_InitStructure,1);//初始化SCL
MyI2C_SDA(MyI2C_InitStructure,1);//初始化SDA
}
/*
*函数简介:软件I2C起始
*参数说明:软件I2C配置结构体
*返回类型:无
*I2C协议:
* SCL ~~~~/---\___
* SDA ~~/---\_____
*/
void MyI2C_Start(MyI2C_InitTypedef *MyI2C_InitStructure)
{
MyI2C_SDA(MyI2C_InitStructure,1);
MyI2C_SCL(MyI2C_InitStructure,1);//复位SCL和SDA
MyI2C_SDA(MyI2C_InitStructure,0);//起始
MyI2C_SCL(MyI2C_InitStructure,0);//准备接收数据
}
/*
*函数简介:软件I2C终止
*参数说明:软件I2C配置结构体
*返回类型:无
*I2C协议:
* SCL ____/-----
* SDA ~~\___/---
*/
void MyI2C_Stop(MyI2C_InitTypedef *MyI2C_InitStructure)
{
MyI2C_SDA(MyI2C_InitStructure,0);
MyI2C_SCL(MyI2C_InitStructure,1);//准备接收停止信号
MyI2C_SDA(MyI2C_InitStructure,1);//终止
}
/*
*函数简介:软件I2C产生应答
*参数说明:软件I2C配置结构体
*参数说明:是否应答,0-NAck非应答 1-Ack应答
*返回类型:无
*I2C协议:
* Ack:
* SCL____/-\___
* SDA~~\___/---
* NAck:
* SCL____/-\___
* SDA~~/-------
*/
void MyI2C_SendAck(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t AckBit)
{
MyI2C_SDA(MyI2C_InitStructure,!AckBit);//发送应答情况
MyI2C_SCL(MyI2C_InitStructure,1);//产生时钟
MyI2C_SCL(MyI2C_InitStructure,0);
MyI2C_SDA(MyI2C_InitStructure,1);//释放总线
}
/*
*函数简介:软件I2C接收应答
*参数说明:软件I2C配置结构体
*返回类型:是否应答,0-NAck非应答 1-Ack应答
*I2C协议:
* SCL ____/-\___
* SDA ~~/-|==|~~
* ( )从机
*/
uint8_t MyI2C_ReceiveAck(MyI2C_InitTypedef *MyI2C_InitStructure)
{
uint8_t AckBit;//应答标志位
MyI2C_SDA(MyI2C_InitStructure,1);//释放SDA总线
MyI2C_SCL(MyI2C_InitStructure,1);//提示从机发送Ack
AckBit=!MyI2C_Read_SDA(MyI2C_InitStructure);//接收应答
MyI2C_SCL(MyI2C_InitStructure,0);//置SCL为0,准备下一轮发送
return AckBit;//返回应答情况
}
/*
*函数简介:软件I2C发送一个8bits数据
*参数说明:软件I2C配置结构体
*参数说明:8bits发送数据
*返回类型:无
*I2C协议:
* SCL ____/-\___/-\___/-\___/-\___/-\___/-\___/-\___/-\___
* SDA ~~x=====x=====x=====x=====x=====x=====x=====x=====~~
*/
void MyI2C_Send8bits(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Byte)
{
for(uint8_t i=0;i<8;i++)
{
MyI2C_SDA(MyI2C_InitStructure,Byte&(0x80>>i));//发送数据每一位,高位先行
MyI2C_SCL(MyI2C_InitStructure,1);//产生时钟
MyI2C_SCL(MyI2C_InitStructure,0);
}
MyI2C_SDA(MyI2C_InitStructure,1);//释放SDA总线
}
/*
*函数简介:软件I2C读取一个8bits数据
*参数说明:软件I2C配置结构体
*返回类型:8bits接收数据
*I2C协议:
* SCL ____/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\___
* SDA ~~/-|==============================|~~
* ( )从机
*/
uint8_t MyI2C_Receive8bits(MyI2C_InitTypedef *MyI2C_InitStructure)
{
uint8_t Byte=0x00;
MyI2C_SDA(MyI2C_InitStructure,1);//释放SDA总线
for(uint8_t i=0;i<8;i++)//读取数据每一位,高位先行
{
MyI2C_SCL(MyI2C_InitStructure,1);//产生时钟
if(MyI2C_Read_SDA(MyI2C_InitStructure)){Byte|=(0x80>>i);}//读取SDA
MyI2C_SCL(MyI2C_InitStructure,0);
}
return Byte;
}
/*
*函数简介:软件I2C发送一个字节数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits发送数据
*返回类型:无
*备注:无
*/
void MyI2C_SendByte(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t Byte)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,Address<<1);//发送设备地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,Byte);//发送数据
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C发送数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:发送数据数组
*参数说明:发送数据数组长度
*返回类型:无
*备注:无
*/
void MyI2C_SendData(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t *Data,uint16_t Length)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,Address<<1);//发送设备地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
for(uint16_t i=0;i<Length;i++)
{
MyI2C_Send8bits(MyI2C_InitStructure,Data[i]);//发送数据
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
}
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C写寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits寄存器地址
*参数说明:8bits数据
*返回类型:无
*备注:无
*/
void MyI2C_WriteRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegAddress,uint8_t Data)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送从机地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,RegAddress);//发送寄存器地址
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,Data);//发送数据
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C接收一个字节数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*返回类型:8bits接收数据
*备注:无
*/
uint8_t MyI2C_ReceiveByte(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address)
{
uint8_t Byte=0;
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,(Address<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
Byte=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
return Byte;
}
/*
*函数简介:软件I2C接收数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:接收数据数组
*参数说明:接收数据数组长度
*返回类型:8bits接收数据
*备注:无
*/
void MyI2C_ReceiveData(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t *Data,uint16_t Length)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,(Address<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
for(uint16_t i=0;i<Length-1;i++)
{
Data[i]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,1);//发送Ack
}
Data[Length-1]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收最后一个数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C读寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits寄存器地址
*返回类型:8bits数据
*备注:无
*/
uint8_t MyI2C_ReadRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegAddress)
{
uint8_t Byte=0;
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送从机地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,RegAddress);//发送寄存器地址
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Start(MyI2C_InitStructure);//重复起始
MyI2C_Send8bits(MyI2C_InitStructure,(SlaveAddress<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
Byte=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
return Byte;
}
/*
*函数简介:软件I2C连续读寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits寄存器首地址
*参数说明:接收数据数组
*参数说明:接收数据数组长度
*返回类型:无
*备注:无
*/
void MyI2C_ContinuousReadRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegStartAddress,uint8_t *ReceiveData,uint16_t Length)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送从机地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,RegStartAddress);//发送寄存器地址
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Start(MyI2C_InitStructure);//重复起始
MyI2C_Send8bits(MyI2C_InitStructure,(SlaveAddress<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
for(uint16_t i=0;i<Length-1;i++)
{
ReceiveData[i]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,1);//发送Ack
}
ReceiveData[Length-1]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收最后一个数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C检测设备状态
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*返回类型:工作状态,0-设备不存在或异常工作 1-设备正常工作
*备注:无
*/
uint8_t MyI2C_CheckDevice(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address)
{
uint8_t WorkStatus;//工作标志位
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,Address<<1);//发送设备地址(写)
WorkStatus=MyI2C_ReceiveAck(MyI2C_InitStructure);//检测Ack应答
MyI2C_Stop(MyI2C_InitStructure);//终止
return WorkStatus;
}
/*
*函数简介:软件I2C查询Who Am I寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits Who Am I寄存器地址
*返回类型:Who Am I寄存器的值,0-设备不存在或异常工作 其他-返回寄存器值
*备注:无
*/
uint8_t MyI2C_CheckWhoAmI(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t WhoAmIAddress)
{
uint8_t WhoAmI;
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送设备地址(写)
if(MyI2C_ReceiveAck(MyI2C_InitStructure)==0)return 0;//检测Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,WhoAmIAddress);//发送寄存器地址
if(MyI2C_ReceiveAck(MyI2C_InitStructure)==0)return 0;//检测Ack应答
MyI2C_Start(MyI2C_InitStructure);//重复起始
MyI2C_Send8bits(MyI2C_InitStructure,(SlaveAddress<<1) | 0x01);//发送设备地址(读)
if(MyI2C_ReceiveAck(MyI2C_InitStructure)==0)return 0;//检测Ack应答
WhoAmI=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
return WhoAmI;
}