avr单片机的TWI两线串行接口

发布者:gamma14最新更新时间:2015-09-28 来源: eefocus关键字:avr单片机  TWI两线  串行接口 手机看文章 扫描二维码
随时随地手机看文章
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

//###########################################################

void Uart_Init(void)
                       
   UCSRB = (1<      //允许发送和接收
UCSRC = (1<

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

DDRD_Bit1=1;                                                         //配置TX为输出(很重要)
}
//###########################################################

void Uart_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         //器件地址
                                                                            
                                                                            
                                                                             
                                                                            
                                                                            
//主机发送模式时各状态字的后续动作
#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<    // TWINT位 通过写1进行清零,一旦清零则TWI开始工作,当相应硬件工作完成后 TWINT位会重新置位为1
                                                                      // TWSTA位 会让硬件在总线上产生一个START的信号 , 声明自己希望成为主机
                                                                      // TWEN 位 使能TWI功能,将 PC0 和 PC1 管脚切换到第二功能上来, 如果清零则为中断 TWI的传输
#define IIC_Stop()          TWCR =(1<    // TWSTO位 在主机模式下,会让硬件在总线上产生一个STOP得信号,并且SCL 和 SDA 两个引脚位高阻态

#define IIC_Wait()          while(!(TWCR&(1<                // TWINT位 经过一次置位使硬件TWI开始工作 ,然后在检测 TWCR 寄存器的 TWINT 位是不是被置位,如果置位为1则表示工作完成可以向下进行

//##############################################################################[page]

unsigned char twi_write(unsigned char addr, unsigned char dd)
{
        TWBR = 10;                           //设定波特率


IIC_Start();                         //硬件发送START信号,并且清零TWINT位,使能硬件TWI,使TWI开始工作
IIC_Wait();                          //等待 发送START完成 TWINT位置位
if ((TWSR & 0xF8) != 0x08) return 0; //检测到TWINT位置位,比对TWSR寄存器内的状态量,如果正确则向下进行数据传输,错误返回 0
       
       
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
       
      
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
       
       
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

       
IIC_Stop();                          //数据传输完成,发送STOP信号,释放对总线的控制
return 1;                            //写入数据成功 ,返回1 ,用来判断是否成功写入数据
       
}
//##############################################################################

unsigned char twi_read(unsigned char addr)
{

unsigned char Receive_Byte ;
TWBR = 2;                            //设定波特率
      
       
IIC_Start();                         //硬件发送START信号,并且清零TWINT位,使能硬件TWI,使TWI开始工作
IIC_Wait();                          //等待 发送START完成 TWINT位置位
if ((TWSR & 0xF8) != 0x08) return 0; //检测到TWINT位置位,比对TWSR寄存器内的状态量,如果正确则向下进行数据传输,错误返回 0
      
   
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
       
      
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
       
       
IIC_Start();                         //硬件发送 RESTART 信号,并且清零TWINT位,使能硬件TWI,使TWI开始工作
        IIC_Wait();                          //等待数据发送完毕 TWINT重新置位
if ((TWSR & 0xF8) != 0x10) return 0; //检测到TWINT位置位,比对TWSR寄存器内的状态量 , 如果正确则向下进行数据传输,错误返回 0
       
      
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;                 //读取到的数据放到局部变量里
       
       
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);
}

关键字:avr单片机  TWI两线  串行接口 引用地址:avr单片机的TWI两线串行接口

上一篇:AVR单片机(学习ing)-ATMEGA16的USART与PC机串行通信
下一篇:AVR单片机(学习ing)—(九)、ATMEGA16的模数转换器—01

推荐阅读最新更新时间:2024-03-16 14:33

AVR单片机(ATMEGA16)DA0832芯片D/A转换
#include iom16v.h #define uchar unsigned char #define uint unsigned int #define cs_l PORTD&=0xfe//输出低电平 #define wr_l PORTD&=0xfd//输出低电平 void delayms(uint x)//8M晶振下延时1ms { uint y,z; for(y=x;y 0;y--) for(z=1325;z 0;z--); } void main() { uchar temp; DDRC=0xff;//设置PC为输出 DDRD|=
[单片机]
<font color='red'>AVR单片机</font>(ATMEGA16)DA0832芯片D/A转换
基于AVR单片机的汽车空调控制系统设计
基于AVR单片机的汽车空调控制系统 摘要: AVR单片机功能强大,用AVR单片机开发各种控制系统只需很少的外部器件就可以实现强大的功能。本文介绍的就是利用Atmega16、CodeVisionAVR C开发环境、Proteus仿真软件开发汽车空调自动控制系统。 前言 Atmega16是美国ATMEL公司的高档8位单片机,采用Flash存储器,可以擦写10000次以上、内部集成 、四通道PWM、集成8路10位精度ADC、片内经过标定的RC振荡器、采用精简指令集,具有32个通用工作寄存器,具有只需两个时钟周期的硬件乘法器,运算速度快等。由于其集成度高、处理速度快,使得利用AVR单片机进行系统开发只需很少(甚至没有)的
[单片机]
基于<font color='red'>AVR单片机</font>的汽车空调控制系统设计
自制51/avr单片机USB ISP 下载线
  如今呢是使用笔记本的人越来越多了,可是呢买了笔记本对于学习很多单片机比如说51或者avr就不方便了。因为大多数电脑都不带串并口了。但是呢新出的笔记本上的USB接口是足够用的。因而都想用USB转了串口或者并口就能方便单片机学习开发时的ISP编程或者JTAG仿真了。其实很多单片机开发商和销售商都早就有了USBisp的配套软件和硬件了的,只不过都比较昂贵,而且技术资料多是保密的,对于自己小本学习单片机的人而言不免都希望能与价廉物美的USBISP烧写器,而且也多想自己动手做一个了。   网上公开的比较流行的支持51和AVR的烧写器是用ATMEL公司的MAGE8单片机做的,其机理也就是通过软件编程的方式将USB接口信号转换为并口信号以
[单片机]
自制51/<font color='red'>avr单片机</font>USB ISP 下载<font color='red'>线</font>
基于AVR单片机的有害气体感应及警示控制系统的设计
利用红外感应系统感应附近有无有害气体,当红外感应系统感受到有有害气体接近时,送出持续一段时间的高电平;单片机通过开启中断,启动语音芯片,单片机通过串口通信,从上位机提取的有害气体参数提示给附近人体,并经过与安全值的比较判定当前环境是否安全。对语音芯片的使用,先将必要的文字、数字信息录制进去,放音时,通过单片机自动寻址,把实时参数读取出来。为便于以后系统改进或移植到其他系统,可设计录音、放音电路,通过切换录制不同内容。系统设计友好、方便,给人的信息也更加直接。 1系统总体设计方案 在气体浓度是现有可利用的数据的基础上,考虑了系统的衔接性和可移植性。系统总体方案见图1。 本系统分为四大模块:核心控制模块、语音电路
[单片机]
基于<font color='red'>AVR单片机</font>的有害气体感应及警示控制系统的设计
avr单片机c语言编程风格介绍
  摘要:作为一个初学者如何具有良好的程序设计风格呢?下面小编将以avr单片机介绍它的c语言编程风格。   C语言编程风格介绍   1.变量定义   在定义变量时,前缀使用变量的类型,之后使用表现变量用途的英文单词或单词缩写,且每个单词或缩写的首字母大写,各种前缀缩写如下:   无符号变量使用 u8,u16,u32;例:unsigned char u8Temp;   有符号变量使用 s8,s16,s32;例:char s8Temp;   浮点数变量使用 f32,d64;例:float f32Temp;   结构体变量使用 st;例:struct Temp stTemp;   字符串变量使用 s;例:char sTemp;   
[单片机]
<font color='red'>avr单片机</font>c语言编程风格介绍
AVR单片机与74HC595的SPI显示程序
使用SPI接口控制74HC595 LED显示 SPI接口的全称是 Serial Peripheral Interface ,意为串行外围接口。SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。 SPI接口是在CPU和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,为全双工通信,数据传输速度总体来说比I2C总线要快,速度可达到几Mbps。 SPI接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从器件,其接口包括以下四种信号: (1)MOSI 主器件数据输出,从器件数据输入 (2)MISO 主器件数据输入,从器件数据输
[单片机]
avr单片机用什么编程?avr单片机编程方式是什么
  本节将详细介绍AVR单片机的流行编程方式,并略述其工作原理,旨在让AVR爱好者根据自己的需要选择或制作恰当的编程工具。下面我们一起来看看avr单片机编程方式讲解。   1、avr单片机用什么编程?   AVR单片机是1997年由ATMEL公司研发出的增强型内置Flash的RISC(Reduced InstrucTIon Set CPU) 精简指令集高速8位单片机。可以广泛应用于计算机外部设备、工业实时控制、仪器仪表、通讯设备、家用电器等各个领域。AVR单片机是 Atmel 公司 1997 年推出的 RISC 单片机。RISC(精简指令系统计算机)是相对于CISC(复杂指令系统计算机)而言的。RISC 并非只是简单地去减少指令,
[单片机]
<font color='red'>avr单片机</font>用什么编程?<font color='red'>avr单片机</font>编程方式是什么
基于AVR单片机的服装压力检测系统设计
O 引言 服装是人们生活的一个重要组成部分,它的设计除了款式、花色、光泽等外观因素之外,舒适性也是服装功能性的一个重要组成部分。所谓服装舒适性是指人体着装后,服装具有满足人体要求并排除任何不舒适因素的性能。服装压可分为两种:由服装自身重量形成的垂直压和由服装紧裹身体产生的束缚压。 传统服装压力舒适度测试方法主要有:流体压力法、电阻法、石膏法。其中,使用流体水银压力计或水压机来测量服装压力的方法简单直接,但精度较低,尤其动态测量相当困难;电阻测量方法是将电阻应变片传感器插入衣服内,由于服装压力而使应变片变形导致电阻值的变化,从而将压力变化转换为变化的电压信号,通过测量该变化的电压值得出服装压力测试结果。该方法测试精度高,
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved