PDA

View Full Version : Assigning TEXT strings to Variables/Arrays?



atomski
- 27th May 2004, 13:23
Hello everyone, Mel,

I 'm currently working on a HAM project
for my radio club involving RS-232 control
of a 434 MHz repeater transmitter. I have
a lot of data and config manus that eat up
a lot of the free space. Many HSEROUT
statements with very similar content etc.
I'd like to use something like this:
Loop:
IF Key1 = 0 THEN : I2CREAD Sda, Scl, EE_addr, B0, [STR StringVar\30] : GOSUB Msg1 : HIGH Tx
IF Key2 = 0 THEN : I2CREAD Sda, Scl, EE_addr, B0, [STR StringVar\30] : GOSUB Msg1 : LOW Tx
GOTO Loop
'*********************************
Msg1:
HSEROUT [FF,LF,CR,StringVar/30,LF,CR]
RETURN
'*********************************
My question is can I send ASCII chars
like decimal (or hex) numbers serially
via RS-232 using this method? I could
read an external eeprom, get text from
it and send it using just one HSEROUT
statement. This would cut down my
code, I guess. Ideas, suggestions?

--
Sincerest regards,

YZ7REA Vladimir M Skrbic
4N7ATV Repeater Administrator
YU7GHZ Radio Club President

Melanie
- 6th July 2004, 14:56
Heads-up Toni, although it's I2C, it can also be adaped for SPI, the theory of loading WORDS remains the same...

Here is an easy way to read a string of WORD data from an external I2C EEPROM and load into an array... (I'm assuming 24LC32/24LC64 types here as they require a WORD Address, just a minor bit of code fiddling is needed for the smaller types to determine Page and Byte addresses).

Example: Load WORD array from external EEPROM starting say at address $0C00, fifteen array elements deep (ie 15 words to be loaded)...

Variables used....

DataW var WORD [30] ' Array big enough for your needs
I2Caddress var BYTE ' Device Address
MessageAddress var WORD
' Starting Address of Data in external EEPROM
MessageLen var BYTE
' Number of WORD Array Elements to load (Min=1, Max=128)
TempA var BYTE ' Temporary BYTE Counter
TempB var BYTE ' Temporary BYTE Counter
TempC var BYTE ' Temporary BYTE Counter
TempW var WORD ' Temporary WORD Variable

.. ..

This is all you need in your program each time you want to acquire a message....

MessageAddress=$0C00 ' Starting address for data
MessageLen=15 ' Remember this is the number of WORDS to load
Gosub GetwordData ' Load from EEPROM into WORD array

.. ..

And this is the subroutine where all the work gets done... data is always loaded into the array starting at DataW(0) for the first word, and ending with DataW(MessageLen-1) for the last word.

GetWordData:
TempB=MessageLen*2-1
I2CAddress=$A0
For TempA=0 to TempB
TEMPW=MessageAddress+TempA
I2CRead SDA,SCL,I2CAddress,TempW,[TempC]
DataW.Lowbyte(TempA)=TempC
Next TempA
Return

Dont specify MessageLen bigger than your defined aray size - you won't get any error messages, but it will just happily overwrite system RAM with corresponding upredictable results.

To save even more codespace, why not have the first byte of your message define the length of the data array to load, so therefore the first byte in EEPROM can be MessageLen, then followed by your data. I'll let you figure that...

If all your messages are a constant size (as per your example) then everything of course becomes correspondingly simpler, as your program needs only to provide the message number, and the GetData subroutine can figure out where it's located.

Likewise if you're loading BYTES instead of WORDS, then again everything is simplified.

I trust this is what you wanted.

Melanie

atomski
- 7th July 2004, 07:38
Sweet! Mel, you are truly amazing! I just wish my little
gray cells would operate with such sharpness and grace
after I spend as much time programming as you have.
Thank you for a very educative example that'll help me
better understand the matter and learn how to write
space saving code.

Vladimir

TONIGALEA
- 8th July 2004, 23:41
Thanks Mel for your example
This is the first time i have tried the example out , but i am running into problems .
because the example was for an I2C eeprom and i had a 24lc128
i decided to tried and copy the the first ten words that were store in the eeprom starting at address 10 to address 28 which contains the following sequence

Eprom Values
****************************************
Addr10 500
Addr12 600
Addr14 700
Addr16 800
Addr18 900
Addr20 1000
Addr22 1100
Addr24 1200
Addr26 1300
Addr28 1400

but i am getting the following results
Addr10 5125
Addr10 30725
Addr10 62465
Addr10 22530
Addr10 48130
Addr10 8195
Addr10 33795
Addr10 59395
Addr10 19460
Addr10 45060
Addr10 5125

using my pragram below


DEFINE LOADER_USED 1 ' uses a bootloader
Include "Modedefs.Bas"


Define OSC 20
clear

' Setup Hardware for uart
DEFINE HSER_BAUD 19200
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_CLROERR 1

@ device pic16F877, HS_osc, wdt_off, pwrt_on, protect_off

' Hardware Defines
' ----------------

SCL VAR PORTC.3 ' I2C clock pin
SDA VAR PORTC.4 ' I2C data pin

' Software Defines
' ----------------
' ** Declare the Variables **
Temp VAR WORD ' General Purpose
Data_Out VAR WORD ' Data read from the Eeprom
Data_In VAR WORD ' Data written to the Eeprom
address VAR WORD ' Address

' added Software Defines
' ----------------

DataW var WORD [30] ' Array big enough for your needs
I2Caddress var BYTE ' Device Address
MessageAddress var WORD
' Starting Address of Data in external EEPROM
MessageLen var BYTE
' Number of WORD Array Elements to load (Min=1, Max=128)
TempA var BYTE ' Temporary BYTE Counter
TempB var BYTE ' Temporary BYTE Counter
TempC var BYTE ' Temporary BYTE Counter
TempW var WORD ' Temporary WORD Variable

index var byte '
'
' Initialise Hardware
' -------------------
ADCON1=7
TRISA=%00000000
TRISB=%00000000
TRISC=%10000000
TRISD=%00000000


Data_Out=0: Data_In =0: Temp =0


'WRITE SUB
'=======
for address = 0 TO 98 STEP 2 ' Loop 50 times
Data_In =Temp ' Data_In is data for EPROM
I2CWrite SDA,SCL,%10100000,address,[Data_In] ' Write each 2 location
Pause 10 ' Delay 10ms after each write
Temp =Temp + 100
Next address

HSerout [" Eprom Values " ,10,13]
HSerout [" ****************************************" ,10,13]


loop:

'This is all you need in your program each time you want to acquire a message....

MessageAddress=10 ' Starting address for data
MessageLen=10 ' Remember this is the number of WORDS to load
Gosub GetwordData ' Load from EEPROM into WORD array


'READ SUB
'=======

for index = 0 to 9
'HSerout [" Addr" ,dec address," ", dec Data_Out,10,13]
HSerout [" Addr" ,dec MessageAddress," ", dec DataW(index) ,10,13]


Pause 1000
next index
GoTo loop

End

i know i must be doing something wrong
Could you help ?

Toni

Melanie
- 9th July 2004, 01:54
Ouch, where do I start...

Again briefly, this time for lack of Battery Power on my Laptop whilst writing this in the back of a London Taxi...

As a starter, look at your WRITE SUB... by saving a WORD the way you're doing, I2CWRITE saves it Highbyte followed by Lowbyte, rather than the other way around (see PBP Manual 12CWrite). It's better to play Byte at a time. Either adjust your WRITE routine, or compensate in your read routine for this reverse order.

Melanie

TONIGALEA
- 9th July 2004, 20:35
Excellent Explanation MEL,
You were right again as you always are , it was due to the way i was writting and reading from the eeprom i made the adjustments you recommended and its magic....
I really appreciate your helping hand

Toni

The pr
DEFINE LOADER_USED 1 ' uses a bootloader
Include "Modedefs.Bas"


Define OSC 20
clear

' Setup Hardware for uart
DEFINE HSER_BAUD 19200
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_CLROERR 1

@ device pic16F877, HS_osc, wdt_off, pwrt_on, protect_off

' Hardware Defines
' ----------------

SCL VAR PORTC.3 ' I2C clock pin
SDA VAR PORTC.4 ' I2C data pin

' Software Defines
' ----------------
' ** Declare the Variables **
Temp VAR WORD ' General Purpose
Data_Out VAR WORD ' Data read from the Eeprom
Data_In VAR byte ' Data written to the Eeprom
address VAR WORD ' Address

' added Software Defines
' ----------------

DataW var WORD [20] ' Array big enough for your needs
I2Caddress var BYTE ' Device Address
MessageAddress var WORD
' Starting Address of Data in external EEPROM
MessageLen var BYTE
' Number of WORD Array Elements to load (Min=1, Max=128)
TempA var BYTE ' Temporary BYTE Counter
TempB var BYTE ' Temporary BYTE Counter
TempC var BYTE ' Temporary BYTE Counter
TempW var WORD ' Temporary WORD Variable
CounterA var word
index var byte '
'
' Initialise Hardware
' -------------------
ADCON1=7
TRISA=%00000000
TRISB=%00000000
TRISC=%10000000
TRISD=%00000000


Data_Out=0: Data_In =0: Temp =0


'WRITE SUB
'=======
for CounterA = 0 TO 98 STEP 2 ' Loop 50 times
Address=CounterA
Data_In =Temp.LowByte ' Data_In is data TO EPPROM
I2CWrite SDA,SCL,%10100000,address,[Data_In] ' Write each 2 location
Pause 10 ' Delay 10ms after each write
address = address +1
Data_In =Temp.HighByte ' Data_In is data TO EPPROM
I2CWrite SDA,SCL,%10100000,address,[Data_In] ' Write each 2 location
Pause 10 ' Delay 10ms after each write
Temp =Temp + 100
Next CounterA


HSerout [" Array Values " ,10,13]
HSerout [" ****************************************" ,10,13]
HSerout ["(0) (1) (2) (3) (4) (5) (6) (7) (8) (9)" ,10,13]

loop:

'This is all you need in your program each time you want to acquire a message....

MessageAddress=10 ' Starting address for data
MessageLen=10 ' Remember this is the number of WORDS to load
'Gosub GetwordData ' Load from EEPROM into WORD array


'READ SUB
'=======

for index = 0 to 9
Gosub GetwordData ' Load from EEPROM into WORD array
HSerout [ dec DataW(index)," " ]
Pause 1000
next index
HSerout [10,13]
GoTo loop

End



GetWordData:
TempB=MessageLen*2-1
I2CAddress=$A0
For TempA=0 to TempB
TEMPW=MessageAddress+TempA
I2CRead SDA,SCL,I2CAddress,TempW,[TempC]
DataW.lowbyte(TempA)=TempC
Next TempA
Return
ogram below
=============

Melanie
- 9th July 2004, 21:43
As a rule, if you start repeating yourself, it's time to think about a subroutine... it might use less codespace in the long run... try it...

for CounterA = 0 TO 98 STEP 2 ' Loop 50 times
Address=CounterA
Data_In =Temp.LowByte ' Data_In is data TO EPPROM
Gosub WriteByte
address = address +1
Data_In =Temp.HighByte ' Data_In is data TO EPPROM
Gosub WriteByte
Temp =Temp + 100
Next CounterA

.. ..

writeByte:
I2CWrite SDA,SCL,%10100000,address,[Data_In]
Pause 10 ' Delay 10ms after each write
Return

Here's a tip... check the Datasheet for the external EEPROM you're using... you might only need a 5mS (or less) pause...