The following is work done by the first satellite team.
Tutorial-PIC Programming Basics
Tutorial-ADC Setup Using the 18F452 or 18F4520
The C compiler used on CAPE1 was the [http://www.microchip.com Microchip] C18 compiler. This software has many issues that veteran programmers know about.
Here is a list of things programmers must be wary of with C18.
*char
for ASCII character arrays. Use char[10]
instead.for
loop, declare the int
outside the for
command. For example, do not do the following:1: for(int i=0; i<sourcedatacount; i++) 2: 3: { 4: 5: }
Instead, do the following:
1: int i; 2: 3: for(i=0; i<sourcedatacount; i++) 4: 5: { 6: 7: }
No more than 256 bytes can be allocated to a variable even though 1K of memory is available. The way to overcome this is to seperate variables into multiple banks using the #pragma udata
command. If you receive the error similar to '.udata_main.o’ can not fit the section
, then you have run out of memory. You can use the following to access more memory and add more variables. Here’s an example where I opened up more memory and created a new char array called buoyA[100]
. Notice the #pragma udata
statements located before and after. The myuaryscn
is trivial and can be called anything.
1: #pragma udata myuaryscn 2: unsigned char buoyA[100]; 3: #pragma udata
If you fill up this bank with memory also, you can open up another one. Here I’ve filled memory with several variables.
1: #pragma udata myuary2 2: unsigned char buoyB[100]; 3: char Ycommand[50]; 4: char Yvalue[4]; 5: char Xcommand[50]; 6: char Xvalue[4]; 7: #pragma udata
You can continue to do this until all RAM has been used up.
See MPLAB C18 C Compiler Getting Started Guide.
See .udata_main.o can not fit the section - C18 Memory Settings.
See char buf(512) - can not fit the section.
Another way of doing this is by increasing the bank size in the linker file. By openening up the linker file, you can edit the contents allowing you to increase the size.
Quick and dirty way is to copy the linker file to your local directory (it’s best not to edit it directly) and change the appropriate ram allocation line.
In the following section:
1: ACCESSBANK NAME=accessram START=0x0 END=0x5F 2: DATABANK NAME=gpr0 START=0x60 END=0xFF 3: DATABANK NAME=gpr1 START=0x100 END=0x1FF 4: DATABANK NAME=gpr2 START=0x200 END=0x2FF 5: DATABANK NAME=gpr3 START=0x300 END=0x3FF 6: DATABANK NAME=gpr4 START=0x400 END=0x4FF 7: DATABANK NAME=gpr5 START=0x500 END=0x5FF 8: DATABANK NAME=gpr6 START=0x600 END=0x6FF 9: DATABANK NAME=gpr7 START=0x700 END=0x7FF 10: DATABANK NAME=gpr8 START=0x800 END=0x8FF 11: DATABANK NAME=gpr9 START=0x900 END=0x9FF 12: DATABANK NAME=gpr10 START=0xA00 END=0xAFF 13: DATABANK NAME=gpr11 START=0xB00 END=0xBFF 14: DATABANK NAME=gpr12 START=0xC00 END=0xCFF 15: DATABANK NAME=gpr13 START=0xD00 END=0xDFF 16: DATABANK NAME=gpr14 START=0xE00 END=0xEFF 17: DATABANK NAME=gpr15 START=0xF00 END=0xF5F 18: ACCESSBANK NAME=accesssfr START=0xF60 END=0xFFF PROTECTED
Change the line:
3: DATABANK NAME=gpr1 START=0x100 END=0x1FF
to:
3: DATABANK NAME=gpr1 START=0x100 END=0x2FF
and delete or comment the line
4: DATABANK NAME=gpr2 START=0x200 END=0x2FF
This gives you the attached linker file which creates a 512 byte section as the first section in RAM. If you were creating a larger than 256 byte variable such as a 512 byte array, it would be better to actually name the section and use a #pragma
statement to put the array in said section. Typically it’s better to not have a variable span multiple banks due to access times (probably trivial in your application) and forcing the variables to lie completely within via pragma statements is the best way to go.
The following code is needed in order to have the PIC jump to a function when an interrupt occurs. Here is an example used on the Microchip PIC18LF452.
1: void Check(void); 2: #pragma code low_vector = 0x0018 3: void low_interrupt(void) 4: { 5: Check(); 6: } 7: #pragma code 8: void Check(void) 9: { 10: INTCONbits.GIE = 0; //Turns interrupts off temporarily 11: 12: //Replace this line with the function to jump to 13: 14: INTCONbits.GIE = 1; //Turns interrupts back on 15: }
The libraries file might be missing some key information (depending on the version you have). The OpenADC()
function, its important to know that ADC_VREFMINUS_VSS
is available which means VREF- gets set to an external negative reference.
Code Example:
1: OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_20_TAD, ADC_CH0 & ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS, 0);