在本文中,我们将解释如何与外部EEPROM沟通使用I2C通信协议的AVR ATMEGA32 MCU。因此,让我们开始使用AVR Atmega32的EEPROM(AT24C16A)接口教程。

你通常需要一个外部EEPROM.当你的系统有一组用户可配置的设置,你需要保存,即使当系统关机;这样系统在下次启动时就会以这些配置启动。

在这种情况下,使用外部EEPROM为您提供了具有更大存储空间的优势(而不是在Atmega32中的内部EEPROM内置),除了保持用户配置,即使MCU失败也是如此。

Atmel EEPROM.

在本文中,我们将使用Atmel EEPROM AT24C16A。它是一个16K位存储器,组织成每个8位的2048字(2048字节)。它有8个大头针,如下图所示。

Atmel EEPROM引脚向上

A0,A1和A2引脚应留下未连接此特定EEPROM.以下绘图显示如何将其引脚连接到ATMEGA32 I2C引脚。您必须确保引脚7(WP连接到地面),因为此引脚是硬件写保护,除非接地,否则不会允许对存储器的任何写入操作。

接口EEPROM到Atmega32

I2C通信协议

I2C是一种总线接口连接,其包含在许多设备中,例如传感器,RTC(实时时钟)和EEPROM。它也被称为双线串行接口(TWI),它是低速设备之间的通信,用于在短距离内可靠的通信。I2C协议仅使用2个引脚,一个用于时钟(SCL)和一个用于数据(SDA)。在Atmega32中,这些引脚是PIN22(SCL)和PIN23(SDA)。它们分别在I / O端口C引脚0和1上复用。

因此,我们将首先使用AVR微控制器配置和启动I2C协议,然后我们将学习如何与EEPROM通信。

I2C在AVR ATMEGA32上的配置:

为了激活I2C协议,在主模式下,在Atmega32上需要配置3个寄存器:TWBR、TWSR和TWCR。我们将再次使用TWCR寄存器(在本教程的后面阶段)来操作通信。

TWBR:TWI比特率寄存器:

R / W. R / W. R / W. R / W. R / W. R / W. R / W. R / W.
TWBR7 TWBR6 TWBR5 TWBR4 TWBR3 TWBR2 TWBR1 TWBR0

这是一个7位的寄存器,其值用于确定数据将在两个通信设备之间交换的比特率。用来计算这个比特率的公式如下

方程

其中(TWBR)是TWI比特率寄存器中的值,TWPS是TWSR寄存器中的2位(TWPS0)&(TWPS1)的值,这将在接下来解释。

出于本练习的目的,我们将把值0x07放在TWBR寄存器中。

TWSR: TWI状态寄存器:

R R R R R R R / W. R / W.
TWS7 TWS6 TWS5 TWS4 TWS3 - - - - - - TWPS1. TWPS0.

在该寄存器中,我们只需要配置用于确定如上所述的比特率的位(TWPS0和TWPS1)。上述等式中的TWP的值如下确定

TWPS1. TWPS0. TWPS.
0 0 0
0 1 1
1 0 2
1 1 3.

在本文示例中,我们将把这些2位清除为零。

TWCR:TWI控制寄存器:

R / W. R / W. R / W. R / W. R R / W. 1 R / W.
TWINT TWEA TWSTA TWSTO TWWC 差不多 - - - - - - Twe.

该7位寄存器用于控制TWI的操作。现在,我们只需要设置差不多位(bit2),它启用I2C模块并覆盖其引脚(端口C引脚0和1)的I/O功能。

到目前为止已完成我们现在可以为I2C初始化写一个函数,如下所示:

void TWI_Init (void) {TWSR=0;TWBR = 0 x07;TWCR | =(1 < <差不多);}

I2C操作

为了开始使用I2C进行通信,您需要通过以下步骤进行:

  1. 通过控制TWI总线,通过将启动信号发送到自由时。
  2. 启动TWI数据传输
  3. 接收双胞胎数据。
  4. 停止传输并释放TWI总线。

我们将在下面详细解释这些步骤。

  1. 通过向其发送启动信号来控制TWI总线:

单片机作为TWI总线上的主人并对其进行控制,单片机感知到总线空闲,然后发出Start信号。这样做后,MCU捕获总线,其他设备不能发送数据,直到MCU释放总线,以避免数据冲突。之后,单片机就可以开始发送数据了。

在本节中,我们将为双线串行总线写入MCU的函数。

  1. 设置TWCR寄存器的TWEN位,确保I2C使能。
  2. 在TWCR寄存器的TWINT位上写1以清除中断标志。
    当I2C模块完成其当前工作并准备从SW获取更多命令时,硬件将该位设置为1。此外,清除此位会立即启动I2C模块。因此,每次我们想要启动I2C模块时,必须确保首先清除这个位,并轮询它,直到它再次变为1,因为这表明I2C已经成功执行了任务。
    注意:这个位永远不会被MCU硬件清除,你必须通过软件清除它。
  3. 向TWSTA寄存器中写入1。
    设置该位使MCU在速率上发送总线上的起始信号,以声明MCU当前正在控制总线并开始传输数据。
  4. 轮询TWINT位(之前已清除),直到它变为1。一旦设置了这个位,就意味着MCU已经成功地将总线控制为一个主总线。

*投票:是启动只有当位的值更改为我们想要的值时才退出的无限循环。这在下面的代码中展示。

#define get_bit(reg,bitnum)((reg&(1 << bitnum))>> bitnum)//获取用于获得某个位的值的位宏。void twi_start(void){twcr =(1 << Twint)|(1 << TWSTA)|(1 << TWEN);while(get_bit(twcr,twint)== 0)//在twint = 0 {}}上轮询

2.启动TWI数据传输:

控制总线后,MCU可以向其发送信息。这通过以下步骤实现:

  1. 将您需要发送在TWI数据寄存器中的数据。
  2. 向TWCR寄存器的TWEN位写1,以确保I2C开启。
  3. 向TWCR寄存器的TWINT位写1,确保TWINT位被清除。
  4. 轮询Twint位(先前清除)直到变为1.一旦设置该位,就意味着传输完成。

下面是函数代码:

void TWI_Write (char data) {TWDR=data;TWCR = (1 < < TWINT) |(1 < <差不多);while (get_bit(TWCR,TWINT)==0) {}}

3.接收TWI数据:

接收TWI数据比传输更容易。您需要遵循以下步骤:

  1. 向TWCR寄存器的TWEN位写1,以确保I2C开启。
  2. 向TWCR寄存器的TWINT位写1,确保TWINT位被清除。
  3. 轮询Twint位直到它变为1。
  4. 从TWDR寄存器读取数据。

此功能如下所示编码:

void twi_read_nack(char * ptr)//函数参数是一个指向mcu中的内存位置的指针,以将所接收的数据存储在{twcr =(1 << Twint)|(1 << Twen)中;while(get_bit(twcr,twint)== 0){} * ptr = twdr;}

4.停止传输并释放TWI总线:

一旦完成数据传输,就应该释放总线,以便其他设备使用它。这是通过以下步骤实现的:

  1. 向TWCR寄存器的TWEN位写1,以确保I2C开启。
  2. 向TWCR寄存器的TWINT位写1,确保TWINT位被清除。
  3. 将1写入TWCR寄存器的TWSTO位,发送停止信号并释放总线。

代码如下:

空白TWI_Stop (void) {TWCR = (1 < < TWSTO) |(1 < <差不多)| (1 < < TWINT);}

EEPROM.

现在我们已经看到了在Atmega32上启动和操作I2C所需的所有功能,让我们看看如何将其与EEPROM一起使用。

EEPROM写数据

要将数据写入EEPROM,您需要使用MCU软件进行下面给出的步骤:

  1. 控制I2C总线。
  2. 发送EEPROM的从地址。其构造如下:
    1. 地址的前4位是1010
    2. 接下来的3位表示内存页码。
    3. 最后一位指示内存操作是否是读取或写入。(写作)
      7 6 5 4 3. 2 1 0
      1 0 1 0 P2. P1. P0. 读/写指示器
  3. 再次发送开始信号
  4. 发送内存地址以读取。
  5. 接收从EEPROM读取的数据。
  6. 发送停止信号释放I2C总线。

此功能可以编码如下:

void EEPROM_Read (char address, char* ptr) //函数参数是EEPROM中读取的地址和MCU中存储读取数据的内存位置的指针{TWI_Start();TWI_Write (0 xa8);TWI_Write(地址);TWI_Start ();TWI_Write (0 xa9);TWI_Read_Nack (ptr);TWI_Stop ();}

现在,让我们把所有的作品放在一起!
下面的程序结合了我们上面写的所有功能,并使用它们对EEPROM的值写入EEPROM,再次检索它,将检索到的数据与写入写入的数据进行比较,如果它们相等(这应该是情况),将检索到的数据与绿色LED进行比较。

#define f_cpu 8000000ul #define get_bit(reg,bitnum)((reg&(1 << bitnum))>> bitnum)//获取用于获得某个位值的位宏。#include  #include  void twi_init(void);void twi_start(void);void twi_stop(void);void twi_write(char数据);void twi_read_nack(char * ptr);void EEPROM_WRITE(CHAR数据,CHAR地址);void EEPROM_READ(CHAR地址,CHAR * PTR);void twi_init(void){// set_bit(twcr,6);TWSR = 0; TWBR=0x07; TWCR|=(1<
        

EEPROM与ATmega32连接的照片(在PCB上)

Eeprom-Atmega32

演示视频

作者

评论被关闭。

Baidu