![]() |
Forum Index : Microcontroller and PC projects : Sub is auto-erasing results....
Author | Message | ||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9502 |
I have been playing with this most of the afternoon, and I can't get the results I want from the sub. Here is the main code: (bear in mind, this is just for testing purposes, so is only supposed to return the expected result, not actually DO anything with those results) [code] FW: FRAM (1,5000,"Hello.") Print M,A,D$ End FR: FRAM (0,5000) Print M,A,D$ End [/code] And the subroutine: [code] Sub FRAM (M,A,D$) 'Mode, Address and Data parimeters If M<0 Or M>1 Then FRAM_FLAG=1 I2C open 400,100 FRAM_FLAG=0 If M=1 Then A2=A+Len(D$):Y1=1:A3=A2+1 For Y=A To A2 I2C write &B1010000,0,3,Y\256,Y Mod 256,Asc(Mid$(D$,Y1,1)) Y1=Y1+1 Next Y I2C write &B1010000,0,3,A3\256,A3 Mod 256,13 'CR marker I2C Close EndIf If M=0 Then D$="" I2C write &B1010000,0,2,A\256,A Mod 256 'Set FRAM start address Do I2C read &B1010000,1,1,B 'Suck a byte from FRAM and hold onto bus D$=D$+Chr$(B) If B=13 Then Exit Do Loop I2C Close EndIf End Sub [/code] From the command prompt, if I enter GOTO FW or GOTO FR, BOTH return zeros as the results, which is not what is expected - it should be 1 5000 Hello. for the FW test, and 0 5000 Hello. for the other test. Now, if I change the sub to print the parameters as it moves through the sub, they are there as expected, when expected, but they are auto-zeroed once the sub exits - I don't get what I am doing wrong. ![]() For example, if I use this code here for the sub: [code] Sub FRAM (M,A,D$) 'Mode, Address and Data parimeters If M<0 Or M>1 Then FRAM_FLAG=1 I2C open 400,100 FRAM_FLAG=0 If M=1 Then A2=A+Len(D$):Y1=1:A3=A2+1 For Y=A To A2 I2C write &B1010000,0,3,Y\256,Y Mod 256,Asc(Mid$(D$,Y1,1)) Y1=Y1+1 Next Y I2C write &B1010000,0,3,A3\256,A3 Mod 256,13 'CR marker I2C Close Print M,A,D$ EndIf If M=0 Then D$="" I2C write &B1010000,0,2,A\256,A Mod 256 'Set FRAM start address Do I2C read &B1010000,1,1,B 'Suck a byte from FRAM and hold onto bus D$=D$+Chr$(B) If B=13 Then Exit Do Loop Print M,A,D$ I2C Close EndIf End Sub [/code] ...then M=1 or 0 depending on FW or FR, and A=5000, and D$="Hello." But the second the sub ends, and returns to the next line of either FW or FR, the values are all zero again. ![]() ![]() Can anyone help me work out what I am doing wrong? EDIT: FECK, FECK, FECK, FECK!!!! From page 28 of the manual: [quote] The arguments act like ordinary variables but they exist only within the subroutine and will vanish when the subroutine ends.[/quote] I was still thinking in MaxiMite mode, which does not forget variables, and they are available again OUTSIDE the sub, but the MicroMite obviously does not do this, for memory reasons. ![]() So, the question now becomes, is there any way to change that behaviour? ...I guess on the full-size MaxiMite, this problem would not surface, and I would get the results I wanted. Interestingly, I made a very simple test sub: [code] Sub XXX (A,B,C) A=A*2:B=B*2:C=C*2 End Sub [/code] ...and called it with: [code] ONE: XXX (2,4,6) Print A,B,C End [/code] ...and I get the results back from this one: 2,8,12...... ![]() ![]() ![]() ![]() ![]() ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9502 |
OK - Problem fixed! NEW caller test routines: [code] FW: FRAM (1,5000,"Hello.") Print M1,A1,D1$ End FR: FRAM (0,5000) Print M1,A1,D1$ End [/code] ...and NEW main sub: [code] Sub FRAM (M,A,D$) 'Mode, Address and Data parimeters If M<0 Or M>1 Then FRAM_FLAG=1 I2C open 400,100 FRAM_FLAG=0 If M=1 Then A2=A+Len(D$):Y1=1:A3=A2+1 For Y=A To A2 I2C write &B1010000,0,3,Y\256,Y Mod 256,Asc(Mid$(D$,Y1,1)) Y1=Y1+1 Next Y I2C write &B1010000,0,3,A3\256,A3 Mod 256,13 'CR marker M1=M:A1=A:D1$=D$ I2C Close EndIf If M=0 Then D$="" I2C write &B1010000,0,2,A\256,A Mod 256 'Set FRAM start address Do I2C read &B1010000,1,1,B 'Suck a byte from FRAM and hold onto bus D$=D$+Chr$(B) If B=13 Then Exit Do Loop M1=M:A1=A:D1$=D$ I2C Close EndIf End Sub [/code] Make a copy of the local argument variables, and check THESE after the sub ends. You keep on learning new tricks in this game of programming...... ![]() ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6224 |
In the subroutine: If M<0 Or M>1 Then FRAM_FLAG=1
I2C open 400,100 FRAM_FLAG=0 FRAM_FLAG will always end up as zero so setting it to 1 in the first line is no use. But you don't seem to use it anywhere anyway...... Jim VK7JH MMedit |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9502 |
FRAM_FLAG is set to one, if the M parameter is less then zero, or greater then 1. I have tested that, and it seems to work. The idea being that if you try to select a mode that is not 0 or 1, the sub exits with this flag set. The same thing applies to FRAM addresses that are less then one, or more then 32767(address zero is not used). The code example Jim quotes was missing the :End Sub on the end of the line - my mistake there! Updated callers: [code] FW: FRAM (1,5000,"Hello.") Print M,A,D$ If FRAM_BA=1 Then Print "Bad write address." End FR: FRAM (0,5000) Print M,A,D$ If FRAM_BA=1 Then Print "Bad read address." If FRAM_BM=1 Then Print "Bad mode." End [/code] Updated sub: [code] Sub FRAM (M1,A1,D1$) 'Mode, Address and Data parameters If M1<0 Or M1>1 Then FRAM_BM=1:End Sub If A1<1 Or A1>32767 Then FRAM_BA=1:End Sub I2C open 400,100 FRAM_BM=0:FRAM_BA=0 If M1=1 Then A2=A1+Len(D1$):Y1=1:A3=A2+1 For Y=A1 To A2 I2C write &B1010000,0,3,Y\256,Y Mod 256,Asc(Mid$(D1$,Y1,1)) Y1=Y1+1 Next Y I2C write &B1010000,0,3,A3\256,A3 Mod 256,13 'CR marker M=M1:A=A1:D$=D1$ I2C Close EndIf If M=0 Then D$="" I2C write &B1010000,0,2,A1\256,A1 Mod 256 'Set FRAM start address Do I2C read &B1010000,1,1,B 'Suck a byte from FRAM and hold onto bus D$=D$+Chr$(B) If B=13 Then Exit Do Loop M=M1:A=A1 I2C Close EndIf End Sub [/code] This version swaps around what parameter variables are passed to the sub, so that the more "Normal" variables can be shown at the end of the sub. Smoke makes things work. When the smoke gets out, it stops! |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3272 |
Sorry but the Maximite and Micromite are exactly the same in this regard. The variables in the parameter list of a subroutine are always local to the sub. BUT, if you used variables when you called the subroutine then any changes to the local variables will be copied back to the variables used when you called the sub. For example: X = 1 Y = 5000 z$ = "Hello." FRAM (X, Y, Z$) Print X,Y,Z$ Would give you what you wanted as X, Y and Z$ would be updated to reflect any changes made to M, A and D$ in the sub. This is a handy way of getting data out of a sub but passing data by reference (which this is) can get confusing (I wish that I never implemented it). Perhaps global variables would be simpler and less confusing. Geoff Geoff Graham - http://geoffg.net |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9502 |
I've just looked closer at my MaxiMite code, and the reason it "Appeared" to be working there, and not on the MicroMite, was that in my MaxiMite code, I don't reference the variables I want OUTSIDE the sub, in the parameter list - exactly as you say. As I was using the likes of X,Y,Z as parameters, and then changing A,B,C kind of thing, all appeared to work as expected. I made a mistake here, in that I used A,B,C as parameters, then tried to change those same variables inside the sub, so they then vanished when the sub exited - just as the manual said would happen, I just did not pick up on my mistake before I posted this flippin' thread! ![]() Human error! ![]() 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 |