![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
How to declare a big string array in ROM? |
Posted: Thu Aug 18, 2016 11:30 am |
|
|
I have a char type variable that can have values from 0x00 to 0xFF and I need to send a string through the serial port by using that variable to take a string from a string array from ROM.
Example:
Code: |
char x;
string str[0xFF]={"zero","one","two"........};
x=getc();
printf(putc,"Result: %s",str[x]);
|
_________________ Electric Blue |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Aug 18, 2016 12:02 pm |
|
|
Depends a little bit on the age of your compiler, and the PIC being used (PIC16's have limitations that the PIC18 doesn't have).
Code: |
const char str[0xFF][8]={"zero","one","two"........};
//There is no such type in C as a 'string'....
//A 'string' in C, is an array of characters terminated with a NULL
//Then what you are showing is a two dimensional array, not a one
//dimensional one. You need to size the right hand bracket for whatever the
//largest single element is.
//Then you either use strcpy, to copy this into a temporary RAM buffer. So:
char temp[10]; //needs to be large enough
strcpy(temp,str[x]);
//then print this:
printf("Result: %s",temp);
//Or if you have a recent compiler, add the line:
#DEVICE PASS_STRINGS=IN_RAM
//after the processor include file, and then:
printf("Result: %s",str[x]);
//will work as is.
|
Printf routes to putc automatically. |
|
![](templates/subSilver/images/spacer.gif) |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Thu Aug 18, 2016 12:16 pm |
|
|
Thanks for your fast answer.
I'm sorry, I forgot to mention that I'm using a PIC18F67J50 and CCS compiler v5.058.
I have two doubts about your example; first, when I add the line
#DEVICE PASS_STRINGS=IN_RAM
to the code, Actually all the strings will be loaded at start in RAM?
Second There's any limit on the array size besides physically ROM size.
Just to know, Can you give one example of one limitation that PIC16 have against PIC18 related to this? _________________ Electric Blue |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 18, 2016 7:01 pm |
|
|
Quote: | when I add the line
#DEVICE PASS_STRINGS=IN_RAM
to the code, Actually all the strings will be loaded at start in RAM?
|
No. It doesn't copy all constant strings into RAM at the start of
the program, as you are suggesting.
When you call a function such as display_string() in the program below,
it copies "Hello World" from ROM into a RAM buffer. The address of the
RAM buffer is then given to display_string(). The RAM buffer is internally
allocated by the compiler. You don't have control over it. It uses a little
bit of your RAM to do this. The same RAM buffer is used each time.
Code: |
#include <18F4620.h>
#device PASS_STRINGS=IN_RAM
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
void display_string(char *ptr)
{
printf("%s", ptr);
}
//======================================
void main(void)
{
display_string("Hello World");
display_string("ABCDE");
while(TRUE);
} |
Quote: | There's any limit on the array size besides physically ROM size ? |
For the PCM compiler, a const array is limited to the ROM page size.
Example: For a 16F877, this is 2K bytes.
For the PCH compiler, I don't think there's a limit. I tried a const array
of 3700 bytes of text for the 18F4620 and it compiled. Example:
Code: | #include <18F4620.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
int8 const array[3700] =
"The PCB, PCM, and PCH are separate compilers. PCB is for 12-bit opcodes, PCM is for
14-bit opcodes, and PCH is for 16-bit opcode PICr microcontrollers. Due to many
similarities, all three compilers are covered in this reference manual. Features and
limitations that apply to only specific microcontrollers are indicated within. These compilers
are specifically designed to meet the unique needs of the PICr microcontroller. This
allows developers to quickly design applications software in a more readable, high-level
language.
[ I cut the rest of the text for brevity ]
";
//======================================
void main(void)
{
int16 i;
int8 value;
value = array[i];
while(TRUE);
} |
All tests were done with compiler vs. 5.061. |
|
![](templates/subSilver/images/spacer.gif) |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Thu Aug 18, 2016 8:27 pm |
|
|
I have to create an array of 256 strings of 12 bytes including the null terminator.
Anyway, if I understand well what you are explaining to me, the compiler will warning me if the array is too big and refuse to compile.
Thanks for your info. _________________ Electric Blue |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Fri Aug 19, 2016 12:43 am |
|
|
The amount of RAM used by 'PASS_STRINGS', is normally quite small. Much less than the size of the strings it handles. A couple of tests I did in the past had it using what appears to be a 'dynamic' buffer of between 16 and 64 bytes. There is a limit on the PIC18's as well on const sizes, but it is something like 64K!.
PASS_STRINGS, 'virtualises' the ROM. Remember on the PIC, the program memory is a completely separate address space. So there is 'address 0' in ROM, and another 'address 0' in RAM. This is why the PIC doesn't just allow a simple linear addressing of the ROM and RAM (like a PC). The advantage of this is that the PIC can be reading bytes from both address spaces at the same time, which gives good performance without involving the complexity of having to add things like cache. Downside is 'how to handle' the two address spaces?...
With 'PASS_STRINGS', the code gives an extended address to the ROM, and automatically buffers the access.
strcpy, is 'overloaded', and knows if it is given a ROM address, to use the code to access this, rather than the normal RAM code. This is the 'old' way of doing this, with you copying the required string to RAM yourself. |
|
![](templates/subSilver/images/spacer.gif) |
E_Blue
Joined: 13 Apr 2011 Posts: 417
|
|
Posted: Mon Aug 22, 2016 9:38 am |
|
|
Thanks! I have it clear now. ![Smile](images/smiles/icon_smile.gif) _________________ Electric Blue |
|
![](templates/subSilver/images/spacer.gif) |
ronaldoklais
Joined: 18 Dec 2012 Posts: 13
|
|
Posted: Mon Aug 22, 2016 11:05 am |
|
|
You can write directly to rom using
#rom ADDRESS = { 0, 3, 11, 2, 3, 4 } // bytes
and then read using read_program_memory(address, dest, size) |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|