STM32通用模拟IIC驱动

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

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值