Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12606 Discussions

how to program use OpenCores I2C Master core in n2

Altera_Forum
Honored Contributor II
2,373 Views

hi all: 

 

I am useing the OpenCores I2C Master core in nios2 . 

 

But the core have no any documents to guide user. It just have a include file . 

 

I have writed the i2c read and write function. But it seems not work. 

 

Who can give me a i2c exampler code of read byte, write byte? Thanks a lot. 

 

following is the include file content: 

 

/* 

* Definitions for the Opencores i2c master core 

*/ 

 

/* --- Definitions for i2c master's registers --- */ 

 

/* ----- Read-write access */ 

# define OC_I2C_PRER_LO 0x00 /* Low byte clock prescaler register */ # define OC_I2C_PRER_HI 0x01 /* High byte clock prescaler register */ # define OC_I2C_CTR 0x02 /* Control register */  

 

/* ----- Write-only registers */ 

# define OC_I2C_TXR 0x03 /* Transmit byte register */ # define OC_I2C_CR 0x04 /* Command register */  

 

/* ----- Read-only registers */ 

# define OC_I2C_RXR 0x03 /* Receive byte register */# define OC_I2C_SR 0x04 /* Status register */ 

 

/* ----- Bits definition */ 

 

/* ----- Control register */ 

# define OC_I2C_EN (1<<7) /* Core enable bit: */ 

/* 1 - core is enabled */ 

/* 0 - core is disabled */# define OC_I2C_IEN (1<<6) /* Interrupt enable bit */ 

/* 1 - Interrupt enabled */ 

/* 0 - Interrupt disabled */ 

/* Other bits in CR are reserved */ 

 

/* ----- Command register bits */ 

# define OC_I2C_STA (1<<7) /* Generate (repeated) start condition*/# define OC_I2C_STO (1<<6) /* Generate stop condition */# define OC_I2C_RD (1<<5) /* Read from slave */# define OC_I2C_WR (1<<4) /* Write to slave */# define OC_I2C_ACK (1<<3) /* Acknowledge from slave */ 

/* 1 - ACK */ 

/* 0 - NACK */# define OC_I2C_IACK (1<<0) /* Interrupt acknowledge */ 

 

/* ----- Status register bits */ 

# define OC_I2C_RXACK (1<<7) /* ACK received from slave */ 

/* 1 - ACK */ 

/* 0 - NACK */# define OC_I2C_BUSY (1<<6) /* Busy bit */# define OC_I2C_TIP (1<<1) /* Transfer in progress */# define OC_I2C_IF (1<<0) /* Interrupt flag */ 

 

/* bit testing and setting macros */ 

# define OC_ISSET(reg,bitmask) ((reg)&(bitmask))# define OC_ISCLEAR(reg,bitmask) (!(OC_ISSET(reg,bitmask)))# define OC_BITSET(reg,bitmask) ((reg)|(bitmask))# define OC_BITCLEAR(reg,bitmask) ((reg)|(~(bitmask)))# define OC_BITTOGGLE(reg,bitmask) ((reg)^(bitmask))# define OC_REGMOVE(reg,value) ((reg)=(value))
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
1,083 Views

 

--- Quote Start ---  

originally posted by alex824@Mar 24 2006, 01:47 PM 

hi all: 

 

i am useing the opencores i2c master core in nios2 . 

 

but the core have no  any documents to guide user. it just have a include file . 

--- Quote End ---  

 

Dear alex824! 

 

This core has manuals with "Programming examples". 

These examples have useful programming steps for this core. 

You should follow these examples and everything would be fine.
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

some sample code 

 

 

 

// I2C REGISTERS# define I2C_PRERLO 0# define I2C_PRERHI 1# define I2C_CTR 2# define I2C_TXR 3# define I2C_RXR 3# define I2C_CR 4# define I2C_SR 4 

 

# define CTR_EN BIT7# define CTR_IEN BIT6 

# define CR_STA BIT7# define CR_STO BIT6# define CR_RD BIT5# define CR_WR BIT4# define CR_NACK BIT3 // # define CR_NC1 BIT2# define CR_NC2 BIT1# define CR_IACK BIT0 

# define SR_RXNACK BIT7# define SR_BUSY BIT6# define SR_AL BIT5# define SR_NC1 BIT4# define SR_NC2 BIT3# define SR_NC3 BIT2# define SR_TIP BIT1# define SR_IF BIT0 

 

# define I2C_WR 0# define I2C_RD BIT0 

 

int32_t i2c_init(void);  

int32_t i2c_write_byte(uint8_t ctrl,uint8_t data,uint8_t *i2c_status); 

int32_t i2c_read_byte(uint8_t ctrl,uint8_t *data,uint8_t *i2c_status); 

 

// write and read time is about 25us for one byte 

// we have to make timeout longer because of interrupts# define I2C_TIMEOUT (1000*50) // 40us (50 cputicks/us) 

 

 

 

int32_t i2c_init(void)  

IOWR(I2C_MASTER_0_BASE,I2C_CTR,0x00); // disable i2c 

IOWR(I2C_MASTER_0_BASE,I2C_PRERLO,24); // sclk = 400khz 

IOWR(I2C_MASTER_0_BASE,I2C_PRERHI,0); // sclk = 400khz 

IOWR(I2C_MASTER_0_BASE,I2C_CTR,CTR_EN); // enable i2c 

return 0; 

}; 

 

 

int32_t i2c_write_byte(uint8_t ctrl,uint8_t data,uint8_t *i2c_status) 

int32_t err=0; 

uint8_t status=0; 

uint32_t t1=0; 

char temp[10]; 

 

IOWR(I2C_MASTER_0_BASE,I2C_TXR,data); //  

IOWR(I2C_MASTER_0_BASE,I2C_CR,ctrl | CR_WR); //  

 

status=IORD(I2C_MASTER_0_BASE,I2C_SR); 

alt_timestamp_start(); 

while(!(status&SR_IF)) { 

 

status=IORD(I2C_MASTER_0_BASE,I2C_SR); 

t1=alt_timestamp(); 

if(t1>I2C_TIMEOUT)  

printf("***ERROR I2C write byte timeout:status:0x%02x %s\r\n",status,binTostr(temp,status)); 

err=-1; 

break; 

if(status&SR_RXNACK) 

printf("***ERROR I2C write byte ack failed:0x%02x %s\r\n",status,binTostr(temp,status)); 

err=-1; 

// printf("I2C write byte time:%05d\r\n",t1/50); 

IOWR(I2C_MASTER_0_BASE,I2C_CR,CR_IACK); //  

*i2c_status=status; 

return err; 

 

 

// normally ctrl = CR_ACK 

int32_t i2c_read_byte(uint8_t ctrl,uint8_t *data,uint8_t *i2c_status) 

int32_t err=0; 

uint8_t status=0; 

uint32_t t1=0; 

char temp[10]; 

 

IOWR(I2C_MASTER_0_BASE,I2C_CR,ctrl | CR_RD);  

status=IORD(I2C_MASTER_0_BASE,I2C_SR); 

alt_timestamp_start(); 

while(!(status&SR_IF)) { 

status=IORD(I2C_MASTER_0_BASE,I2C_SR); 

t1=alt_timestamp(); 

if(t1>I2C_TIMEOUT)  

printf("***ERROR I2C read byte timeout:status:0x%02x %s\r\n",status,binTostr(temp,status)); 

err=-1; 

break; 

// printf("I2C read byte time:%05d\r\n",t1/50); 

IOWR(I2C_MASTER_0_BASE,I2C_CR,CR_IACK); //  

*data=IORD(I2C_MASTER_0_BASE,I2C_RXR); 

*i2c_status=status; 

return err; 

}
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

[Dear alex824! 

 

This core has manuals with "Programming examples". 

These examples have useful programming steps for this core. 

You should follow these examples and everything would be fine. 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=13762)</div> 

 

--- Quote End ---  

 

 

Thank you very much! http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/dry.gif
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

Thank you very much! Fischer http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif

0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

hi : 

 

I write the i2c read and write function follow fischer&#39;s sample. 

 

The write function is work fine. 

 

But the read function hava a little problem. 

 

I find the i2c will work fail after use the read function. The reason is I didn&#39;t send  

 

the ACK to I2C slave. so the I2C slave still engross the I2C date. 

 

I try some ways to send the ACK signel to slave ,but not success. 

 

for instance: 

IOWR(I2C_MASTER_0_BASE,I2C_CR,CR_IACK); //  

IOWR(I2C_MASTER_0_BASE,I2C_CR,CR_NACK );  

*data=IORD(I2C_MASTER_0_BASE,I2C_RXR); 

 

Who can give me some advice? Thanks a lot!
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

int32_t aic12_read_reg(uint8_t reg,uint8_t *data,uint8_t count)  

uint32_t i; 

int32_t err=0; 

uint8_t status=0; 

uint8_t devadd=0x40; 

 

*data=0;  

// first init register index 

err=i2c_write_byte(CR_STA,(devadd<<1)|I2C_WR,&status); 

if(err) return -1; 

err=i2c_write_byte(CR_STO,reg,&status); 

if(err) return -1; 

// now read register index 

err=i2c_write_byte(CR_STA,(devadd<<1)|I2C_RD,&status); 

if(err) return -1; 

for(i=0;i<count-1;i++)  

err=i2c_read_byte(0,data,&status); // CR_NACK = BIT3 = 0 --> ack is sent  

if(err) return -1; 

data++; 

// create stop signal, no ack 

err=i2c_read_byte(CR_STO | CR_NACK ,data,&status);  

 

return err; 

 

 

this is sample code (device specific) to read from a codec device  

(see your device datasheet), you have to give the correct  

ctrl value to the read function, 

the read is done in the "for loop", the last read is done with  

"CR_STO | CR_NACK"  

if BIT 3 = CR_NACK is set, no acknoledge is sent  

 

good luck
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

Very interesting. Thank you for this valuable information. While looking over your code I ask myself if there is a way to monitor changes in the core through interrupts. Does someone know if this is possible and maybe could provide code samples or a clue how to implement it?

0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

hi all: 

 

I use the opencore I2C control the encode 7113 success by fisher and slava help. 

Thank you. 

 

The following is my codes.I wish it can help othters. 

# define BIT0 0x01# define BIT1 0x02# define BIT2 0x04# define BIT3 0x08# define BIT4 0x10# define BIT5 0x20# define BIT6 0x40# define BIT7 0x80 

 

// I2C REGISTERS# define I2C_PRERLO 0# define I2C_PRERHI 1# define I2C_CTR 2# define I2C_TXR 3# define I2C_RXR 3# define I2C_CR 4# define I2C_SR 4 

 

# define CTR_EN BIT7# define CTR_IEN BIT6 

# define CR_STA BIT7# define CR_STO BIT6# define CR_RD BIT5# define CR_WR BIT4# define CR_NACK BIT3 // # define CR_NC1 BIT2# define CR_NC2 BIT1# define CR_IACK BIT0 

# define SR_RXNACK BIT7# define SR_BUSY BIT6# define SR_AL BIT5# define SR_NC1 BIT4# define SR_NC2 BIT3# define SR_NC3 BIT2# define SR_TIP BIT1# define SR_IF BIT0 

 

# define I2C_WR 0# define I2C_RD BIT0 

# define DELAY_TIME 5 

 

//saa7113 macro-definition# define s_7113addr_w 0x4a# define s_7113addr_r 0x4b 

 

int i2cMaster_init(void)  

IOWR(INCODE_I2C_MASTER_BASE,I2C_CTR,0x00); // disable i2c 

IOWR(INCODE_I2C_MASTER_BASE,I2C_PRERLO,99); // sclk = 100khz 

IOWR(INCODE_I2C_MASTER_BASE,I2C_PRERHI,0); // sclk = 100khz 

IOWR(INCODE_I2C_MASTER_BASE,I2C_CTR,CTR_EN); // enable i2c 

 

return 0; 

}; 

 

int encode7113_write_byte(unsigned char subaddr, unsigned char data) 

if(encode7113_write_sl_waddr_subaddr(subaddr) == -1) 

return -1; 

 

if(encode7113_write_sl_data(data) == -1) 

return -1; 

 

return 0; 

 

int encode7113_write_sl_waddr_subaddr(unsigned char subaddr) 

// set start condition and write slave address 

IOWR(INCODE_I2C_MASTER_BASE,I2C_TXR,s_7113addr_w); 

IOWR(INCODE_I2C_MASTER_BASE,I2C_CR,CR_STA | CR_WR); 

 

if(waiting_for_tip() == -1) 

return -1; 

 

if(waiting_for_rxnack() == -1) 

return -1; 

 

//write subaddres 

IOWR(INCODE_I2C_MASTER_BASE,I2C_TXR,subaddr); 

IOWR(INCODE_I2C_MASTER_BASE,I2C_CR, CR_WR); 

 

if(waiting_for_tip() == -1) 

return -1; 

 

if(waiting_for_rxnack() == -1) 

return -1; 

 

return 0; 

 

 

int encode7113_write_sl_data(unsigned char data) 

IOWR(INCODE_I2C_MASTER_BASE,I2C_TXR,data); 

IOWR(INCODE_I2C_MASTER_BASE,I2C_CR, CR_STO | CR_WR); 

 

if(waiting_for_tip() == -1) 

return -1; 

 

if(waiting_for_rxnack() == -1) 

return -1; 

 

return 0; 

 

 

 

int waiting_for_tip(void) 

unsigned char cnt=20*DELAY_TIME; 

unsigned char status; 

 

status = IORD(INCODE_I2C_MASTER_BASE,I2C_SR); 

for(; cnt != 0; cnt--) 

if(status & SR_TIP) 

status =IORD(INCODE_I2C_MASTER_BASE,I2C_SR); 

else 

break; 

if(cnt == 1) 

printf("write slave address TIP fail\n"); 

return -1; 

return 0;  

 

int waiting_for_rxnack(void) 

unsigned char cnt=20*DELAY_TIME; 

unsigned char status; 

 

status = IORD(INCODE_I2C_MASTER_BASE,I2C_SR); 

for(; cnt != 0; cnt--) 

if(status & SR_RXNACK) 

status =IORD(INCODE_I2C_MASTER_BASE,I2C_SR); 

else 

break; 

if(cnt == 1) 

printf("RXNACK fail\n"); 

return -1; 

return 0;  

 

unsigned char encode7113_read_byte(unsigned char subaddr) 

unsigned char data; 

if(encode7113_write_sl_waddr_subaddr(subaddr) == -1) 

return 0; 

 

// set start condition and read slave address 

IOWR(INCODE_I2C_MASTER_BASE,I2C_TXR,s_7113addr_r); 

IOWR(INCODE_I2C_MASTER_BASE,I2C_CR,CR_STA | CR_WR); 

 

if(waiting_for_tip() == -1) 

return 0; 

 

if(waiting_for_rxnack() == -1) 

return 0; 

 

//set nack read and stop condition 

IOWR(INCODE_I2C_MASTER_BASE,I2C_CR, CR_RD | CR_NACK | CR_STO ); 

 

data = IORD(INCODE_I2C_MASTER_BASE,I2C_RXR); 

 

printf("data = %x\n",data); 

return data; 

}
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

where can i find the so-called programming example? 

thank you!
0 Kudos
Altera_Forum
Honored Contributor II
1,083 Views

 

--- Quote Start ---  

originally posted by sjtuj@Sep 4 2006, 07:33 AM 

where can i find the so-called programming example? 

thank you! 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=18039) 

--- quote end ---  

 

--- Quote End ---  

 

Summary of information: 

In this forum under "Post your own IP" check the post "Integrate the Opencores&#39;s I2C ip into SOPC" 

 

As mentioned by jdhar there is "A ready made avalon component - no need to do all of this." under: 

http://via.fps-tech.org/svn/fpga/cores/i2c_master/trunk/ (http://via.fps-tech.org/svn/fpga/cores/i2c_master/trunk/

-> copy the folder and files into a folder in your Quartus project directory, SOPC Builder will find the component automatically. Add the component to your SOPC Builder system and connect the signals to some pins. 

 

The single hdl files, some usefull documentation and programming examples (chapter 6 of "i2c_specs.doc") can be found under: 

http://www.opencores.org/cvsweb.shtml/i2c/ (http://www.opencores.org/cvsweb.shtml/i2c/

 

The code from Fischer or alex824 (thank you very much guys!!!) can be copied into a .c file and then just use that functions. 

 

Hope this makes it easier or faster for somebody http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif
0 Kudos
Reply