Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: I2C для TVP5146
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
Veg@
На DK-NIOS-2S60N (StratixII) пытаюсь связаться с платой АЦП DC-VIDEO-TVP5146N по интерфейсу I2C. Для этого:
1. использую Opencores I2C Master.
2. в соответствии с даташитом на АЦП я описал выводы:

QuartusII:
Код
...
output           scl_pad_io;
inout            sda_pad_io;
wire             scl_pad_io;
wire             sda_pad_io;
...
.scl_pad_io_to_and_from_the_opencores_i2c_master_0(scl_pad_io),
.sda_pad_io_to_and_from_the_opencores_i2c_master_0(sda_pad_io)  
...
3. взял готовую программную реализацию:
Код
#include <io.h>
#include "system.h"

// Overall status and control
#define IOWR_I2C_PRERLO(port,data)  IOWR(port, 0, data)
#define IOWR_I2C_PRERHI(port,data)  IOWR(port, 1, data)
#define IOWR_I2C_CTR(port,data)  IOWR(port, 2, data)
#define IOWR_I2C_TXR(port,data)  IOWR(port, 3, data)
#define IOWR_I2C_CR(port,data)  IOWR(port, 4, data)
#define IORD_I2C_PRERLO  IORD(port, 0)
#define IORD_I2C_PRERHI  IORD(port, 1)
#define IORD_I2C_CTR  IORD(port, 2)
#define IORD_I2C_RXR  IORD(port, 3)
#define IORD_I2C_SR  IORD(port, 4)

#define I2C_CR_STA 0x80
#define I2C_CR_STO 0x40
#define I2C_CR_RD 0x20
#define I2C_CR_WR 0x10
#define I2C_CR_ACK 0x08
#define I2C_CR_IACK 0x01

#define I2C_SR_TIP 0x02
#define I2C_SR_RXNACK 0x80
#define DELAY_TIME 35

void i2c_write(long port, unsigned char address, unsigned char reg, unsigned char data);
unsigned char i2c_read(long port, unsigned char address, unsigned char reg);
void init_i2c(long port,unsigned char address);
void i2c_wait_tip(long port);
void i2c_wait_rxnack(long port);

int main() {
    init_i2c(OPENCORES_I2C_MASTER_0_BASE,0xBA>>1);
    unsigned char data = i2c_read(OPENCORES_I2C_MASTER_0_BASE,0xBA>>1,0x0B);
    printf("reg: 0x%X",data);
    return 0;  
}

    void i2c_write(long port, unsigned char address, unsigned char reg, unsigned char data) {
      i2c_wait_tip(port);
      
      // write address
      IOWR_I2C_TXR(port, address<<1);
      IOWR_I2C_CR(port, I2C_CR_STA | I2C_CR_WR | I2C_CR_ACK);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
            
      // write register address
      IOWR_I2C_TXR(port, reg);
      IOWR_I2C_CR(port, I2C_CR_WR | I2C_CR_ACK);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
            
      // write data
      IOWR_I2C_TXR(port, data);
      IOWR_I2C_CR(port, I2C_CR_WR | I2C_CR_STO | I2C_CR_IACK);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
    }

    unsigned char i2c_read(long port, unsigned char address, unsigned char reg) {
      i2c_wait_tip(port);
      
       // write address
      IOWR_I2C_TXR(port, address<<1);
      IOWR_I2C_CR(port, I2C_CR_STA | I2C_CR_WR);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
          
      // write register address
      IOWR_I2C_TXR(port, reg);
      IOWR_I2C_CR(port, I2C_CR_WR);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
          
      // write address for reading
      IOWR_I2C_TXR(port, (address<<1) | 1);
      IOWR_I2C_CR(port, I2C_CR_STA | I2C_CR_WR);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
          
      // read data
      IOWR_I2C_CR(port, I2C_CR_RD | I2C_CR_ACK | I2C_CR_STO);
      i2c_wait_tip(port);
      i2c_wait_rxnack(port);
      return IORD_I2C_RXR;
    }
      
    void init_i2c(long port,unsigned char address) {
      // Setup prescaler
      int prescale = 200000000/(5*100000)-1;
      IOWR_I2C_PRERLO(port, prescale & 0xff);
      IOWR_I2C_PRERHI(port, (prescale & 0xff00)>>8);
      // Enable core
      IOWR_I2C_CTR(port, 0x80);
      // write init values
      i2c_write(port,address,0xE8,0x02);
      i2c_write(port,address,0xE9,0x00);
      i2c_write(port,address,0xEA,0x80);
      i2c_write(port,address,0xE0,0x01);
      i2c_write(port,address,0xE8,0x60);
      i2c_write(port,address,0xE9,0x00);
      i2c_write(port,address,0xEA,0xB0);
      i2c_write(port,address,0xE0,0x01);
      i2c_write(port,address,0xE0,0x00);
      i2c_write(port,address,0x03,0x01);
      i2c_write(port,address,0x03,0x00);
    }

    void i2c_wait_tip(long port) {
        int cnt=20*DELAY_TIME;
        unsigned char status;
        status = IORD_I2C_SR;
        for(; cnt != 0; cnt--) {
            if(status & I2C_SR_TIP) status = IORD_I2C_SR;
            else break;
            if(cnt == 1) {
                printf("write slave address TIP fail\n");
                return -1;
            }
        }
        return 0;
    }
    
    void i2c_wait_rxnack(long port) {
        unsigned char cnt=20*DELAY_TIME,status;
        status = IORD_I2C_SR;
        for(; cnt != 0; cnt--) {
            if(status & I2C_SR_RXNACK) status = IORD_I2C_SR;
            else break;
            if(cnt == 1) {
                printf("RXNACK fail\n");
                return -1;
            }
        }
        return 0;
    }
4. пытаюсь связаться с одним из декодеров TVP5146 по адресу 0xBA и прочитать регистр 0x0B. В ответ всегда приходит значение 0x00. При этом проверка на флаги TIP и RXNACK удачна (но даже и в том случае, когда я обращаюсь по неверному адресу устройства). Т.е. связь с ядром I2C видимо есть, а с АЦП - нет.

В связи с этим несколько вопросов:
1. достаточно ли для инициализации и дальнейшего общения с декодером использовать только линии SCL и SDA, которые предлагает Opencores I2C Master (нужны ли RESETB и I2CA) ?
2. насколько я понял, АЦП не имеет интерфейса WISHBONE (по крайней мере об этом нигде не написано). Возможно ли тогда вообще использовать в данном случае Opencores I2C Master? (как, например, расчитать значение делителя частоты?)
Спасибо.
FLTI
Цитата(Veg@ @ May 1 2010, 00:22) *
3. взял готовую программную реализацию:

Не могли бы Вы дать ссылку на источник этого кода.
Я его уже видел, но в несколько ином виде, например там не использовалось i2c_wait_rxnack(port) и по-иному описан i2c_wait_tip(long port).
Кстати, компиляция на i2c_wait_rxnack(port) и i2c_wait_tip(long port) выдаёт ошибки в тех местах, где Return.
Как Вы это обошли?

Также мне непонятно что означают и откуда взяты данные константы?

#define I2C_CR_STA 0x80
#define I2C_CR_STO 0x40
#define I2C_CR_RD 0x20
#define I2C_CR_WR 0x10
#define I2C_CR_ACK 0x08
#define I2C_CR_IACK 0x01

#define I2C_SR_TIP 0x02
#define I2C_SR_RXNACK 0x80
#define DELAY_TIME 35


В I2C-Master Core Specification с OpenCores они не значатся.

Ну и в итоге разобрались ли с проблемой?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.