Jump to content

    

Recommended Posts

На DK-NIOS-2S60N (StratixII) пытаюсь связаться с платой АЦП DC-VIDEO-TVP5146N по интерфейсу I2C. Для этого:

1. использую Opencores I2C Master.

2. в соответствии с даташитом на АЦП я описал выводы:

1337383.jpg

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? (как, например, расчитать значение делителя частоты?)

Спасибо.

Edited by Veg@

Share this post


Link to post
Share on other sites
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 они не значатся.

 

Ну и в итоге разобрались ли с проблемой?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this