Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Squeezing the most out of your PIC

Status
Not open for further replies.

richacm

New Member
Hi,

I've been doing rather a lot with the PIC16F877A I am using and find I am having to redo bits and peices because I am running out of memory. When I compile the program I normally see I have about 9% free of ROM and about 45% free of RAM.

The other day I purchased some 64K Eeprom's which I interface with using I2C. I only needed 1 and had to buy 10 so I now have 9 lying around which I am not using at present. How easy is it to stick some of the PIC program on the External EEprom and then load it in to RAM to execute? I figure I may as well use up the 45% of RAM that is free if I can.

I figured that the logic of the PIC program would be:
1. Initialise I2C
2. Read byte from Eeprom
3. Store byte to RAM
4. Repeat 2 and 3 until all EEprom read
5. Continue executing ROM
6. Execute RAM instructions when needed.

Is this possible? Has anyone done it?

Thanks heaps,

Craig
 
Craig,

May I ask what language you're using Sir? Just curious, because.... I just started playing with BoostC and find it extremely interesting when I look at the assembly code it generates. It's reasonably efficient but not optimized nearly as well as it could be.

Mike
 
Last edited:
Craig,

May I ask what language you're using Sir? Just curious, because.... I just started playing with BoostC and find it extremely interesting when I look at the assembly code it generates. It's reasonably efficient but not optimized nearly as well as it could be.

Mike

Mike, I'm using mikroBasic. I think it is pretty inefficient in its compilation but it works extremely well.

Craig
 
PICs are Harvard architecture. They won't execute code in RAM.

But you might be able to do overlays by reading off your EEPROM and writing to Flash and then executing. Try it! I'd love to hear if you can make it work.

Writing to flash is no walk in the park. It's slow and there's a limited write endurance here. There's a small risk that the write will go wrong (electrical glitch?) and overwrite the program space that wasn't supposed to change. On the whole, loading and burning and reburning ROM simply to increase the code space is a no-no. Because after all, rarely do we do one block of code and change to another just once every 5 min or whatever.

The solution's real simple actually: get a bigger part! The 18F series ranges all the way up to "downright huge".
 
Yes, you can do something similar, but it will be slow. You will be interpreting the tokenized commands on the fly and loading arguments into the W register and then calling an ersatz command. Expect to lose 90% to 99.99% of your speed when working like this.
 
When people run out of programming space it is normally because they have badly written code or a lot of data. If it's the later then storing the data in EEPROM will solve the problem. If it's the former then getting someone to look over your code and suggesting different ways to write it would be beneficial. If it's neither then get a bigger chip.

If you have code like,
Code:
    PutLCD("H")
    PutLCD("e")
    PutLCD("l")
    PutLCD("l")
Then we have found the problem.

Mike.
 
Cheers. My code is quite simple actually, it just has a lot of functions.

Web Server, ADC, LCD display, I2C components. I'm using standard libraries from mikroBasic and I think some of them are a bit heavy software wise.

Craig
 
I'm guessing that the web server is the culprit. Can you store the data on a serial EEPROM?

Talking about what you can squeeze out of a Pic, a while ago I was playing with the free version of Swordfish Basic and wrote a little program that read 3 DS1820s (OW) + a DS1307 (I²C) and displayed them on a LCD. The total code was 2150 instructions long.

This was the code for anyone curious.
Code:
{
*****************************************************************************
*  Name    : Test1320.BAS                                                   *
*  Author  : Mike WEbb                                                      *
*  Notice  : Copyright (c) None                                             *
*          : No  Rights Reserved                                            *
*  Date    : 3/3/2008                                                       *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
Device = 18F1320
Clock = 8               // 4MHz clock

Config OSC = INTIO2, WDT = OFF, LVP = OFF

#option LCD_DATA = PORTB.0
#option LCD_RS = PORTB.5
#option LCD_EN = PORTB.4
#option LCD_COMMAND_US = 2000 
#option LCD_DATA_US = 50 
#option LCD_INIT_DELAY = 100

#option I2C_SCL = PORTA.3
#option I2C_SDA = PORTA.4

Include "18F1320.bas"
Include "init.bas"
Include "LCD.bas" 
Include "OW.bas"    
Include "Convert.bas"   
Include "MyModule.bas"   
Include "SI2C.bas"             

Dim Command As Byte
Dim DeviceCode As Byte
Dim Hours As Byte
Dim Test As Word
Const Degrees(8) As Byte = ($0E,$0A,$0E,$00,$00,$00,$00,$00)
OSCCON = $70            // 4 MHz clock
ADCON1  = $7f
Cls

SI2C.Initialize()
LCD.Write(Degrees)

While True
    StartConvert(PORTA.0)
    StartConvert(PORTA.1)
    StartConvert(PORTA.2)
    LCD.WriteAt(1,1,"T1=",DecToStr(GetTemperature(PORTA.0)/2),0,"C ")
    LCD.WriteAt(1,9,"T2=",DecToStr(GetTemperature(PORTA.1)/2),0,"C  ")
    LCD.WriteAt(2,1,"T3=",DecToStr(GetTemperature(PORTA.2)/2),0,"C ")
    Hours=ReadDS1307(2)
    If Hours.6=1 Then
        Hours=Hours And $1f
    EndIf
    WriteBCD(Hours)
    LCD.Write(":")    
    WriteBCD(ReadDS1307(1))
    LCD.Write(":")    
    WriteBCD(ReadDS1307(0))
Wend                            // repeat forever 
End

If you can switch to an 18 series chip then I would highly recommend SwordFish.

Mike.
 
I suspect there's a compromise somewhere between a PIC with gobs of memory and writing more efficient code.

Coming from an assembly language background and preference (fading fast, btw) I'm intrigued by the code the various compilers generate. Of the two instructions below, BoostC (16F') produces 4 assembly instructions for the first one and 2 assembly instructions for the second one.
Code:
nyb = nyb << 1;

nyb <<= 1;
Besides some of those bloated libraries Mike (pommie) mentions, I've noticed that LCD string data can get out of hand sometimes.

Mike
 
3v0,

I doubt it's a bug and suspect it's just the way their compiler parses and evaluates the instruction and pushes out "building blocks" of code.

Even the excellent Swordfish BASIC compiler has nits. It promotes an 8 bit variable to a 16 bit temp' when the variable is being used to index an array with dimensioning that doesn't really require more than an 8 bit value (example below).

Code:
DIM Display(16) As LongWord ' 64 bytes
DIM i As Byte               ' values of 0..15

Display(i).byte0 = 0
'
'  Swordfish generates the following code for the previous line
'
'   movff   i,temp_lo       ; temp_lo = 0,1,2,3,4,5,6..15
'   clrf    temp_hi         ;
'   clrc                    ;
'   rlcf    temp_lo,F       ; temp_lo = 0,2,4,6,8,10,12..30
'   rlcf    temp_hi,F       ;
'   rlcf    temp_lo,F       ; temp_lo = 0,4,8,12,16,20,24..60
'   rlcf    temp_hi,F       ;
'   lfsr    0,Display       ;
'   movf    temp_lo,W       ;
'   addwf   FSR0L,F         ;
'   movf    temp_hi,W       ;
'   addwfc  FSR0H,F         ;
'   clrf    INDF0           ;
'
'  where I think I might do it like this
'
'   lfsr    0,Display       ; 8 words
'   rlncf   i,W             ;
'   rlncf   WREG,W          ;
'   addwf   FSR0L,F         ;
'   movlw   0               ;
'   addwfc  FSR0H,F         ;
'   clrf    INDF0           ;
Couldn't the compiler test to see if the argument_array_width multiplied by the argument_array_dimension is less than or equal to an 8 bit value and use the second bit of code to setup FSR0 when the index variable is type Byte?

Mike
 
I read my post and it sure sounds like I said it was a bug. When I wrote it I was thinking that it may get more attention if it went in as a bug then as an enhancement request, WIBN. Which it is.

Regress:
The compilers for the HP64000 system (uC emulator system) had three bugs that keep reoccurring. A friend found that you had to have 2 of the 3 bugs present in the system. Fixing 1 ensured the other two would be broken. The products were getting long in the tooth so he fixed the worst bug and issued workarounds for the other two. The test suite was modified to show the 2 bugs as OK. Another 2 bugs became a feature.
 
Reminds me of a joke:

"Engineering revision R23127-2 fixes the two new bugs that were introduced in Engineering revision R23127-1."
 
Have you looked at the 24FJ series of 16 bits PICs? The program and data space is much larger, and there is a lot more processing power. The downsides are 3.3 V only and there is no DIL version bigger than 28 pins.

The C compiler is free, although I still program them in assembly.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top