【问题标题】:Codevision AVR access external eeprom 24c02B using TWICodevision AVR 使用 TWI 访问外部 eeprom 24c02B
【发布时间】:2015-05-23 19:09:07
【问题描述】:

我是 C 的初学者。我正在尝试读写外部 eeprom (AT24c02B),然后将存储在 eeprom 中的数据字节显示到 PORTB 中的 LED 和/或 LCD。所以我知道数据成功存储在eeprom中。

PORTB 中的 LED 低电平有效。

这是代码,我从 cvAVR 帮助中获得的:

#include <mega16a.h>

// Alphanumeric LCD functions
#include <alcd.h>

// Declare your global variables here

// TWI functions
#include <twi.h>

#include <delay.h>

/* 7 bit TWI bus slave address of the AT24C02B 2kbyte EEPROM */
#define EEPROM_TWI_BUS_ADDRESS (0xA0 >> 1)

void main(void)
{
// Declare your local variables here
struct
     {
     struct
          {
          unsigned char msb;
          unsigned char lsb;
          } addr;
     unsigned char data;
     } twi_eeprom;


unsigned char eeprom_rd_data;

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out 
DDRA=(1<<DDA7) | (1<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
// State: Bit7=0 Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0 
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out 
DDRB=(1<<DDB7) | (1<<DDB6) | (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit7=1 Bit6=1 Bit5=1 Bit4=1 Bit3=1 Bit2=1 Bit1=1 Bit0=1 
PORTB=(1<<PORTB7) | (1<<PORTB6) | (1<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (1<<PORTB2) | (1<<PORTB1) | (1<<PORTB0);

// TWI initialization
// Mode: TWI Master
// Bit Rate: 100 kHz
twi_master_init(100);

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTA Bit 0
// RD - PORTA Bit 1
// EN - PORTA Bit 2
// D4 - PORTA Bit 4
// D5 - PORTA Bit 5
// D6 - PORTA Bit 6
// D7 - PORTA Bit 7
// Characters/line: 16
lcd_init(16);

// Global enable interrupts
#asm("sei")

/* write the byte 0x55 to the AT24C02B EEPROM address 0x210 */
twi_eeprom.addr.msb=0x02;
twi_eeprom.addr.lsb=0x10;
twi_eeprom.data=0x55;
twi_master_trans(EEPROM_TWI_BUS_ADDRESS,(unsigned char *) &twi_eeprom,3,0,0);

/* 10ms delay to complete the write operation */
delay_ms(10);

/* read the byte back into the eeprom_rd_data variable */
twi_master_trans(EEPROM_TWI_BUS_ADDRESS,(unsigned char *) &twi_eeprom,2,&eeprom_rd_data,1);

while (1)
      {
      // Place your code here

      PORTB = ; //What variable should I call?
      delay_ms(3000);
      }
}  

twi.h

/******************************************************************************
 TWI driver library for the CodeVisionAVR C V2.05.1+ Compiler

 Copyright (C) 2010-2011 Pavel Haiduc, HP InfoTech S.R.L., All rights reserved.
*******************************************************************************/

#ifndef _TWI_INCLUDED_
#define _TWI_INCLUDED_

#include <stdbool.h>

// TWI transaction result values
#define TWI_RES_OK 0
#define TWI_RES_BUFFER_OVERFLOW 1
#define TWI_RES_ARBITRATION_LOST 2
#define TWI_RES_BUS_ERROR 3
#define TWI_RES_NACK_RECEIVED 4
#define TWI_RES_BUS_TIMEOUT 5
#define TWI_RES_FAIL 6
#define TWI_RES_UNKNOWN 7

extern unsigned char twi_tx_index; // data index in the transmit buffer
extern unsigned char twi_rx_index; // data index in the receive buffer
extern unsigned char twi_result; // holds the result of the last TWI transaction

// TWI master initialization
// bit_rate - SCL bit rate [kHz]
void twi_master_init(unsigned int bit_rate);

// function used for performing a TWI master transaction
// slave_addr - 7 bit address of the TWI slave with which the transaction must be performed
// tx_data - pointer to the buffer that holds the data to be transmitted to the slave
// tx_count - number of bytes that must be transmitted to the slave during the transaction
// rx_data - pointer to the buffer that holds the data received from the slave
// rx_count - number of bytes that must be received from the slave during the transaction
// returns true on success
bool twi_master_trans(
     unsigned char slave_addr,
     unsigned char *tx_data, unsigned char tx_count,
     unsigned char *rx_data, unsigned char rx_count);

// TWI slave initialization
// match_any_addr - if true, the slave match address logic responds to all received addresses
// addr - 7 bit address of the TWI slave
// rx_buffer - pointer to the slave receive buffer
// rx_buffer_size - size of the slave receive buffer
// tx_buffer - pointer to the slave transmit buffer
// slave_rx_handler - pointer to the TWI slave receive processing function
// slave_tx_handler - pointer to the TWI slave transmit processing function
void twi_slave_init(
     bool match_any_addr,
     unsigned char addr,
     unsigned char *rx_buffer,
     unsigned char rx_buffer_size,
     unsigned char *tx_buffer,
     bool (*slave_rx_handler)(bool rx_complete),
     unsigned char (*slave_tx_handler)(bool tx_complete)
     );

#pragma library twi.lib

#endif

我想问的是:
1. 写入 eeprom 后,我应该调用什么变量来显示 8 LED 上的字节?

ex: 写入字节后:0xF0,则 PORTB 中的 LED 将为 0xF0 (11110000)

  1. 我在互联网上搜索过,但仍然对这条线感到困惑

twi_master_trans(EEPROM_TWI_BUS_ADDRESS,(unsigned char *) &amp;twi_eeprom,3,0,0);

twi_master_trans(EEPROM_TWI_BUS_ADDRESS,(unsigned char *) &amp;twi_eeprom,2,&amp;eeprom_rd_data,1);

有人可以解释一下吗? &amp;twi_eeprom,3,0,0 实际上是什么意思?

设备:Atmega16a
程序:Codevision AVR 3.12
外部 eeprom : AT24c02b

任何答案和评论将不胜感激。
谢谢并原谅我的英语。

一品

【问题讨论】:

  • 嗯,'twi.h' 中有什么东西?
  • @MartinJames 我忘了附上,等我编辑我的帖子
  • 使用stdint.h,而不是内置类型。
  • @Olaf 你是说'struct' typedef吗?我会试试看。谢谢
  • stdint.h 与结构有什么关系? 你的谷歌关闭了吗?如果该代码来自 Atmel,那就怪罪他们(好吧,这实际上并不奇怪)。要了解发送的内容等,只需阅读 EEPROM 和 AVR 的数据表(这可能包括参考手册、用户指南、家庭指南等)

标签: c embedded microcontroller avr eeprom


【解决方案1】:

TWI 是一种将数据从主设备双向传输到从设备的方法。在您的情况下,您的代码在主机上运行,​​而 EEPROM 是从机。数据同时在设备之间移动。也就是说,一个字节被传输到从机的同时,一个字节被从机传回。

twi.h 中给出的函数描述了启动此过程的方法,并在此处描述了参数。

unsigned char slave_addr,
unsigned char *tx_data, 
unsigned char tx_count,
unsigned char *rx_data, 
unsigned char rx_count

第一个参数是代码中给出的常量。

接下来的两个参数是要从中获取数据的缓冲区的地址和要获取的长度。

接下来的两个是接收数据的缓冲区地址和长度。

要将0x55 写入特定地址的 EEPROM,您需要向 EEPROM 发送三个字节。这些为您安排在一个结构中。如果你给函数结构的地址和长度 3,函数会为你处理它。 (unsigned char *) &amp;twi_eeprom 是结构体的地址。

你现在不关心接收,所以只需输入 0 和 0 作为接收地址和长度。

读回值时,只需将字节的地址发送到EEPROM即可。所以发送相同的结构,但只有两个字节。您还需要保存接收到的字节。它将进入变量eeprom_rd_data,因为您将该变量的地址传递给了函数。将 PORRTB 设置为等于 eeprom_rd_data 以显示其值。

【讨论】:

  • 我试过了,但所有的 LED 一直亮着。有人知道为什么吗?我很困惑。
  • 是时候学习使用调试器了。只需阅读工具链的文档即可。
  • 我怀疑twi_master_trans() 的调用方式有问题。在我看来,EEPROM 应该接收 2 个字节的地址,然后在第三轮发回您正在寻找的数据。这意味着您应该将三个字节保存到一个数组中,然后查看第三个字节的数据。我建议将unsigned char eeprom_rd_data[3];声明为一个数组,调用函数读取长度3而不是1,然后在eeprom_rd_data[2]中查找数据。仔细查看 EEPROM 的数据表,找出正确的协议。
  • @Olaf 解决了先生,这是我的硬件。代码有效。提前致谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多