您的位置 首页 动态

IAR For AVR 两线串行接口 TWI 使用

ATMEL的TWI和PHILIPS的IIC基本上应该是算一个东西,但是他们在名义上是不同的,这样谁都不用支付给对方使用费。他们的协议是一…

ATMEL的TWI 和 PHILIPS的IIC 根本上应该是算一个东西,可是他们在名义上是不同的,这样谁都不必支交给对方运用费。他们的协议是相同的,一切咱们作为运用者根本能够简略的当作 TWI便是IIC

废话说完,开端正题。这次是关于在ATMega16 平台下的硬件IIC(还不太习气说TWI)的运用。在ATMega16的Datasheet里咱们能够看到很强壮的功用,主从设置许多。本文只说一种最常用的方法,那便是“ATMega16 硬件TWI 的 扫描发送 和 扫描读取”。

首先要清晰TWI 发送和承受的流程:

发送:

1,设定数据传输波特率

2,发送START信号,等候应对 ==》 《== 应对信号

3,发送芯片地址,等候应对 ==》 《==应对信号

4,发送数据的肯定地址,等候应对 ==》 《==应对信号

5,发送要写入的数据,等候应对 ==》 《==应对信号

6,发送STOP信号,开释总线 ==》 数据写入成功

接纳:

1,设定数据传输波特率

2,发送START信号,等候应对 ==》 《== 应对信号

3,发送芯片地址,等候应对 ==》 《==应对信号

4,发送数据的肯定地址,等候应对 ==》 《==应对信号

5,发送RESTART信号,等候应对 ==》 《==应对信号

6,发送芯片地址并注明读操作,等候应对 ==》 《==应对信号

7,读取数据,等候应对 ==》 《==应对信号

8,发送STOP信号,开释总线 ==》 数据读操作成功

使用芯片 :ATMega 16 晶振 : 7.3728

代码文件:Project

|___TWI.C

| |_____ IAR_DELAY.H

|___UART.C

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

IAR_DELAY.H

#ifndef __IAR_DELAY_H
#define __IAR_DELAY_H

#include

#define XTAL 7.3728 //可界说为你所用的晶振频率(单位Mhz)

#define delay_us(x) __delay_cycles ( (unsigned long)(x * XTAL) )
#define delay_ms(x) __delay_cycles ( (unsigned long)(x * XTAL*1000) )
#define delay_s(x) __delay_cycles ( (unsigned long)(x * XTAL*1000000) )

#endif

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

UART.C

#include
#define uchar unsigned char
#define uint unsigned int

//###########################################################
/*串口初始化函数*/
voidUart_Init(void)
{
UCSRB = (1<UCSRC = (1<

UBRRH=0x00; //设置波特率寄存器低位字节
UBRRL=47; //9600 //设置波特率寄存器高位字节

DDRD_Bit1=1; //装备TX为输出(很重要)
}
//###########################################################
/*发送一个字符数据,查询方法*/
voidUart_Transmit(uchar data)
{
while(!(UCSRA&(1< //while(UCSRA_UDRE==0); /* 等候发送缓冲器为空*/
UDR = data; /* 发送数据*/
}

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

#include
#include “IAR_DELAY.H”
#define uchar unsigned char
#define uint unsigned int

void Uart_Init(void);
void Uart_Transmit(uchar data);

//变量声明
#define EEPROM_BUS_ADDRESS 0xA0 //器材地址
/*#####################################################################*/
/*从器材地址位界说:______________________________________————-*/
/* AT24C02 | 1 | 0 | 1 | 0 | A2 | A1 | A0 | R/~W |————*/
/* —————————————————*/
/*#####################################################################*/
//主机发送形式时各状况字的后续动作
#define TW_START 0x08 //开端信号已宣布
#define TW_REP_START 0x10 //重复开端信号已宣布
#define TW_MT_SLA_ACK 0x18 //写字节已宣布并遭到ACK信号
#define TW_MT_SLA_NACK 0x20 //写字节已宣布并遭到NACK信号
#define TW_MT_DATA_ACK 0x28 //数据已宣布并遭到ACK 信号
#define TW_MT_DATA_NACK 0x30 //数据已宣布并遭到NACK 信号
#define TW_MT_ARB_LOST 0x38 //丢掉总线操控权
//主机接纳形式时各状况字的后续动作
#define TW_MR_ARB_LOST 0x38 //丢掉总线操控权,未收到应对信号
#define TW_MR_SLA_ACK 0x40 //读指令已宣布并遭到ACK
#define TW_MR_SLA_NACK 0x48 //读指令已宣布并遭到NACK
#define TW_MR_DATA_ACK 0x50 //数据已收到,ACK已宣布
#define TW_MR_DATA_NACK 0x58 //数据已收到,NACK已宣布

#define IIC_Start() TWCR =(1< // TWSTA位 会让硬件在总线上发生一个START的信号 , 声明自己期望成为主机
// TWEN 位 使能TWI功用,将 PC0 和 PC1 管脚切换到第二功用上来, 假如清零则为中止 TWI的传输
#define IIC_Stop() TWCR =(1<

#define IIC_Wait() while(!(TWCR&(1<

//##############################################################################
/*I2C总线单字节写入*/
unsigned char twi_write(unsigned char addr, unsigned char dd)
{
TWBR = 10; //设定波特率

/*start 发动*/
IIC_Start(); //硬件发送START信号,而且清零TWINT位,使能硬件TWI,使TWI开端作业
IIC_Wait(); //等候 发送START完结 TWINT方位位
if ((TWSR & 0xF8) != 0x08) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量,假如正确则向下进行数据传输,过错回来 0

/*SLA_W 芯片地址*/
TWDR = EEPROM_BUS_ADDRESS ; //芯片地址 0xA0 ,赋值给数据寄存器 TWDR ,等候发送
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x18) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*addr 操作地址*/
TWDR = addr; //将写入数据的肯定地址 ,赋值给数据寄存器 TWDR ,等候发送
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x28) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*dd 写入数据*/
TWDR = dd; //即将写入的数据 ,赋值给数据寄存器 TWDR ,等候发送
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x28) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*stop 中止*/
IIC_Stop(); //数据传输完结,发送STOP信号,开释对总线的操控
return 1; //写入数据成功 ,回来1 ,用来判别是否成功写入数据

}
//##############################################################################
/*I2C总线单字节读取*/
unsigned char twi_read(unsigned char addr)
{

unsigned char Receive_Byte ;
TWBR = 2; //设定波特率

/*start 发动*/
IIC_Start(); //硬件发送START信号,而且清零TWINT位,使能硬件TWI,使TWI开端作业
IIC_Wait(); //等候 发送START完结 TWINT方位位
if ((TWSR & 0xF8) != 0x08) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量,假如正确则向下进行数据传输,过错回来 0

/*SLA_W 芯片地址*/
TWDR = EEPROM_BUS_ADDRESS; //芯片地址 0xA0 ,赋值给数据寄存器 TWDR ,等候发送
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x18) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*addr 操作地址*/
TWDR = addr; //将写入数据的肯定地址 ,赋值给数据寄存器 TWDR ,等候发送
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x28) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*restart 重发动*/
IIC_Start(); //硬件发送 RESTART 信号,而且清零TWINT位,使能硬件TWI,使TWI开端作业
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x10) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*SLA_R 芯片地址*/
TWDR = 0xA1; //芯片地址 0xA0 并注明是读取操作(最终一位为 1 ),赋值给数据寄存器 TWDR ,等候发送
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x40) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0

/*读取数据*/
TWCR = (1 << TWINT) | (1 << TWEN); //对操控寄存器TWCR的 TWINT 位软件写1进行清零,然后 使能TWI硬件接口 ,让TWI进行作业,发送 TWDR寄存器 中的数据
IIC_Wait(); //等候数据发送结束 TWINT从头置位
if ((TWSR & 0xF8) != 0x58) return 0;//检测到TWINT方位位,比对TWSR寄存器内的状况量 , 假如正确则向下进行数据传输,过错回来 0
Receive_Byte = TWDR; //读取到的数据放到局部变量里

/*stop 中止*/
IIC_Stop(); //数据传输完结,发送STOP信号,开释对总线的操控

return Receive_Byte; //将读取到的数据作为函数的输出

}
//##############################################################################
/*主函数*/
void main(void)
{
uchar c,d;
Uart_Init(); //串口初始化
delay_us(20);
Uart_Transmit(0x55); //测验串口

c = twi_write(0x51,0xf8); //在地址0x51里写入数据0x22
Uart_Transmit(c); //将回来值发送到串口测验是否写入成功

delay_ms(2);

d = twi_read(0x51); //将地址0x51里的数据读出来
Uart_Transmit(d); //将读取到的数据发送串口
while(1);
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/dongtai/252155.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部