159 lines
3.1 KiB
C
159 lines
3.1 KiB
C
/*
|
||
* iic.c
|
||
*
|
||
* Created on: Oct 24, 2021
|
||
* Author: wuwenfeng
|
||
*/
|
||
|
||
#include "iic.h"
|
||
#include "gpio.h"
|
||
#define iic_sda(x) HAL_GPIO_WritePin(iic_sda_GPIO_Port, iic_sda_Pin, x)
|
||
#define iic_scl(x) HAL_GPIO_WritePin(iic_scl_GPIO_Port, iic_scl_Pin, x)
|
||
#define read_iic_sda HAL_GPIO_ReadPin(iic_sda_GPIO_Port, iic_sda_Pin)
|
||
|
||
#define IIC_SDA_SET iic_sda(1)
|
||
#define IIC_SCL_SET iic_scl(1)
|
||
#define IIC_SDA_CLR iic_sda(0)
|
||
#define IIC_SCL_CLR iic_scl(0)
|
||
#define SDA_OUT() change_io_function(iic_sda_GPIO_Port, iic_sda_Pin,0)
|
||
#define SDA_IN() change_io_function(iic_sda_GPIO_Port, iic_sda_Pin,1)
|
||
#define READ_SDA read_iic_sda
|
||
|
||
//产生IIC起始信号
|
||
void IIC_Start(void)
|
||
{
|
||
SDA_OUT(); //sda线输出
|
||
IIC_SDA_SET;
|
||
IIC_SCL_SET;
|
||
IIC_SDA_CLR;//START:when CLK is high,DATA change form high to low
|
||
IIC_SCL_CLR;//钳住I2C总线,准备发送或接收数据
|
||
}
|
||
//产生IIC停止信号
|
||
void IIC_Stop(void)
|
||
{
|
||
SDA_OUT();//sda线输出
|
||
IIC_SCL_CLR;
|
||
IIC_SDA_CLR;//STOP:when CLK is high DATA change form low to high
|
||
IIC_SCL_SET;
|
||
IIC_SDA_SET;//发送I2C总线结束信号
|
||
}
|
||
//等待应答信号到来
|
||
//返回值:1,接收应答失败
|
||
// 0,接收应答成功
|
||
uint8_t IIC_Wait_Ack(void)
|
||
{
|
||
uint8_t ucErrTime=0;
|
||
SDA_IN(); //SDA设置为输入
|
||
IIC_SDA_SET;
|
||
IIC_SCL_SET;
|
||
while(READ_SDA)
|
||
{
|
||
ucErrTime++;
|
||
if(ucErrTime>250)
|
||
{
|
||
IIC_Stop();
|
||
return 1;
|
||
}
|
||
}
|
||
IIC_SCL_CLR;//时钟输出0
|
||
return 0;
|
||
}
|
||
//产生ACK应答
|
||
void IIC_Ack(void)
|
||
{
|
||
IIC_SCL_CLR;
|
||
SDA_OUT();
|
||
IIC_SDA_CLR;
|
||
IIC_SCL_SET;
|
||
IIC_SCL_CLR;
|
||
}
|
||
//不产生ACK应答
|
||
void IIC_NAck(void)
|
||
{
|
||
IIC_SCL_CLR;
|
||
SDA_OUT();
|
||
IIC_SDA_SET;
|
||
IIC_SCL_SET;
|
||
IIC_SCL_CLR;
|
||
}
|
||
//IIC发送一个字节
|
||
//返回从机有无应答
|
||
//1,有应答
|
||
//0,无应答
|
||
void IIC_Send_Byte(uint8_t txd)
|
||
{
|
||
uint8_t t;
|
||
SDA_OUT();
|
||
IIC_SCL_CLR;//拉低时钟开始数据传输
|
||
for(t=0;t<8;t++)
|
||
{
|
||
//IIC_SDA=(txd&0x80)>>7;
|
||
if((txd&0x80)>>7)
|
||
IIC_SDA_SET;
|
||
else
|
||
IIC_SDA_CLR;
|
||
txd<<=1;
|
||
|
||
IIC_SCL_SET;
|
||
|
||
IIC_SCL_CLR;
|
||
|
||
}
|
||
}
|
||
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
|
||
uint8_t IIC_Read_Byte(unsigned char ack)
|
||
{
|
||
unsigned char i,receive=0;
|
||
SDA_IN();//SDA设置为输入
|
||
for(i=0;i<8;i++ )
|
||
{
|
||
IIC_SCL_CLR;
|
||
|
||
IIC_SCL_SET;
|
||
receive<<=1;
|
||
if(READ_SDA)receive++;
|
||
|
||
}
|
||
if (!ack)
|
||
IIC_NAck();//发送nACK
|
||
else
|
||
IIC_Ack(); //发送ACK
|
||
return receive;
|
||
}
|
||
|
||
void IIC_SAND_DATE(unsigned char DEVICE_ADD,unsigned char IN_DEVICE_ADD,char *DATAS,uint16_t LONG)
|
||
{
|
||
IIC_Start();
|
||
IIC_Send_Byte(DEVICE_ADD);
|
||
if(IIC_Wait_Ack()){return;}
|
||
IIC_Send_Byte(IN_DEVICE_ADD);
|
||
if(IIC_Wait_Ack()){return;}
|
||
for(int a=0;a<LONG;a++)
|
||
{
|
||
IIC_Send_Byte(*DATAS);
|
||
DATAS++;
|
||
|
||
}
|
||
if(IIC_Wait_Ack()){return;}
|
||
IIC_Stop();
|
||
}
|
||
|
||
void IIC_READ_DATE(unsigned char DEVICE_ADD,unsigned char IN_DEVICE_ADD,char *DATAS,uint16_t LONG)
|
||
{
|
||
IIC_Start();
|
||
IIC_Send_Byte(DEVICE_ADD);
|
||
if(IIC_Wait_Ack()){return;}
|
||
IIC_Send_Byte(IN_DEVICE_ADD);
|
||
if(IIC_Wait_Ack()){return;}
|
||
IIC_Start();
|
||
IIC_Send_Byte(DEVICE_ADD+1);
|
||
if(IIC_Wait_Ack()){return;}
|
||
for(int a=0;a<LONG;a++)
|
||
{
|
||
*DATAS=IIC_Read_Byte(0);
|
||
DATAS++;
|
||
}
|
||
if(IIC_Wait_Ack()){return;}
|
||
IIC_Stop();
|
||
}
|