Whilst this has also been posted to the piclist here it is for reference - and also that several hours after posting it's still somewhere 'lost in space'.
>
> Can you provide a quick example of writing data to
> code space and reading it back?
>
This is relatively simple... and there's many ways of doing this... so I'll keep it short with just one method...
The PBP command to read data from codespace is READCODE address,data.
For example 16F pics that support READCODE like the 16F876, and the 16F877 (amongst others) allow you to save and extract 14-bits of data per memory location. For those that haven't got enough fingers and toes to do the math, that gives you a range of 0-16383. Let's call this PCWord (for Program Code Word rather than a real word which is 16 bits). Naturally you define 'data' as a word if you want to grab all 14-bits, and if you define it as a byte you just get the lower 8 bits. The 'address' is also a WORD (a real 16-bit variety) and is any spot in valid codespace.
WRITING to codespace should be restricted, it's not as resilient as EEPROM and theoretically wears out quicker, but for use as sporadic storage or for giant Lookup tables, it saves on an external EEPROM if you're tight for cash or PCB Real-Estate. READING from codespace is unlimited, doesn't wear out your PIC, doesn't use any calories and can be used without restriction - so go do it.
WRITECODE is the opposite to READCODE and allows you to write to those memory locations. But it's kinda wasteful having to use WRITECode to create a 1000 word table before having to use it. Whilst WRITECODE and READCODE are the equivalents of READ and WRITE on a bigger scale, what's missing is the equivalent of the DATA statement which allows you to preset those memory locations.
For this we have to jump into some lines of Assembler which I'll teach you here...
Let's say we wish to create a 1000 word table in Program space. First choose a memory location well away from your code. So an PIC16F876/877 has 8K (8192) words of Program Codespace. If we put our data table out of the way starting at address 7190, it means we can create a program that uses up to 7190 words. Any bigger and it risks overwriting our data table.
Our Data table is created thus (note caps for CODE and DB)... and shove it at the end of your code... PLEASE NOTE that I am using PBP's Assembler mnemonics here, there are some variances for MPASM but the theory is the same.
(Note: Here on this forum, the display above will corrupted and left-justified. The CODE and DB statements must be indented and must NOT start at column 1 in your code. The left-hand edge is reserved in Assembler for Labels ONLY.)Code:Asm CODE 7190 DB 254 DB 1 DB "Hey, Beautiful" DB 254 DB 192 DB "What's Cookin?" DB 0 Endasm
This is the equivalent of sequentially storing...
Let's now read that data in and display it on our LCD... here's a couple of ways rolled into one demo program...Code:$FE,$01,"Hey, Beautiful",$FE,$C0,"What's Cookin?",0
(Download the accompanying pcode.txt file for a pretty example).Code:PCAddress var WORD PCData var BYTE DoitAgain: PCAddress=7190 ' ' Read & Display till we get a stop character ' ReadCodeLoop: READCODE PCAddress,PCData If PCData>0 then LCDOut PCData PCAddress=PCAddress+1 Goto ReadCodeLoop endif Pause 2000 ' ' Read a set number of locations ' (two in this case - to Clear the LCD) ' For PCAddress=7190 to 7191 READCODE PCAddress,PCData LCDOut PCData Next PCAddress Pause 1000 Goto DoitAgain End
There are a number of things you have to remember. So here's the rules of the game - don't disregard them or they'll come back and bite you...
1. Don't spill your data out of available memory... you'll get stacks of compiler error messages anyway. Remember, be nice, leave some space for your program. Every PCWord you steal from Program Memory is one word less you've got available in programming.
2. Remember how many data elements you've preset. If you've preset 1000 PCWords, don't access 1001 because it probably won't contain things relevant to your data table.
3. When using WRITECODE, if you access the WRONG memory locations, you run the risk of corrupting your program code. Stick rigidly to the addresses for your data. Remember the golden rule of programming... "if you put it into memory, remember where you put it".
The downside... OK there's no free lunch (unless you're buying it for me). No gain without pain, and this little niggle is significant...
4. Whilst you can WRITECODE with 14 bits, and READCODE with 14 bits, you can't preset 14-bits with the assembler DB statement. You can ONLY preset 8 bits, and the upper 6 bits (remember 14-bits for our PCWord) will always be preset to %110100. Hey, I didn't write the assemblers - so don't lay this one on me. Consider the DB statement as standing for 'Data Byte'. BYTE being the appropriate thing to notice. So each 8-bit BYTE you store, gets saved as a 14-bit PCWord... example...
You want to save a value of ONE...
DB 1
That memory location will actually contain in 14-bits...
11010000000001
You can however within your PBP Program do this...
and that address will have in 14-bits...Code:MyWord var Word MyWord=1 WRITECODE address,MyWord
00000000000001
(when reading or writing with WRITECODE and READCODE into/from a 16-bit word, the upper two bits should always be considered zero)...
You might think that instead of using the DB statement, I'll go and use DW (Data Word rather than Data Byte)... but look what happens...
You would think you would get 00000000000001 stored into location 7190... but hey, they've thought of that and you actually get the lower 8-bits stored into location 7190, and the upper eight bits (yes of a whole 16-bit word) gets stored in location 7191. The upper six bits of both memory locations stubbornly still get preset to %110100. Like I said, don't lay this on me.Code:CODE 7190 DW 1
Finally... if there is such a thing as 'finally'...
5. Playing with the CODE directive (as in example CODE 7190), kinda screws the compiler reporting the true value of the words used in your program. If you need to know the actual size of your compiled program (useful to determine how much Program Code space it's used), just remove the Asm...Endasm section and compile. Drop it back in for your final program. Some folks will argue that the Asm...Endasm section should be lower down in your code and just jump over it. Sure you could do that. Personally I like to keep the data blocks that I'm tampering with well away from my Program Code.
The appended file is a ready-to-run demonstrator. Go create and have fun.
So I lied about keeping it short...
Melanie
Bookmarks