/********************************************************** * 函数功能 ---> 向IIC总线发送一个字节数据 * 入口参数 ---> dat:要发送的数据 * 返回数值 ---> ack:返回应答信号 * 功能说明 ---> none **********************************************************/ u8 IIC_Write_Byte(u8 dat) { u8 i; u8 iic_ack=0; //iic应答标志 IIC_SDA_OUT(); //设置成输出 for(i = 0;i < 8;i++) { if(dat & 0x80) IIC_SDA = 1; //判断发送位,先发送高位 else IIC_SDA = 0; IIC_Delay(); IIC_SCL = 1; //为SCL下降做准备 IIC_Delay(); IIC_SCL = 0; //突变,将数据位发送过去 dat<<=1; //数据左移一位 } //字节发送完成,开始接收应答信号 IIC_SDA = 1; //释放数据线 IIC_SDA_IN(); //设置成输入 IIC_Delay(); IIC_SCL = 1; //为SCL下降做准备 IIC_Delay(); iic_ack |= IN_SDA; //读入应答位 IIC_SCL = 0; return iic_ack; //返回应答信号 }
//IIC通信停止信号: SCL为高电平时,SDA由低电平向高电平转变,结束传送数据 void IIC_Stop(){ IIC_SDA = 0; IIC_Delay(); IIC_SCL = 1; IIC_Delay(); IIC_SDA = 1; }
/********************************************************** * 函数功能 ---> 从IIC总线上读取一个字节数据 * 入口参数 ---> none * 返回数值 ---> x:读取到的数据 * 功能说明 ---> none **********************************************************/ u8 IIC_Read_Byte(void) { u8 i; u8 x=0; IIC_SDA = 1; //首先置数据线为高电平 IIC_SDA_IN(); //设置成输入 for(i = 0;i < 8;i++) { x <<= 1; //读入数据,高位在前 IIC_Delay(); IIC_SCL = 1; //突变 IIC_Delay(); if(IN_SDA) x |= 0x01; //收到高电平 IIC_SCL = 0; IIC_Delay(); } //数据接收完成 IIC_SCL = 0; return x; //返回读取到的数据 }
void WM8960_WriteData(Uint8 channel, Uint8 Register, Uint16 Data) { Uint8 HightByte,LowByte; Uint8 I2C_Status; HightByte = Data >> 8; HightByte = HightByte & 0x01; HightByte |= (Register << 1); LowByte = Data; //bit 7 - 0 IIC_Start(channel); IIC_Delay(); if(!(IIC_WriteByte(channel,WM8960_Write_ADD))) { I2C_Status = IIC_WriteByte(channel,HightByte); I2C_Status = IIC_WriteByte(channel,LowByte); IIC_Delay(); IIC_Stop(channel); #if DebugVerbosity > 1 if(I2C_Status == 0) { UART_TxStr("Channel = "); UART_TxUint8(channel); UART_TxStr("Register = "); UART_TxUint8(Register); UART_TxStr(" Value = "); UART_TxUint8(Data>>8); UART_TxUint8(LowByte); UART_TxStr("\n\r"); }
//IIC通信开始信号: SCL为高电平时,SDA由高电平向低电平转变,开始传送数据。 void IIC_Start(){ IIC_SDA = 1; IIC_SCL = 1; IIC_Delay(); IIC_SDA = 0; IIC_Delay(); IIC_SCL = 0; }
void IIC_NAck(void) //Send No ACK (High) { SCL = 0; IIC_Delay(); SDA = 1; IIC_Delay(); SCL = 1; IIC_Delay(); SCL = 0; IIC_Delay(); }
void IIC_Ack(void) //Send ACK (LOW) { SCL = 0; IIC_Delay(); SDA = 0; IIC_Delay(); SCL = 1; IIC_Delay(); SCL = 0; IIC_Delay(); }
void IIC_Stop(void) //STOP the IIC, SDA Low-to-high when SCL is high { SCL = 0; IIC_Delay(); SDA = 0; IIC_Delay(); SCL = 1; IIC_Delay(); SDA = 1; IIC_Delay(); }
void IIC_Start(void) //start the IIC, SDA High-to-low when SCL is high { SDA = 1; IIC_Delay(); SCL = 1; IIC_Delay(); SDA = 0; IIC_Delay(); SCL = 0; IIC_Delay(); }
/********************************************************** * 函数功能 ---> IIC停止 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> SCL高电平期间,SDA由低电平突变到高电平时停止总线 **********************************************************/ void IIC_Stop(void) { IIC_SDA_OUT(); //设置成输出 IIC_SDA = 0; //为SDA上升做准备 IIC_Delay(); IIC_SCL = 1; //在SCL高电平时,SDA为上升沿时候总线停止 IIC_Delay(); IIC_SDA = 1; //突变,总线停止 IIC_Delay(); }
//向IIC总线上写一个字节 void IIC_Write_Byte(unsigned char dat){ unsigned char i; IIC_SCL = 0; //只有在时钟线低时才能改变数据线电平状态 for(i=0;i<8;i++){ IIC_SDA = (bit)(dat&0x80); //IIC通信高位再前,低位再后。写入高位,(bit)表示强制转换成位 IIC_SCL = 1; //拉高让从机读 IIC_Delay(); IIC_SCL = 0; //拉低为下位数据线准备 IIC_Delay(); dat <<= 1; //数据左移一位,把次高位放在最高位,为写入次高位做准备 } }
/********************************************************** * 函数功能 ---> IIC启动 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> SCL高电平期间,SDA由高电平突变到低电平时启动总线 **********************************************************/ void IIC_Start(void) { IIC_SDA_OUT(); //设置成输出 IIC_SDA = 1; //为SDA下降启动做准备 IIC_SCL = 1; //在SCL高电平时,SDA为下降沿时候总线启动 IIC_Delay(); IIC_SDA = 0; //突变,总线启动 IIC_Delay(); IIC_SCL = 0; IIC_Delay(); }
//IIC通信应答信号: 接收数据的IC在接收到8bit数据后,会拉低数据线,表示数据接收成功 bit IIC_ACK(){ bit ack;//定义一个位变量,来暂存应答状态。 IIC_SCL = 0; //只有在时钟线低时才能改变数据线电平状态 IIC_Delay(); IIC_SDA = 1; //释放数据总线,准备接收应答信号。 IIC_Delay(); IIC_SCL = 1; //拉高时钟线。 IIC_Delay(); ack = IIC_SDA; //读取状态 IIC_SCL = 0; return ack; //返回应答信号的状态,0表示应答,数据接收成功。反之失败 }
/********************************************************** * 函数功能 ---> 主机向从机发送应答信号 * 入口参数 ---> a:应答信号 * 0:应答信号 * 1:非应答信号 * 返回数值 ---> none * 功能说明 ---> none **********************************************************/ void IIC_Ack(u8 a) { IIC_SDA_OUT(); //设置成输出 if(a) IIC_SDA = 1; //放上应答信号电平 else IIC_SDA = 0; IIC_Delay(); IIC_SCL = 1; //为SCL下降做准备 IIC_Delay(); IIC_SCL = 0; //突变,将应答信号发送过去 IIC_Delay(); }
u8 IIC_ReadBit(void) { u8 i,Temp=0; IIC_SDA_In(); for(i=0;i<8;i++) { IIC_SCL_L(); IIC_Delay(1); IIC_SCL_H(); Temp<<=1; if(IIC_SDA_Read()) Temp++; IIC_Delay(1); } IIC_SCL_L(); return Temp; }
void IIC_Send_Byte(u8 dat) //write a byte to IIC { u8 i; i = 8; SCL = 0; do { if(dat & 0x80) SDA = 1; else SDA = 0; dat <<= 1; IIC_Delay(); SCL = 1; IIC_Delay(); SCL = 0; IIC_Delay(); } while(--i); }
u8 IIC_Wait_Ack(void) //Check ACK, If F0=0, then right, if F0=1, then error { u8 err = 0; SDA = 1; IIC_Delay(); SCL = 1; IIC_Delay(); while(SDA) { err++; if (err > 200) { IIC_Stop(); return 0; } } SCL = 0; IIC_Delay(); return 1; }
/* void IIC_Start(void) { IIC_SDA_Out(); IIC_SDA_H(); IIC_SCL_H(); IIC_Delay(1); IIC_SDA_L(); IIC_Delay(1); IIC_SCL_L(); } void IIC_Stop(void) { IIC_SDA_Out(); IIC_SCL_L(); IIC_SDA_L(); IIC_Delay(1); IIC_SCL_H(); IIC_SDA_H(); IIC_Delay(1); } void IIC_Ack(u8 re) { IIC_SDA_Out(); if(re) IIC_SDA_H(); else IIC_SDA_L(); IIC_SCL_H(); IIC_Delay(1); IIC_SCL_L(); IIC_Delay(1); } */ int IIC_WaitAck(void) { u16 Out_Time=1000; IIC_SDA_H(); IIC_SDA_In(); IIC_Delay(1); IIC_SCL_H(); IIC_Delay(1); while(IIC_SDA_Read()) { if(--Out_Time) { IIC_Stop(); printf("error 2A\r\n"); return 0xff; } } IIC_SCL_L(); return 0; }
void IIC_WriteBit(u8 Temp) { u8 i; IIC_SDA_Out(); IIC_SCL_L(); for(i=0;i<8;i++) { if(Temp&0x80) { IIC_SDA_H(); } else { IIC_SDA_L(); } Temp<<=1; IIC_Delay(1); IIC_SCL_H(); IIC_Delay(1); IIC_SCL_L(); } }
u8 IIC_Read_Byte(unsigned char ack) //read A byte from IIC { u8 i,dat; i = 8; SDA = 1; SCL = 0; do { SCL = 1; IIC_Delay(); dat <<= 1; if(SDA) dat++; SCL = 0; IIC_Delay(); } while(--i); if (ack == 0) IIC_NAck();//·¢ËÍnACK else if (ack == 1) IIC_Ack(); //·¢ËÍACK return(dat); }
//从IIC总线上读取一个字节 unsigned char IIC_Read_Byte(){ unsigned char i; unsigned char dat = 0x00;//定义一个存取变量。 IIC_SCL = 0; //只有在时钟线低时才能改变数据线电平状态 for(i=0;i<8;i++){ IIC_SCL = 1; IIC_Delay(); dat <<= 1;//数据左移一位,把次高位放在最高位,为写入次高位做准备 if(IIC_SDA) //如果为高就写入到数据,为零跳过 dat |= 0x01; //数据是从高到低写入,所以右移或上。 IIC_SCL = 0; DelayIIC(); } return dat;//返回读取的一个字节数据。 }