AVR单片机 I2C总线 的使用

基于AVR单片机的Arduino提供了使用I2C总线的库,使用很方便,但是若想有个性化的功能就很难实现

本文就在AVR单片机上使用I2C作简要介绍


先简单介绍一下I2C总线

I2C有两根线,SDA,SCL,最多允许128个设备在总线上,每个设备都有唯一的地址

设备之间是有主从的关系的,主设备产生时钟信号,开始和结束数据传输


每次传输都有开始信号和结束信号,开始信号是在SCL高的时候拉低SDA,结束是在SCL高的时候拉高SDA
在数据传输过程中,但SCL高时,SDA必须保持不变



在开始信号和结束信号之间,总线忙


因为I2C又叫TWI(Two Wire Interface),所以AVR中相关寄存器都以TW开头

寄存器名都是英文的缩写,所以就不写中文名称了

TWBR:用来从CPU频率来产生SCL频率,可用如下公式,通过设置TWBR与PrescalerValue的值来确定总线频率


TWCR:control register

TWSR:status register

TWDR:data register

又比如如下几个寄存器,INT是中断的缩写,STA,STO分别是开始和结束,EN则是使能

理解了这些寄存器,便能轻松理解程序了

TWINT

TWSTA

TWSTO

TWEN


总线初始化函数

void i2c_init(void) 
{
  TWSR = 0;                                    // 把PrescalerValue设置为1
  TWBR = ((F_CPU / I2C_SPEED) - 16) / 2;       // 通过实现设置的I2C_SPEED来确定TWBR
  TWCR = 1<<TWEN;                              // 使能I2C
}

开始函数

void i2c_start(uint8_t address) 
{
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) ; // 开始
  waitTransmissionI2C();                       // 等待传输结束
  TWDR = address;                              // 发送设备地址
  TWCR = (1<<TWINT) | (1<<TWEN);
  waitTransmissionI2C();                       // 等待传输结束
}

结束函数

void i2c_stop(void) 
{
  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
}


等待传输结束函数

void waitTransmissionI2C() 
{
  uint16_t count = 255;
  while (!(TWCR & (1<<TWINT))) //若传输出现故障,开始计数
  {
    count--;
    if (count==0)       //当计数达到255扔故障,放弃传输
    {              
      TWCR = 0;                  //重置TWINT
      i2c_errors_count++;	//记录I2C故障
      break;
    }
  }
}


读函数

uint8_t i2c_read(uint8_t ack) 
{
  TWCR = (1<<TWINT) | (1<<TWEN) | (ack? (1<<TWEA) : 0);
  waitTransmissionI2C();
  uint8_t r = TWDR;       //返回TWDR(数据寄存器)中的值
  if (!ack) i2c_stop();
  return r;
}


有ack的读函数和没有ack的读函数

uint8_t i2c_readAck() 
{
  return i2c_read(1);
}

uint8_t i2c_readNak(void) 
{
  return i2c_read(0);
}


写函数

void i2c_write(uint8_t data ) 
{
  TWDR = data;                               // 向设备写一个字节
  TWCR = (1<<TWINT) | (1<<TWEN);
  waitTransmissionI2C();
}

有了这些函数,便可根据不同原件的要求,通过I2C进行读写操作了


参考资料:http://www.embedds.com/programming-avr-i2c-interface/

https://code.google.com/p/multiwii/






  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SMBus(System Management Bus)是一种基于I2C(Inter-Integrated Circuit)总线的通信协议,常用于电池管理、温度传感器、电子标签等应用。在单片机使用SMBus通信需要相应的硬件接口和软件程序支持。 以下是一份SMBus总线单片机C语言程序示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <avr/io.h> #include <util/delay.h> #include "i2c.h" #define SLAVE_ADDR 0x50 // 从机地址 int main(void) { uint8_t data[2]; // 存放读取的数据 i2c_init(); // 初始化I2C总线 while (1) { // 发送读取命令 if (!i2c_start(SLAVE_ADDR | I2C_WRITE)) { i2c_stop(); continue; } i2c_write(0x00); i2c_stop(); // 读取数据 if (!i2c_start(SLAVE_ADDR | I2C_READ)) { i2c_stop(); continue; } data[0] = i2c_read_ack(); data[1] = i2c_read_nack(); i2c_stop(); // 处理数据 int value = (data[0] << 8) | data[1]; float temperature = (float)value / 16.0; printf("Temperature: %.2f°C\n", temperature); _delay_ms(1000); // 延时1秒 } return 0; } ``` 这是一个使用AVR单片机的示例程序,需要先包含I2C总线驱动程序。在主函数中,先初始化I2C总线,然后循环读取从机的温度传感器数据,并将数据转换为实际温度值进行输出。 SMBus总线单片机硬件接口需要至少两个引脚,一个是SDA(数据线),一个是SCL(时钟线)。在电路图中,需要连接主控制器的SDA和SCL引脚到从机的SDA和SCL引脚,同时需要在从机上连接上拉电阻。在使用SMBus总线时,需要注意主从机的地址设置和数据读写的顺序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值