iic_drive.c
#include "iic_drive.h"
//控制I2C速度的延时
void CT_Delay(void)
{
/*工作条件:CPU主频72MHz
循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
*/
int cnt = 10;
while(cnt--);
}
//IIC接口初始化
void CT_IIC_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
GPIO_Initure.Pin=IIC_SDA_PIN|IIC_SCL_PIN;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(IIC_PIN_PORT,&GPIO_Initure);
}
//SDA设置为输出
void CT_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = IIC_SDA_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(IIC_PIN_PORT, &GPIO_InitStruct);
}
//SDA设置为输入
void CT_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = IIC_SDA_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(IIC_PIN_PORT, &GPIO_InitStruct);
}
//产生IIC起始信号
void CT_IIC_Start(void)
{
CT_SDA_OUT(); //sda线输出
CT_IIC_SDA(1);
CT_IIC_SCL(1);
CT_Delay();
CT_IIC_SDA(0); //START:when CLK is high,DATA change form high to low
CT_Delay();
CT_IIC_SCL(0); //钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void CT_IIC_Stop(void)
{
CT_SDA_OUT(); //sda线输出
CT_IIC_SCL(0);
CT_IIC_SDA(0);
CT_Delay();
CT_IIC_SCL(1);
CT_Delay();
CT_IIC_SDA(1); //发送I2C总线结束信号
CT_Delay();
}
//等待应答信号到来,返回值:1-接收应答失败;0-接收应答成功
unsigned char CT_IIC_Wait_Ack(void)
{
unsigned char ucErrTime=0;
CT_IIC_SDA(1);
CT_SDA_IN(); //SDA设置为输入
CT_IIC_SCL(1);
CT_Delay();
while(CT_READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
CT_IIC_Stop();
return 1;
}
CT_Delay();
}
CT_IIC_SCL(0); //时钟输出0
return 0;
}
//产生ACK应答
void CT_IIC_Ack(void)
{
CT_IIC_SCL(0);
CT_SDA_OUT();
CT_Delay();
CT_IIC_SDA(0);
CT_Delay();
CT_IIC_SCL(1);
CT_Delay();
CT_IIC_SCL(0);
}
//不产生ACK应答
void CT_IIC_NAck(void)
{
CT_IIC_SCL(0);
CT_SDA_OUT();
CT_Delay();
CT_IIC_SDA(1);
CT_Delay();
CT_IIC_SCL(1);
CT_Delay();
CT_IIC_SCL(0);
}
//IIC发送一个字节,返回从机有无应答,1-有应答;0-无应答
void CT_IIC_Send_Byte(unsigned char txd)
{
CT_SDA_OUT();
CT_IIC_SCL(0); //拉低时钟开始数据传输
CT_Delay();
for(unsigned char t=0;t<8;t++)
{
CT_IIC_SDA((txd&0x80)>>7);
txd<<=1;
CT_IIC_SCL(1);
CT_Delay();
CT_IIC_SCL(0);
CT_Delay();
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
unsigned char CT_IIC_Read_Byte(unsigned char ack)
{
unsigned char receive=0;
CT_SDA_IN(); //SDA设置为输入
CT_Delay();
for(unsigned char i=0;i<8;i++)
{
CT_IIC_SCL(0);
CT_Delay();
CT_IIC_SCL(1);
CT_Delay();
receive<<=1;
if(CT_READ_SDA)
{
receive++;
}
}
if(!ack)
{
CT_IIC_NAck(); //发送nACK
}
else
{
CT_IIC_Ack(); //发送ACK
}
return receive;
}
iic_drive.h
#ifndef __MYCT_IIC_H
#define __MYCT_IIC_H
#include "gpio.h"
#define IIC_PIN_PORT GPIOH
#define IIC_SDA_PIN GPIO_PIN_6
#define IIC_SCL_PIN GPIO_PIN_7
//IO操作函数
#define CT_IIC_SCL(n) (n?HAL_GPIO_WritePin(IIC_PIN_PORT,IIC_SCL_PIN,GPIO_PIN_SET):HAL_GPIO_WritePin(IIC_PIN_PORT,IIC_SCL_PIN,GPIO_PIN_RESET))//SCL
#define CT_IIC_SDA(n) (n?HAL_GPIO_WritePin(IIC_PIN_PORT,IIC_SDA_PIN,GPIO_PIN_SET):HAL_GPIO_WritePin(IIC_PIN_PORT,IIC_SDA_PIN,GPIO_PIN_RESET))//SDA
#define CT_READ_SDA HAL_GPIO_ReadPin(IIC_PIN_PORT,IIC_SDA_PIN)
//IIC所有操作函数
void CT_IIC_Init(void); //初始化IIC的IO口
void CT_IIC_Start(void); //发送IIC开始信号
void CT_IIC_Stop(void); //发送IIC停止信号
void CT_IIC_Send_Byte(unsigned char txd); //IIC发送一个字节
unsigned char CT_IIC_Read_Byte(unsigned char ack); //IIC读取一个字节
unsigned char CT_IIC_Wait_Ack(void); //IIC等待ACK信号
void CT_IIC_Ack(void); //IIC发送ACK信号
void CT_IIC_NAck(void); //IIC不发送ACK信号
#endif