/*************笔记****************
1、CubeMX 定义任意两个引脚,作为通讯脚,并对引脚作出如下配置:
GPlO output level --High
GPIO mode --Output open drai
GPIO Pull-up/Pull-down --No pull-up and no pull-down
Maximum output speed --LOW
User label --IIC_SCL/IIC_SDA
IIC_SCL--PB6 IIC_SDA--PB7
---------------------------------------------------------
***********************************/
#include "hal_iic.h"
/**********************************************************************/
// 功能描述:用于IIC通讯时延时,以满足IIC对时序的要求(内部使用)
// 输入参数:cnt 延时记数器 (定义成volatile防止被优化掉)
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
//#pragma optimize= none
void IIC_Delay(volatile uint32_t cnt)
{
while(cnt--);
}
/**********************************************************************/
// 功能描述: IIC使能初始化
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
void IIC_Init(const IIC_PIN *I)
{
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
}
/**********************************************************************/
// 功能描述: IIC通讯开始
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:胡安勤
// 修改记录:
/**********************************************************************/
void IIC_Start (const IIC_PIN *I)//
{
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 0); //SDA = 0
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 0); //SCL = 0
IIC_Delay(I->DelayTick);
}
/**********************************************************************/
// 功能描述: IIC通讯结束
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
void IIC_Stop (const IIC_PIN *I)
{
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 0); //SDA = 0
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
IIC_Delay(I->DelayTick);
}
/**********************************************************************/
// 功能描述: IIC从设备应答
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 返 回 值:0: 设备应答正常 1: 设备无应答
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
IIC_STATUS IIC_Wait_ACK(const IIC_PIN *I)
{
uint8_t s1;
uint8_t i = 0;
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
s1 = GPIO_READ_PIN(I->SDA_PORT, I->SDA_PIN);
while (s1 && i++ < 100) //判断是否应答 0应答,1无答
{
s1 = GPIO_READ_PIN(I->SDA_PORT, I->SDA_PIN);
}
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 0); //SCL = 0
IIC_Delay(I->DelayTick);
if(s1)
{
return(IIC_WAIT_ACK_ERR);
}
else
{
return(IIC_OK);
}
}
/**********************************************************************/
// 功能描述: 主设备应答
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
void IIC_ACK(const IIC_PIN *I)
{
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 0); //SDA = 0
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 0); //SCL = 0
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
}
/**********************************************************************/
// 功能描述: 主设备非应答
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
void IIC_NACK(const IIC_PIN *I)
{
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 0); //SCL = 0
IIC_Delay(I->DelayTick);
}
/**********************************************************************/
// 功能描述: 发送一个字节
// 输入参数:I:结构体,定义IIC使用的PIN管脚 data: 待发送字节
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
void IIC_WriteByte(const IIC_PIN *I, uint8_t data)
{
uint16_t i;
for(i = 0; i < 8; i++)
{
if((data & 0x80) == 0x80)
{
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
}
else
{
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 0); //SDA = 0
}
data = data << 1;
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 0); //SCL = 0
//IIC_Delay(I->DelayTick);
}
IIC_Delay(I->DelayTick);
GPIO_WRITE_PIN(I->SDA_PORT, I->SDA_PIN, 1); //SDA = 1
}
/**********************************************************************/
// 功能描述: 从从设备接收一个字节
// 输入参数:I:结构体,定义IIC使用的PIN管脚
// 输出参数:data:读取到的字节
// 返 回 值:无
// 编写时间:2014.11.21
// 作 者:
// 修改记录:
/**********************************************************************/
void IIC_ReadByte(const IIC_PIN *I, uint8_t *data)
{
uint8_t tmp = 0;
uint8_t i;
IIC_Delay(I->DelayTick);
for(i = 0; i < 8; i++)
{
tmp = tmp << 1;
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 1); //SCL = 1
IIC_Delay(I->DelayTick);
if (GPIO_READ_PIN(I->SDA_PORT, I->SDA_PIN)) //读数据脚
{
tmp = tmp | 0x01;
}
else
{
tmp = tmp & 0xfe;
}
GPIO_WRITE_PIN(I->SCL_PORT, I->SCL_PIN, 0); //SCL = 0
IIC_Delay(I->DelayTick);
}
*data = tmp;
}
#ifndef __IIC_Configuration_HEAD_
#define __IIC_Configuration_HEAD_
#include "main.h"
#define GPIO_WRITE_PIN(PORT,PIN,VALUE) HAL_GPIO_WritePin(PORT,PIN,(VALUE)?GPIO_PIN_SET:GPIO_PIN_RESET)
#define GPIO_READ_PIN(PORT,PIN) HAL_GPIO_ReadPin(PORT,PIN)
typedef enum {
IIC_OK = 0x00, //IIC工作正常
IIC_WAIT_ACK_ERR = 0x01, //slave设备返回ACK错误
IIC_WRITE_ERR = 0x02, //向slave设备写入错误
IIC_READ_ERR = 0x04 //从slave设备读取错误
} IIC_STATUS;
typedef struct
{
GPIO_TypeDef *SCL_PORT; //定义IIC时钟使用的端口
uint16_t SCL_PIN; //定义IIC时钟使用的PIN脚
GPIO_TypeDef *SDA_PORT; //定义IIC数据使用的端口
uint16_t SDA_PIN; //定义IIC数据使用的PIN脚
uint32_t DelayTick; //定义延时,以适应不同器件对速率的不同要求,具体值要在调试中确定
uint8_t ADDR; //器件地址
}IIC_PIN;
void IIC_Init(const IIC_PIN *I);
void IIC_Start (const IIC_PIN *I);
void IIC_Stop (const IIC_PIN *I);
IIC_STATUS IIC_Wait_ACK(const IIC_PIN *I);
void IIC_WriteByte(const IIC_PIN *I,uint8_t data);
void IIC_ReadByte(const IIC_PIN *I,uint8_t *data);
void IIC_ACK(const IIC_PIN *I);
void IIC_NACK(const IIC_PIN *I);
#endif