View previous topic :: View next topic |
Author |
Message |
igorp
Joined: 23 Apr 2005 Posts: 4
|
pointers |
Posted: Sat Apr 23, 2005 5:02 pm |
|
|
Hi all more experienced
I missed something... What is wrong by such construction ?
void lcd_writeline_rom(char lineno, char const * text) {
while (*text)
The compiler refuses *text in while statement because it's not a numeric expression... Strange behaving at least by me.
Regards
Igor |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Apr 23, 2005 6:25 pm |
|
|
Remove the "const" declarator, shown in bold below:
void lcd_writeline_rom(char lineno, char const * text) |
|
|
igorp
Joined: 23 Apr 2005 Posts: 4
|
pointers |
Posted: Sun Apr 24, 2005 3:02 pm |
|
|
I see... C Compiler Reference Manual page 232
I don't see any way how to send address of a string stored in the program memory to a procedure as a parameter. Am I right?
Igor |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 24, 2005 3:05 pm |
|
|
Yes. You can't pass a pointer to a constant string, in CCS. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
Re: pointers |
Posted: Sun Apr 24, 2005 9:11 pm |
|
|
igorp wrote: | I see... C Compiler Reference Manual page 232
I don't see any way how to send address of a string stored in the program memory to a procedure as a parameter. Am I right?
Igor |
Copy it to RAM and then pass a pointer to that buffer. |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Mon Apr 25, 2005 10:12 am |
|
|
As a new PIC programmer, I understand that the Harvard architecture imposes limitations in this area.
If I wanted to do something like the following normal C code, what is the best way with PCH/PCM? A printf in each case?
Code: |
char *cp;
switch (i) {
case 0:
cp = "zero";
break;
case 1:
cp = "one";
break;
default:
cp = "huh?";
}
printf("Got %s\r\n", cp);
|
_________________ The best weather is bad weather |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Apr 25, 2005 10:16 am |
|
|
This should be more efficient than a bunch of printf's
Code: |
char cp[5];
switch (i) {
case 0:
strcpy (cp, "zero");
break;
case 1:
strcpy (cp, "one");
break;
default:
strcpy (cp, "huh?");
}
printf("Got %s\r\n", cp);
|
|
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Mon Apr 25, 2005 11:32 am |
|
|
I use a 2d array alot.
Code: |
const char error_txt[8][16] =
{
"USART overflow", // -0-
"TXBuffer ovrflw", // -1-
"RXBuffer ovrflw", // -2-
"Bad Checksum", // -3-
"", // -4-
"LCD X exceeded", // -5-
"LCD Y exceeded", // -6-
"" // -7-
};
//========================== err_chk ===============================
void ChkErr(void) //print out any errors that occured
{
int8 chk=0;
fprintf(STDERR,"ERROR(%U): %s.\r\n",chk,error_txt[chk]);
}
|
I think this puts the stings in rom. And you can print easy. But your not passing a pointer. You could also do as suggested and memcopy. |
|
|
gustnado
Joined: 23 Apr 2005 Posts: 21 Location: Phoenix,AZ
|
|
Posted: Mon Apr 25, 2005 1:01 pm |
|
|
Oddly enough, in my tests, the series of printf's are shorter than the strcpy's. The following shows number of instruction words (in decimal):
Code: |
printf strcpy
14 bit 10 14
16 bit 9 16
|
It appears to be inlining strcpy and part of printf.
Is there a way to tell it to not inline strcpy in this case (I would guess not)? #separate only works in the function declaration, not in its usage, as far as I can tell.
It also appears that there is no strncpy, which I often use to avoid future buffer over-runs.
treitmey's solution with the two dimensional array uses a lot of program memory to hold the leftover space for each entry, and thus is inefficient (space wise). I tried all sorts of things to have a constant array of pointers to strings (rather than treitmey's array of the strings themselves), without success. Does anyone know how to do that?
I know there are serious restrictions on the use of pointers due to the Harvard architecture (separate program and data address spaces), although it is possible in at least some processors (I'm new to PIC - I think only some families have a register to access tables in the program memory.) _________________ The best weather is bad weather |
|
|
Ttelmah Guest
|
|
Posted: Mon Apr 25, 2005 2:42 pm |
|
|
The solution I used in the past to efficient use of a constant string, was to code a massive block like:
Code: |
const char E_general[] = {
"Manual~Data~Setup~Alarms~Cal ~Wash ~Sample ~IP span~Zero~Timings~Clock~Language~High~XHigh~for ~"
"every ~secs~hours~mins~continuously~Cal Hi~"
};
|
And then either store the address of the start of each string in a seperate constant array, or (with a very long table...), search for each '~' marker, and store the byte number where this occurs. The output routine simply transfers characters from the specified start, till it sees the next '~' marker.
Best Wishes |
|
|
igorp
Joined: 23 Apr 2005 Posts: 4
|
pointers |
Posted: Mon Apr 25, 2005 2:42 pm |
|
|
I suggest such solution:
Code: |
char const tabstr[]={"this string is over twenty characters\000\
second string\000\
thirth string, please\000"};
void lcd_writeline_rom(char lineno, char nostring) {
unsigned char i = 0;
// address tabstr has to be known here
while (nostring) { //seek for first character of the selected string
if (!tabstr[i++]) nostring--;
}
// we have the index of first characters of wanted string in i
........
}
void main()
{
.......
lcd_init();
lcd_writeline_rom(0, 0);
lcd_writeline_rom(1, 2);
.....
}
|
Two disadvantages :
1 - The procedure has to know where strings are stored
2- I am not able to find out how to do the continuation line in the IDE editor.
3- to find the selected string in any huge array takes some time.
I use it for LCD display (with running text if the string is longer than 16 characters).
Regards
Igor |
|
|
|