![]() |
Forum Index : Microcontroller and PC projects : (uM) Possible I2C Bug with 4.5C
Author | Message | ||||
redrok![]() Senior Member ![]() Joined: 15/09/2014 Location: United StatesPosts: 209 |
Hi All; I'm having problems transferring data from the Master to a Slave uMite. I have setup 2 programs, one for the Master the other for the Slave. As far as I can tell, only a few characters can be sent before a kind of reset occurs. 1. This has the effect of choking on the first few characters. 2. Then usually the rest will be sent. 3. Lastly, a null string is reported. The best condition, (Least errors), is when: 1. I2C speed is 400KHz. 2. The Slave is running at 5MHz, (Master doesn't mater). Any faster and choking starts to happen. 3. But that pesky null string still happens. I've been trying to understand the problem for 2 weeks and have come to the conclusion that I'm an idiot or there's some kind of bug. Redrok BTW, after first loading each program do a "Goto InitializeVars". This stores some Vars which get loaded at startup. Just run them and the slave will send the Partial Strings to the terminal. ' ------------------------------------------------------------ ------------------- ' MMTstMasterStringLcd.bas ' Goto InitializeVars ' Do this once to Initialize the Stored Vars Var Restore Print "CpuSpeed=";Str$(CpuSpeed,3);" I2cSpeed=";Str$(I2cSpeed,4);" Line=";Str$(SL,2);" Position=";Str$(SP,2) Cpu CpuSpeed SAdd=&H26 Dim Msg(84) Pause 100 ' Watchdog 5000 ' Gosub SLcdClear DoAgain: Q$ = Inkey$ : If Q$ <> "" Then Gosub Setup Lcdout$ = Right$("0"+Str$(SL),2) + Right$("0"+Str$(SP),2) + Lcdst$ Print "CILPSU";Str$(CpuSpeed,3);"MHz";Str$(I2cspeed,4);"KHz";Str$( SL,3);"Lin";Str$(SP,3);"Pos";Str$(Len(Lcdout$),3);"Chr ";Chr$(34);Lcdout$;Chr$(34) Gosub SLcd LLen = Len(Lcdst$) Lcdst$=Right$(Lcdst$,LLen-1)+Left$(Lcdst$,1) Pause PTime Goto DoAgain End Setup: Print "C=Cpu speed, I=I2c speed, L=Line, P=Position, S=String, U=paUse time" If Ucase$(Q$) = "C" Then Input "Cpu Speed 5..48 "; CpuSpeed : Cpu CpuSpeed If Ucase$(Q$) = "I" Then Input "I2cSpeed 10..400 "; I2cSpeed If Ucase$(Q$) = "L" Then Input "LCD Line 1 .. 4 "; SL If Ucase$(Q$) = "P" Then Input "LCD Position 1 .. 80 "; SP If Ucase$(Q$) = "S" Then Input "Input A String "; Lcdst$ : If Len(Lcdst$) = 0 then Return If Ucase$(Q$) = "U" Then Input "Input paUse time in mS "; PTime Var Save CpuSpeed, I2cSpeed, SL, SP, PTime, Lcdst$ Return ' Drive The LCD SLcd: I2C OPEN I2cSpeed, 500 I2C WRITE SAdd, 1, Len(Lcdout$), Lcdout$ If MM.I2C Then Error "Drive LCD Cmd 4" I2C CLOSE Return InitializeVars: CpuSpeed = 5 I2cSpeed = 400 SL = 1 SP = 1 PTime = 1000 Lcdst$ = "_234567_10_234567_20_234567_30_234567_40_234567_50_234567_6 0_234567_70_234567_80" ' Lcdst$ = "_234567_10_234567_20_234567_30_234567_40" ' Lcdst$ = "_234567_10_234567_20" ' Lcdst$ = "ABCDEFGHIJ" Var Save CpuSpeed, I2cSpeed, SL, SP, PTime, Lcdst$ End ' ------------------------------------------------------------ ------------------- ' MMTstSlaveStringLcd.bas ' Goto InitializeVars ' Do this once to Initialize the Stored Vars Var Restore Print "CpuSpeed =";Str$(CpuSpeed,3) Cpu CpuSpeed SAdd=&H26 Dim Msg(100) Lcd Init 4,5,6,7,2,3 ' LCD D4 D5 D6 D7 RS EN I2C SLAVE OPEN &H26, 0, 1, WriteD, ReadD DO ' WATCHDOG 10000 Q$ = Inkey$ : If Q$ <> "" Then Gosub Setup LOOP Setup: Print "C=Cpu speed" If Ucase$(Q$) = "C" Then Input "Cpu Speed 5..48 "; CpuSpeed : Cpu CpuSpeed : Var Save CpuSpeed Return ReadD: I2C SLAVE READ 84, Lcdin$, Rcvd SL = Val(Mid$(Lcdin$,1,2)) SP = Val(Mid$(Lcdin$,3,2)) If Rcvd >= 4 then Lcdst$ = Right$(Lcdin$,Rcvd-4) Print "C ";Str$(CpuSpeed,3);"MHz ";Str$(SL,3);"Lin";Str$(SP,3);"Pos";Str$(Rcvd,3);"Chr ";Chr$(34);Lcdin$;Chr$(34); If SL > 0 And SL <= 4 And SP > 0 Then Lcd SL, SP, Lcdst$ Else Print " Bad LCD Command"; ' Only send the LCD Legal Commands Lcdst$ = "" IReturn WriteD: IReturn InitializeVars: CpuSpeed = 5 Var Save CpuSpeed End ' ------------------------------------------------------------ ------------------- |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6269 |
This might be the same problem: http://www.thebackshed.com/forum/forum_posts.asp?TID=6599&PN =18 The I2C has a 256 byte circular buffer so any bytes received have to get read before the buffer overflows. Jim VK7JH MMedit |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3282 |
Hmm, a couple if things. Firstly, you do not need to do a "Goto InitializeVars" initially. Executing VAR RESTORE does not generate an error if there is nothing to restore. So you could replace "Goto InitializeVars" with "IF CpuSpeed == 0 THEN InitializeVars". But the real problem is the I2C issue and your program makes it impossible to identify just what the problem is. It requires the tester to setup a test hardware with LCD, etc then reverse engineer your program to understand what is going on. You need to distil it down to a dozen or less lines that demonstrates the issue without requiring unnecessary hardware. Then the question is, how does your demo differ from the demo code in the User Manual? (which does work) As Jim has pointed out, there is one known bug. But it does not sound like your issue. To me it sounds like noise on the I2C bus. Do you have the correct pullups? Are you using a long cable? Use an oscilloscope to see what is going on. Also try it at a reasonable speed (400KHz can be difficult to get working). Geoff Geoff Graham - http://geoffg.net |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
Just my 2c, and agree with Geoff and Jim. With respect to the 400kHz thing, it is always a good idea to run the I2C at 100kHz for a start, just so you can prove that things are working as expected - slow down your bus, and see if the problem fixes itself. 400kHz I2C does work fine, but you have to respect some rules(short as possible data and clock lines, and have a ground wire between data lines) - see page 61 of the MicroMite manual: [quote] When running the I2C bus atabove 150 kHzthe cabling between the devices becomes important. Ideally the cables should be as short as possible (to reduce capacitance) and also the data and clock lines should not run next to each other but have a ground wire between them (to reduce crosstalk). If the data line is not stable when the clock is high, or the clock line is jittery, the I2C peripherals can get "confused" and end up locking the bus (normally by holding the clock line low). If you do not need the higher speeds then operating at 100 kHz is the safest choice.[/quote] Smoke makes things work. When the smoke gets out, it stops! |
||||
redrok![]() Senior Member ![]() Joined: 15/09/2014 Location: United StatesPosts: 209 |
Hi All; I'm having problems transferring data from the Master to a Slave uMite. I have setup 2 programs, one for the Master the other for the Slave. As far as I can tell, only a few characters can be sent before a kind of reset occurs. 1. This has the effect of choking on the first few characters. 2. Then usually the rest will be sent. 3. Lastly, a null string is reported. The best condition, (Least errors), is when: 1. I2C speed is 400KHz. 2. The Slave is running at 5MHz, (Master doesn't mater). Any faster and choking starts to happen. 3. But that pesky null string still happens. I've been trying to understand the problem for 2 weeks and have come to the conclusion that I'm an idiot or there's some kind of bug. Redrok BTW, after first loading each program do a "Goto InitializeVars". This stores some Vars which get loaded at startup. ' ------------------------------------------------------------ ------------------- ' MMTstMasterStringLcd.bas ' Goto InitializeVars ' Do this once to Initialize the Stored Vars Var Restore Print "CpuSpeed=";Str$(CpuSpeed,3);" I2cSpeed=";Str$(I2cSpeed,4);" Line=";Str$(SL,2);" Position=";Str$(SP,2) Cpu CpuSpeed SAdd=&H26 Dim Msg(84) Pause 100 ' Watchdog 5000 ' Gosub SLcdClear DoAgain: Q$ = Inkey$ : If Q$ <> "" Then Gosub Setup Lcdout$ = Right$("0"+Str$(SL),2) + Right$("0"+Str$(SP),2) + Lcdst$ Print "CILPSU";Str$(CpuSpeed,3);"MHz";Str$(I2cspeed,4);"KHz";Str$( SL,3);"Lin";Str$(SP,3);"Pos";Str$(Len(Lcdout$),3);"Chr ";Chr$(34);Lcdout$;Chr$(34) Gosub SLcd LLen = Len(Lcdst$) Lcdst$=Right$(Lcdst$,LLen-1)+Left$(Lcdst$,1) Pause PTime Goto DoAgain End Setup: Print "C=Cpu speed, I=I2c speed, L=Line, P=Position, S=String, U=paUse time" If Ucase$(Q$) = "C" Then Input "Cpu Speed 5..48 "; CpuSpeed : Cpu CpuSpeed If Ucase$(Q$) = "I" Then Input "I2cSpeed 10..400 "; I2cSpeed If Ucase$(Q$) = "L" Then Input "LCD Line 1 .. 4 "; SL If Ucase$(Q$) = "P" Then Input "LCD Position 1 .. 80 "; SP If Ucase$(Q$) = "S" Then Input "Input A String "; Lcdst$ : If Len(Lcdst$) = 0 then Return If Ucase$(Q$) = "U" Then Input "Input paUse time in mS "; PTime Var Save CpuSpeed, I2cSpeed, SL, SP, PTime, Lcdst$ Return ' Drive The LCD SLcd: I2C OPEN I2cSpeed, 500 I2C WRITE SAdd, 1, Len(Lcdout$), Lcdout$ If MM.I2C Then Error "Drive LCD Cmd 4" I2C CLOSE Return InitializeVars: CpuSpeed = 5 I2cSpeed = 400 SL = 1 SP = 1 PTime = 1000 Lcdst$ = "_234567_10_234567_20_234567_30_234567_40_234567_50_234567_6 0_234567_70_234567_80" ' Lcdst$ = "_234567_10_234567_20_234567_30_234567_40" ' Lcdst$ = "_234567_10_234567_20" ' Lcdst$ = "ABCDEFGHIJ" Var Save CpuSpeed, I2cSpeed, SL, SP, PTime, Lcdst$ End ' ------------------------------------------------------------ ------------------- ' MMTstSlaveStringLcd.bas ' Goto InitializeVars ' Do this once to Initialize the Stored Vars Var Restore Print "CpuSpeed =";Str$(CpuSpeed,3) Cpu CpuSpeed SAdd=&H26 Dim Msg(100) Lcd Init 4,5,6,7,2,3 ' LCD D4 D5 D6 D7 RS EN I2C SLAVE OPEN &H26, 0, 1, WriteD, ReadD DO ' WATCHDOG 10000 Q$ = Inkey$ : If Q$ <> "" Then Gosub Setup LOOP Setup: Print "C=Cpu speed" If Ucase$(Q$) = "C" Then Input "Cpu Speed 5..48 "; CpuSpeed : Cpu CpuSpeed : Var Save CpuSpeed Return ReadD: I2C SLAVE READ 84, Lcdin$, Rcvd SL = Val(Mid$(Lcdin$,1,2)) SP = Val(Mid$(Lcdin$,3,2)) If Rcvd >= 4 then Lcdst$ = Right$(Lcdin$,Rcvd-4) Print "C ";Str$(CpuSpeed,3);"MHz ";Str$(SL,3);"Lin";Str$(SP,3);"Pos";Str$(Rcvd,3);"Chr ";Chr$(34);Lcdin$;Chr$(34); If SL > 0 And SL <= 4 And SP > 0 Then Lcd SL, SP, Lcdst$ Else Print " Bad LCD Command"; ' Only send the LCD Legal Commands Lcdst$ = "" IReturn WriteD: IReturn InitializeVars: CpuSpeed = 5 Var Save CpuSpeed End ' ------------------------------------------------------------ ------------------- Of course. I just wanted to be complete so others could reproduce the problem. As with all the "Saved Vars" one really only has to do them once, or at least only when they are changed. In this "Testing" phase I needed to be able to quickly change them, more or less, on the fly. Actually, the LCD part is not failing at all, except when passed bad parameters. Just comment out, in the Slave Program, Lines 8, 9, and 26, the 3 lines that operate the LCD. All data that would be sent to the LCD is echoed to the console so I can see what is going on. I'm running TeraTerm with a single RS-232 to USB interface. I added a DPDT switch in the RS-232 lines so I could easily switch between the Master & Slave consoles. This works well as I can quickly program each uMite and monitor their consoles. I formatted each uMite output to the consoles so both Master & Slave data line up. This way it is easy to compare the two outputs. Ok, The problem is almost certainly in the Slave lines 20..29. This is where the I2C bytes are being caught from the bus. I'm using an I2C sniffer, that cool tiny scope by Gabotronics called the XProtoLab to monitor the I2C bus. Every byte the Master sends is correct in every detail. Therefore, I think the problem must be in the Slave interrupt routine. A bit more about operating the programs: 1. Once running the Master and Slave each operate on a simple single Inkey$ interface. 2. The Master commands are "CILPSU" C=Cpuspeed I=I2cspeed L=lcdLine P=lcdPosition S=change the String U=paUse to change the rate strings packets are sent. 3. The Slave commands are "C " C=Cpuspeed. 4. Once a command changes a parameter it is saved using Var Save. Each time a reset occurs the Saved Vars are restored. This makes it convenient to run through basic operating parameters. I think I copied everything correctly. In the beginning I had tried many things just to get it going and settled on the Slave running at 5MHz and and the I2C at 400KHz. The pullups are 1KOhm to increase the rise times, cable length is about 12", and another 18" stub to the Sniffer. My good scope shows clean transitions and nearly zero cross talk. That's the unusual problem!!! Here is my Theory Something happens when a packet is sent. Apparently there is a limited time, or number of clock cycles, before the I2C chokes. The faster the I2C runs more of the packet is accepted before it chokes. The slower the uMite runs more of the packet is accepted before it chokes. Here are a few examples: 5MHz 400KHz 8600 Clocks: C 5MHz 1Lin 1Pos 84Chr "0101_234567_60_234567_70_234567_80_234567_10_234567_20_2345 67_30_234567_40_234567_50" C 5MHz 0Lin 0Pos 0Chr "" Bad LCD Command 5MHz 200KHz 10600 Clocks: C 5MHz 1Lin 1Pos 51Chr "0101234567_20_234567_30_234567_40_234567_50_234567_" C 5MHz 60Lin 0Pos 33Chr "60_234567_70_234567_80_234567_10_" Bad LCD Command 5MHz 100KHz 13600 Clocks: C 5MHz 1Lin 1Pos 32Chr "0101234567_40_234567_50_234567_6" C 5MHz 0Lin 23Pos 52Chr "0_234567_70_234567_80_234567_10_234567_20_234567_30_" Bad LCD Command 5MHz 20KHz 14000 Clocks: C 5MHz 1Lin 1Pos 5Chr "01012" C 5MHz 34Lin 56Pos 69Chr "34567_70_234567_80_234567_10_234567_20_234567_30_234567_40_ 234567_50_" Bad LCD Command C 5MHz 23Lin 45Pos 10Chr "234567_60_" Bad LCD Command 5MHz 10KHz 20000 Clocks: C 5MHz 1Lin 0Pos 3Chr "010" Bad LCD Command C 5MHz 14Lin 56Pos 29Chr "14567_40_234567_50_234567_60_" Bad LCD Command C 5MHz 23Lin 45Pos 38Chr "234567_70_234567_80_234567_10_234567_2" Bad LCD Command C 5MHz 0Lin 23Pos 14Chr "0_234567_30_23" Bad LCD Command 10MHz 400KHz 6200 Clocks: C 10MHz 1Lin 1Pos 29Chr "0101_10_234567_20_234567_30_2" C 10MHz 34Lin 56Pos 55Chr "34567_40_234567_50_234567_60_234567_70_234567_80_234567" Bad LCD Command 20MHz 400KHz 4800 Clocks: C 20MHz 1Lin 1Pos 10Chr "0101_20_23" C 20MHz 45Lin 67Pos 74Chr "4567_30_234567_40_234567_50_234567_60_234567_70_234567_80_2 34567_10_234567" Bad LCD Command 40MHz 400KHz 6400 Clocks: C 40MHz 1Lin 1Pos 6Chr "010123" C 40MHz 45Lin 67Pos 78Chr "4567_10_234567_20_234567_30_234567_40_234567_50_234567_60_2 34567_70_234567_80_" Bad LCD Command So the time to choke is: Proportional to I2cSpeed and inversely proportional to CpuSpeed As a guess: Since each packet contains 86 bytes (1 Address + 1 Length + 84 String characters) Clock cycles to first choke is about: (6Chars + 2Chars) * 8 Bits/Char = 64bits 64bits / 400K bits/S = 0.00016 Seconds 40MHz = 40M Clocks/S 0.00016S * 40M Clocks/S = 6400 Clocks Or ((6Chars + 2Chars) * 8Bits/Char) * 40MClocks/S / (400KBits/S) = 6400Clocks These Clock times probably have a bunch of error to them but there seems to be a trend over a wide range. Note! There may be 2 to 4 output lines all of which faithfully and accurately show all 84 characters with no errors. This shows that the I2C bus doesn't have any noise problems. One would expect some errors if it was noisy, but there aren't any. So, what do you think is the problem? I hope I have explained this enough. |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6269 |
Try putting a PAUSE in at the beginning of the rec interrupt routine ReadD:
PAUSE 20 I2C SLAVE READ 84, Lcdin$, Rcvd SL = Val(Mid$(Lcdin$,1,2)) SP = Val(Mid$(Lcdin$,3,2)) .... The interrupt is triggered as soon as the first bytes are received but it takes time to receive all 84 bytes. If the value of Rcvd is less than expected, you need a longer delay. Instead of a delay, you could check Rcvd and go back and read again until you have all the data. Start with the delay. Jim VK7JH MMedit |
||||
redrok![]() Senior Member ![]() Joined: 15/09/2014 Location: United StatesPosts: 209 |
Hi TassyJim; That worked nicely. Although I set it to 100mS to cover all the bases. Ok, I get it that it takes time to read all the data. But, why does MMBasic move on to the next command in the interrupt routine before the I2C command is finished receiving all its data? How does that work? How can you tell if all the characters have come in if the quantity to be received are not known? I do know the maximum number of characters though. I could add a preamble to the text string that says how many more characters are to be sent I suppose. Redrok |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
How do you specify the uM slave bus speed? You can set the master speed, but there is no option in the slave commands for telling MMBASIC what speed bus it has. Perhaps the slave commands default to 100kHz speed or something, and if that is the case, then setting a faster master speed would no doubt cause garbled comms between the two. I am playing with this idea at the moment.... Smoke makes things work. When the smoke gets out, it stops! |
||||
BobD![]() Guru ![]() Joined: 07/12/2011 Location: AustraliaPosts: 935 |
I2C slave speed is just that. It is a slave to the master in clock speed also. It syncs on the clock provided by the master. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
Ahhhhh - understand - thanks. ![]() In my experiments thus far, I have got no results at all at 400kHz speed, but am getting results at 100kHz. MASTER: [code] I2C open 100,100 D$="12345678901234567890123456789012345678901234567890" D$=D$+Chr$(13) I2C write &B1010101,0,Len(D$),D$ I2C read &B1010101,0,1,B Print Chr$(B):D$="" End [/code] SLAVE: [code] I2C slave open &B1010101,0,0,TXD,RXD Do:Loop TXD: I2C slave write 1,75 Pause 50 IReturn RXD: Do I2C slave read 1,B,N D$=D$+Chr$(B) If B=13 Then Exit Do Loop Print D$:D$="" Pause 50 IReturn [/code] I have a feeling, that when used in a master/slave arrangement like this with two uM chips, you may well have to send data byte-at-a-time with acknowledge rather then just throwing the string at it. I am about to play with that idea now. Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6269 |
The I2C command has no idea how much data is arriving, only the amount you want to read. I2C can be treated a lot like RS232 data. If you know how many bytes are coming in, you can wait for that many but you need to consider the case of transmission being interrupted. If the I2C routine waited for the number of bytes you have specified (84 in your case) the program will hang if fewer that 84 arrived. The Rcvd variable gives you the actual number of bytes received without the risk of program stalling. You could read one character at a time and check for an end of line or similar or check the Rcvd value and if it is less than the number you wanted, go back and read again. This is quicker than setting a long delay but you still need to cover the loss of all transmission. Jim VK7JH MMedit |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
I am able to get reliable results with the clock set to 10kHz. Any faster then this, and the comms are garbled. This is byte-at-a-time writing. Master sends a byte, then waits for slave to acknowledge, then sends another, till it runs into a CR, then it stops. The tinkering continues.... ![]() EDIT: OK, I have it working now right up to 400kHz. MASTER: [code] I2C open 400,100 D$="The quick brown fox jumps over the lazy dog." D$=D$+Chr$(13) For X=1 To Len(D$) I2C write &B1010101,0,1,Asc(Mid$(d$,x,1)) I2C read &B1010101,0,1,B 'Wait for slave to acknowledge byte Next Print Chr$(B) End [/code] SLAVE: [code] I2C slave open &B1010101,0,0,TXD,RXD Do If B=13 Then D$=D$+Chr$(13):Print D$:D$="":B=0 Loop TXD: I2C slave write 1,75 IReturn RXD: I2C slave read 1,B,N D$=D$+Chr$(B) IReturn [/code] Apart from one lost character at the very beginning, all is as expected, even up at 400kHz. I will now make D$ much longer and see what happens, but I expect that slave-acknowledge must be used in the slave uM, or you will get nowhere - the master throws the data at the slave, and the slave is not fast enough to process an incoming byte, and get back to listening again, before the master has sent more data. Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
Working at 400kHz with a string 224 bytes long. MASTER: [code] I2C open 400,100 EOL$=Chr$(13) + Chr$(10) DA$="The quick brown fox jumps over the lazy dog." + EOL$ DB$="An expert is someone who will tell you why you can't do something." DB$=DB$+EOL$ DC$="Forgive me if I am being thicker then the offspring of a" + EOL$ DD$="village idiot and a TV weather girl...(Blackadder)" D$=Chr$(85)+DA$+DB$+DC$+DD$+EOL$ For X=1 To Len(D$) I2C write &B1010101,1,1,Asc(Mid$(d$,x,1)) I2C read &B1010101,0,1,B 'Wait for slave to acknowledge byte Next I2C write &B1010101,0,1,27 'Send end-of-data byte Print Chr$(B) End [/code] SLAVE: [code] I2C slave open &B1010101,0,0,TXD,RXD Do If B=27 Then Print D$:D$="":B=0 Loop TXD: I2C slave write 1,75 IReturn RXD: I2C slave read 1,B,N D$=D$+Chr$(B) IReturn [/code] ![]() We're always missing the first byte of the message - not sure why at this stage, but if it was consistent, then a dummy byte could always be used for byte one. EDIT: I have fixed the missing byte one, by adding a capital U to the start of the data string, as a data-slicer sync kind of thing. No missing characters now. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6269 |
Another way to receive data when the length of the string is unknown. Theory: Once the data starts coming it arrives without any delays. This means that you can tell the data has finished when there is no data in a brief time. Data is read from the buffer in short chunks and added to record$ The size of the PAUSE depends on the I2C transmission rate. ReadD:
' received a message record$="" pause 1 ' it takes 500 uS for 5 bytes at 100k do I2C SLAVE READ 255, rx$, rcvd ' try to read a lot more than expecting record$=record$+rx$ pause 1 loop until rcvd = 0 'keep looping until no more data received IReturn Not tested. Jim VK7JH MMedit |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
Will experiment with that idea today. Any idea why I should need the capital U sync byte to make my code work? Is there an internal I2C data buffer in the uM and if so, what is it's size? There is mention of the I2C bug that is known about. Can someone link me to that, so I can read about it. I remember reading in posts about the bug, but never bothered to actually read up on what the bug was. Smoke makes things work. When the smoke gets out, it stops! |
||||
viscomjim Guru ![]() Joined: 08/01/2014 Location: United StatesPosts: 925 |
Hi Grogster, take a look here. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9589 |
Thanks. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |