hi aim implementing i-button interface to lpc2148 using ds2482 1-wire to i2c bridge. my problem is i am using hardware i2c controller in lpc2148.i am writing 3 routine 1 detect the i button 2 read i-button 3 write i-button each routine using i2c interrupt.i seen some example in that all i2c code are written in side the interrupt routine only. im confused about how can i uses the interrupt routine for 3 main routine. and can i enable the i2c and initiate start and send slave addresses and receive the acknowledgment and come back from interrupt routine and do some work in main routine and again enter to i2c interrupt routine and continue the next i2c operation
aka "Finite State Machine" or "FSM" for short.
This sounds like a job for a State Machine:
Your interrupt routine besically just detects "Events", and it is up to the State Machine (in your "main" code) to handle these events.
Google for "State Machine", "Finite State Machine", and "FSM"...
Have you looked at the sample code available from Maxim?
That is generally a bad idea.
In general, interrupt handlers should be kept as short and quick as possible - just gathering data and/or setting flags to be used by the "main" code to do the "main" processing work...
hi .. can i configure I2CON to certain value and I2DAT with certain value after this enable I2C interrupt . in isr of I2C im not doing anything and checking status using containt of I2CSTAT resister to do the next part of i2c once again put the value in I2DAT and I2CON and once again enabling I2C interrupt.
It sounds like your first step needs to be to learn how to use the I2C controller in the LPC2148?
You need to do that before you start worrying about the DS2482.
I suggest that you start by reading the LPC2148 datasheet, and working through all the NXP examples and application notes that you can find.
See also: http://www.keil.com/download/list/arm.htm
The Maxim APPLICATION NOTE 3684, "How to Use the DS2482 I2C 1-Wire Master" requires only five I2C routines:
I2C_start: I2C start command. I2C_rep_start: I2C repeated start command. I2C_stop: I2C stop command. I2C_write: Writes a byte to the I2C bus. I2C_read: Reads a byte from the I2C bus.
So you need to get yourself to the stage of being able to write those 5 routines...
Is there any particular reason you are using a DS2482 as opposed to implementing a 1-Wire master on your LPC2148? For instance are you out of GPIO lines (you only need one)?
The reason I ask is because I think writing your own 1-Wire master is a lot simpler than using the I2C to 1-Wire bridge. Removing I2C from the equation is one less thing that can go wrong, if you know what I mean.
Either way, the app note Andy mentioned before (www.maxim-ic.com/.../3684) has a lot of code in it that you could use. I also have some 1-wire code for a lpc2148 that I wrote that I could post if you want.
It is trivial to bit-bang the one-wire protocol. The only real problem is if the processor is constantly busy, not having any time slots available where it may busy-wait for the bit delays and with multiple (or slow) high-priority interrupt routines that makes it hard to figure out a worst-case scenario.
Since everything in the one-wire interface is handled with varying pulse lengths, delays may only deviate with a few us.
"Since everything in the one-wire interface is handled with varying pulse lengths, delays may only deviate with a few us."
Note that timing only needs to be controlled within a timeslot - the timing between timeslots is completely uncritical.
Yes, infinite pauses are allowed, as long as they are not put within a bit read, bit write or presence detect. And a reset may be infinitely long.
If the target has other very high-priority tasks, the one-wire communication can be an interesting exercise in time multiplexing.
please send 1-wire code on lpc2148
I have pasted what I have. My code is set up to use Timer0 irq to clear the busy wait flag. 1-Wire line is on P0.4.
Please note that I haven't finished the Overdrive implementation. I was planning to switch on ODFlag to vary the low pulse times.
/* OneWire.c Source file for one wire ARM LPC2148 code One Wire line is on P0.4 */ #include <LPC21xx.H> #include <stdio.h> #include <stdlib.h> #include "OneWire.h" /********golbals***********/ char ODflag = 0; volatile char waiting = 1; /********end globals******/ /********Macros************/ #define OWline 0x00000010 //OWline to p0.4 #define ReadOne IO0PIN&OWline /*******end Macros*********/ /*************************/ //wait clears the waiting flag //and dissables timer irq /*************************/ __irq void wait() { T0IR = 1; // Clear interrupt flag T0TCR = 0; waiting = 0; // clear flag when irq fires VICVectAddr = 0; // Acknowledge Interrupt } /*************************/ //initializes 1-Wire pin and //timer irq /*************************/ void OW_init() { PINSEL0 &= 0xFFFFFFCF; // set pinsel to gpio p0.4 IO0DIR &= ~OWline; // set to input T0MCR = 3; // Interrupt and Reset on MR0 T0TCR = 0; // Timer0 dont enable until readyEnable VICVectAddr1 = (unsigned long)wait; // set interrupt vector in 0 VICVectCntl1 = 0x20 | 4; // use it for Timer 0 Interrupt VICIntEnable = 0x00000010; // Enable Timer0 Interrupt } /*************************/ //Pulls 1-Wire line low for //specified number of cycles /*************************/ __inline void PullLineLow(unsigned int cycles) { /* 60Mhz/4 = 15Mhz per instruction */ T0MR0 = cycles; //set # of cycles for irq waiting=1; //reset global //pull line low here IO0DIR |= OWline; //set p0.0 to ouput IO0CLR |= OWline; //set p0.0 to low T0TCR = 1; // Timer0 enable while(waiting){} //wait here until irq fires //let go of line here IO0DIR &= ~OWline; //set to input (hi-z) waiting=1; //reset global } /*************************/ //same as PullLineLow, without pulling line low /*************************/ __inline void delay(unsigned int cycles) { /* 60Mhz/4 = 15Mhz per instruction */ T0MR0 = cycles; waiting=1; //reset global T0TCR = 1; // Timer0 enable while(waiting){} waiting=1; } /****OW_ResetAndPD********/ //Sends a standard speed One Wire //Reset. Returns if a PD pulse //is read. /*************************/ int OW_ResetAndPD() { //Pull line low for reset pulse PullLineLow(7200); // pull low ~480us delay(900); // wait ~60us for tpdh //read Presence detect if( ReadOne ) // line high, no presence detect low return 0; // means no part or error delay(2700); // finish tpdl ~180us ODflag = 0; return 1; } /****OW_ReadByte***********/ //Reads a 1-Wire byte and returns it. /****************************/ char OW_ReadByte() { char Byte; short i; Byte=0; for(i=0;i<8;i++) { PullLineLow(70); //low for ~5us delay(140); //wait about 10us if( ReadOne ) Byte |= (1<<i); delay(675); //wait45; //complete tslot } return Byte; } /****OW_ReadByte***********/ //Reads multiple 1-Wire bytes //and returns a pointer to them. /****************************/ void OW_ReadBytes(int howMany, char* Byte) { int byteCount; for(byteCount=0;byteCount<howMany;byteCount++) Byte[byteCount] = OW_ReadByte(); } /****OW_WriteByte***********/ //Writes a 1-wire byte. /****************************/ void OW_WriteByte(char Byte) { int i; for(i=0;i<8;i++) { if(Byte & (1<<i)) { PullLineLow(70); //line low for ~5us delay(900); //line high for rest of tslot 60us }else { PullLineLow(970); //lin low for ~65us } delay(70); //trec about 5us } return; } /****OW_WriteByte***********/ //Writes Multiple 1-wire bytes. /****************************/ void OW_WriteBytes(char* Bytes, int howMany) { int i; for(i=0;i<howMany;i++) OW_WriteByte(Bytes[i]); return; } /****OW_ResetAndSkipRom***/ //Sends a standard speed One Wire //Reset and a skip rom command. Returns a //1 on successful PD pulse. /**************************/ int OW_ResetAndSkipRom() { PullLineLow(7200); //pull low ~480us delay(900); // wait ~60us for tpdh //read Presence detect if( ReadOne ) //line high, no presence detect low return 0; //means no part or error delay(2700); //finish tpdl ~180us ODflag = 0; OW_WriteByte(0xCC); return 1; } /****OW_ResetAndMatchRom***/ //Sends a standard speed One Wire //Reset and a match rom command with //Rom Code. Fails if no PD is read. /****************************/ int OW_ResetAndMatchRom(char* Rom) { PullLineLow(7200); //pull low ~480us delay(900); // wait ~60us for tpdh //read Presence detect if( ReadOne ) //line high, no presence detect low return 0; //means no part or error delay(2700); //finish tpdl ~180us ODflag = 0; OW_WriteByte(0x55); //Match Rom OW_WriteBytes(Rom,8); //Write RomCode return 1; } void OW_WriteScratch(char* scratchpadData,char TA1,char TA2) { OW_WriteByte(0x0F); //write scratch OW_WriteByte(TA1); //write TA1 OW_WriteByte(TA2); //write TA2 OW_WriteBytes(scratchpadData,32); //write scratch return; }
int OW_ReadScratch(char* scratchpadData,char TA1,char TA2,char ES) { char readTA1,readTA2,readES; char* readScratchPad; short i; readScratchPad = 0; OW_ResetAndSkipRom(); OW_WriteByte(0xAA); //read scratch readTA1 = OW_ReadByte(); //read TA1 if(readTA1 != TA1) return 0; readTA2 = OW_ReadByte(); //read TA2 if(readTA2 != TA2) return 0; readES = OW_ReadByte(); //read ES byte if(readES != ES) return 0; OW_ReadBytes(32, readScratchPad ); //read entire scratchpad for(i=0;i<32;i++) {// make sure it is what we think it is if(readScratchPad[i] != scratchpadData[i]) return 0; } return 1; } void OW_CopyScratch(char TA1,char TA2,char ES) { OW_ResetAndSkipRom(); OW_WriteByte(0x55); OW_WriteByte(TA1); OW_WriteByte(TA2); OW_WriteByte(ES); // waitSec; } char* OW_ReadRom(char TA1,char TA2,int howmany) { char* readbytes; readbytes=0; OW_ResetAndSkipRom(); OW_WriteByte(0xF0); OW_WriteByte(TA1); OW_WriteByte(TA2); OW_ReadBytes(howmany, readbytes); //read 'howmany' bytes of mem return readbytes; } //////******//////////// // Overdrive functions /////////////////////// /****OW_ResetAndSkipRom***/ //Sends a standard speed One Wire //Reset and a OD skip rom command. Returns a //1 on successful PD pulse. Done at regular //speed, puts part in OD mode. /**************************/ int OW_ResetAndODSkipRom() { PullLineLow(7200); //pull low ~480us delay(900); // wait ~60us for tpdh //read Presence detect if( ReadOne ) //line high, no presence detect low return 0; //means no part or error delay(2700); //finish tpdl ~180us OW_WriteByte(0x3C); ODflag=1; return 1; } /****OW_ResetAndMatchRom***/ //Sends a standard speed One Wire //Reset and a match rom command with //Rom Code. Fails if no PD is read. //Reset and PD done at reg speed, //puts part in OD mode, sends rom //code at OD speeds. /****************************/ int OW_ResetAndODMatchRom(char* Rom) { return 0; }
I forgot to mention that this code uses a MCB2140 running at 60Mhz.
Drew
//one wire interface using ds2482 using LPC2148 hardware I2C //************** crystal=12Mhz Pclk=12Mhz**************// #include<lpc214x.h> void i2c_INIT(void); void i2c_STOP(void); unsigned int i2c_data_read(void); void i2c_data_write(unsigned int); void SendI2CAddress_R(unsigned char); void SendI2CAddress_W(unsigned char); #define ds2482_address_write 0x30 #define ds2482_address_read 0x31 #define STA 0x20 #define SIC 0x08 #define SI 0x08 #define STO 0x10 #define STAC 0x20 #define AA 0x04 #define AAC 0x04 #define I2CBLOCK_ENABLE 0x40 //enable the hardware I2C block unsigned int state; //*****************MAIN_START************************// main() { unsigned int value; i2c_INIT(); while(1) { unsigned int temp=0x00;SendI2CAddress_W(ds2482_address_write); i2c_data_write(command); SendI2CAddress_R(ds2482_address_read); temp=i2c_data_read(); while(1); } } //*****************I2C_INITIALIZATION***************************// void i2c_INIT(void) { I2C0CONCLR = 0xFF; PINSEL0 |= 0x50; // Set pinouts as scl and sda I2C0SCLL=0x64; //Set bit rate 12 Mhz/VPBDIV+SCLH+SCLL I2C0SCLH=0x64; // } //****************i2c_write*******************// void i2c_data_write(unsigned int data) I2C0DAT=data; while( ! (I2C0CONSET & SI)); //wait untill status available... state=I2C0STAT; if(state ==0x28 ) { I2C0CONCLR |= SIC; } else if(state==0x30)// i2c stop condition. { I2C0CONCLR = SIC; I2C0CONSET = STO; } } //****************i2c_address_write*****************// void SendI2CAddress_W(unsigned char Addr_S) { I2C0CONCLR = 0xFF; // function would hang. I2C0CONSET = I2CBLOCK_ENABLE; // Hardware I2C bus //block enabled I2C0CONSET = STA ; // set STA - allow master to //acknowlege slave; while(I2C0STAT!=0x08); // Wait for start to be completed I2C0CONCLR = STAC ;//stop repeatrd //start condition I2C0DAT = Addr_S; // Charge slave Address I2C0CONCLR = SIC; while( ! ( I2C0CONSET & SI)) ; // wait till status //available state=I2C0STAT; // read Status.See standard error codes if(state == 0x18) { state=I2C0STAT; // read Status.See standard error codes } else if(state !=0x18) { i2c_STOP(); } } //****************i2c_address_read*****************// void SendI2CAddress_R(unsigned char Addr_S) { I2C0CONCLR = 0xFF; // function would hang. I2C0CONSET = I2CBLOCK_ENABLE; // Hardware I2C bus block enabled I2C0CONSET = STA | AA; // set STA - allow master to //acknowlege slave; while(I2C0STAT!=0x08); // Wait for start to be //completed I2C0CONCLR = STAC;//clear repeated start condition I2C0DAT = Addr_S; // Charge slave Address I2C0CONCLR = SIC; while( !(I2C0CONSET & SI)) ;// wait till status //available state=I2C0STAT;// read Status. See standard error code if(state !=0x40) { i2c_STOP(); } else if(state == 0x40) { state=I2C0STAT; // read Status. See standard error codes } } //*******************I2C_READ_DATA*****************// unsigned int i2c_data_read(void) { unsigned int temp; I2C0CONCLR = SIC; while( ! ( I2C0CONSET & SI)) ; // wait till status available state=I2C0STAT; if(state == 0x50) { return I2C0DAT; } else if(state== 0x58) { i2c_STOP(); } } // ********************I2C_STOP**************************// void i2c_STOP(void) { while( ! ( I2C0CONSET & SI)) ; // wait till status available I2C0CONSET = STO; I2C0CONCLR = SIC; } }
******************************************
1.my problem is that when i send the address to i2c slave im getting status code as 0x18 ie address+w is sented to save and ack is received by master. 2. when i try to write data im getting status code as 0x30 insted of 0x28 i.e. data on I2C0DAT is transmitted and ack not recived.
What is the value of command in i2c_data_write(command) ? I think if you send an invalid command the ds2482 will nack.
0xF0 is a device reset and clears the state machine of the DS2482, have you tried writing that as your first command?
Now im getting ack