iic:#include <iom16v.h>
#include <macros.h>
#define uint unsigned int
#define uchar unsigned char
#define SLA_W 0xa0 //从机地址,主机写操作
#define SLA_R 0xa1 //从机地址,主机读操作
#define Baud_set 100 //TWI波特率设置
#define P_value 0x03 //预分频值
#define ST_FAIL 0 //出错状态
#define ST_START 1 //START状态检查
#define ST_SLAW 2 //SLAW状态检查
#define ST_WADDR 3 //ADDR状态检查
#define ST_RESTART 4 //RESTART状态检查
#define ST_SLAR 5 //SLAR状态检查
#define ST_RDATA 6 //读取数据状态检查,循环n字节
#define ST_WDATA 7 //写数据状态检查,循环n字节
#define FAIL_MAX 20 //重试次数最大值
/********主机发送状态码********/
#define TW_START 0x08 //START已发送
#define TW_REP_START 0x10 //重复START已发送
#define TW_MT_SLA_ACK 0x18 //SLA+W 已发送收到ACK
#define TW_MT_SLA_NACK 0x20 //SLA+W 已发送接收到NOT ACK
#define TW_MT_DATA_ACK 0x28 //数据已发送接收到ACK
#define TW_MT_DATA_NACK 0x30 //数据已发送接收到NOT ACK
#define TW_MT_ARB_LOST 0x38 //SLA+W 或数据的仲裁失败
/********主机接收状态码********/
#define TW_START 0x08 //START已发送
#define TW_REP_START 0x10 //重复START已发送
#define TW_MR_ARB_LOST 0x38 //SLA+R 或NOT ACK 的仲裁失败
#define TW_MR_SLA_ACK 0x40 //SLA+R 已发送接收到ACK
#define TW_MR_SLA_NACK 0x48 //SLA+R 已发送接收到NOT ACK
#define TW_MR_DATA_ACK 0x50 //接收到数据ACK 已返回
#define TW_MR_DATA_NACK 0x58 //接收到数据NOT ACK已返回
/********从机接收状态码********
#define TW_SR_SLA_ACK 0x60 //自己的SLA+W 已经被接收ACK已返回
#define TW_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收ACK 已返回
#define TW_SR_GCALL_ACK 0x70 //接收到广播地址ACK 已返回
#define TW_SR_ARB_LOST_GCALL_ACK 0x78 //SLA+R/W 作为主机的仲裁失败;接收到广播地址ACK已返回
#define TW_SR_DATA_ACK 0x80 //以前以自己的SLA+W被寻址;数据已经被接收ACK已返回
#define TW_SR_DATA_NACK 0x88 //以前以自己的SLA+W被寻址;数据已经被接收NOT ACK已返回
#define TW_SR_GCALL_DATA_ACK 0x90 //以前以广播方式被寻址;数据已经被接收ACK已返回
#define TW_SR_GCALL_DATA_NACK 0x98 //以前以广播方式被寻址;数据已经被接收NOT ACK已返回
#define TW_SR_STOP 0xA0 //在以从机工作时接收到STOP或重复START
/********从发送状态码********
#define TW_ST_SLA_ACK 0xA8 //自己的SLA+R 已经被接收ACK 已返回
#define TW_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收ACK 已返回
#define TW_ST_DATA_ACK 0xB8 //TWDR 里数据已经发送接收到ACK
#define TW_ST_DATA_NACK 0xC0 //TWDR 里数据已经发送接收到NOT ACK
#define TW_ST_LAST_DATA 0xC8 //TWDR 的一字节数据已经发送(TWAE = "0");接收到ACK
/********其它状态码********
#define TW_NO_INFO 0xF8 //没有相关的状态信息;TWINT = "0"
#define TW_BUS_ERROR 0x00 //由于非法的START 或STOP 引起的总线错误
/******** TWI接口的初始化函数********/
void TWI_init(void)
{
TWAR = 0x00; //主机模式,该地址无效
TWCR = 0x00; //关闭TWI模块
TWBR = Baud_set; //100
TWSR = P_value; //64分频
}
/********将Write_data写入AT24C04内部的以EE_address为地址的存储区********/
void write_EEPROM(uchar Write_data,uchar EE_address)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
while (!(TWCR & (1<<TWINT))); //0x08
TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x18
TWDR = EE_address;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x28
TWDR = Write_data;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x28
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}
/********从AT24C04内部的以EE_address为地址的存储区读出数据********/
uchar read_EEPROM(EE_address)
{
uchar temp;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
while (!(TWCR & (1<<TWINT))); //0x08
TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x18
TWDR = EE_address;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x28
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
while (!(TWCR & (1<<TWINT))); //0x10
TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x40
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x58
temp = TWDR;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
return temp;
}
模拟iic:
#include <iom16v.h>
#include <macros.h>
#define uint unsigned int
#define uchar unsigned char
uchar ack; //ack=1,发送正常,ack=0,表示接收器无应答
#define SLA_W 0xa0 //从机地址,主机写操作
#define SLA_R 0xa1 //从机地址,主机读操作
#define SCL_CLR PORTB &= ~(1 << PB6) //电平置低
#define SCL_SET PORTB |= (1 << PB6) //电平置高
#define SCL_IN DDRB &= ~(1 << PB6) //方向输入
#define SCL_OUT DDRB |= (1 << PB6) //方向输出
#define SDA_CLR PORTB &= ~(1 << PB7) //电平置低
#define SDA_SET PORTB |= (1 << PB7) //电平置高
#define SDA_R PINB & (1 << PB7) //电平读取
#define SDA_IN DDRB &= ~(1 << PB7) //方向输入
#define SDA_OUT DDRB |= (1 << PB7) //方向输出
/********函数声明********/
void delay_us(uint us); //短延时函数声明
void I2C_start(void); //启动信号函数声明
void I2C_stop(void); //停止信号函数声明
void I2C_init(void); //I2C总线初始化函数声明
void I2C_Ack(void); //应答信号函数声明
void I2C_NAck(void); //非应答信号函数声明
uchar RecByte(void); //接收(读)一字节数据函数声明
uchar SendByte(uchar write_data) ;//发送(写)一字节数据函数声明
void write_EEPROM(uchar value,uint addr);//向指定地址写一字节数据函数声明
uchar read_EEPROM(uint addr); //读取某一地址数据函数声明
uchar read_nbyte (uchar SLA,uchar SUBA,uchar *pdat,uchar n);//接收(读)n字节数据函数声明
uchar write_nbyte(uchar SLA,uchar SUBA,uchar *pdat,uchar n);//发送(写)n字节数据函数声明
/********us延时函数********/
void delay_us(uint us)
{
uint i;
us=us*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
for( i=0;i<us;i++);
}
/********I2C启动函数********/
void I2C_start(void)
{
SDA_SET;
SCL_SET;
delay_us(11);
SDA_CLR;
delay_us(11);
SCL_CLR;
}
/********I2C停止函数********/
void I2C_stop(void)
{
SDA_CLR;
delay_us(11);
SCL_SET;
delay_us(11);
SDA_SET;
}
/********I2C总线初始化函数********/
void I2C_init()
{
SCL_CLR;
I2C_stop();
}
/********发送应答函数********/
void I2C_Ack()
{
SDA_CLR;
SCL_SET;
delay_us(11);
SCL_CLR;
SDA_SET;
}
/********发送非应答函数********/
void I2C_NAck()
{
SDA_SET;
SCL_SET;
delay_us(11);
SCL_CLR;
SDA_CLR;
}
/********从I2C总线芯片接收(读)一字节数据函数********/
uchar RecByte()
{
uchar i=8,temp=0;
SDA_IN;
delay_us(11);
while (i--)
{
SCL_SET;
temp<<=1;
if (SDA_R){temp++;}
SCL_CLR;
delay_us(11);
}
SDA_OUT;
return temp;
}
/********向I2C总线芯片发送(写)一字节数据函数********/
uchar SendByte(uchar write_data)
{
uchar i=8;
while (i--)
{
if (write_data&0x80){SDA_SET;}else{SDA_CLR;}
write_data<<=1;
delay_us(11);
SCL_SET;
delay_us(11);
SCL_CLR;
}
SDA_SET;
delay_us(11);
SCL_SET;
SDA_IN;
delay_us(11);
if (SDA_R){ack=0;}else{ack=1;}
SCL_CLR;
SDA_OUT;
delay_us(11);
return ack; //返回应答位
}
/********向24CXX指定地址写入一字节数据函数********/
void write_EEPROM(uchar value,uint addr)
{
uchar i=3;
SDA_OUT;
SCL_OUT;
while (i--)
{
I2C_start();
SendByte(SLA_W);
if (ack==0)
{
I2C_stop();
continue;
}
SendByte(addr);
if (ack==0)
{
I2C_stop();
continue;
}
SendByte(value);
if (ack==0)
{
I2C_stop();
continue;
}
I2C_stop();
if(!(ack==0))break;
}
}
/********从24CXX指定地址读取一字节数据函数********/
uchar read_EEPROM(uint addr)
{
uchar value;
SDA_OUT;
SCL_OUT;
I2C_start();
SendByte(SLA_W);
SendByte(addr);
I2C_start();
SendByte(SLA_R);
value=RecByte();
I2C_stop();
return value;
}
/********向24CXX写入多字节数据函数********/
uchar write_nbyte(uchar SLA,uchar SUBA,uchar *pdat,uchar n)
{
uchar s;
I2C_start();
SendByte(SLA); //发送器件地址
if(ack==0) return(0);
SendByte(SUBA); //发送器件子地址
if(ack==0) return(0);
for(s=0; s<n; s++)
{
SendByte(*pdat); //发送数据
if(ack==0) return(0);
pdat++;
}
I2C_stop(); //结束总线
return(1);
}
/********从24CXX读取多字节数据函数********/
uchar read_nbyte (uchar SLA,uchar SUBA,uchar *pdat,uchar n)
{
uchar s;
I2C_start();
SendByte(SLA); //发送器件读地址
if(ack==0) return(0);
SendByte(SUBA); //发送器件子地址
if(ack==0) return(0);
I2C_start();
SendByte(SLA+1); //发送器件写地址
if(ack==0) return(0);
for(s=0; s<n; s++)
{
*pdat=RecByte(); //接收数据
I2C_Ack(); //发送应答位
pdat++;
}
I2C_NAck(); //发送非应答
I2C_stop(); //结束总线
return(1);
}转载
|