|
|
View previous topic :: View next topic |
Author |
Message |
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
RS232 Stream with data of 0x00 - this ones for Ttelmah |
Posted: Sun Aug 20, 2006 6:34 am |
|
|
I little while ago, you were very helpul on answering questions on streams. - see "help on custom Send_string_RS232 function" below
http://www.ccsinfo.com/forum/viewtopic.php?t=27883
you pointed out having a define to send out strings.
I implemented your thoughts, but am still having problems.
I think its because any putc or fputc sees a 0x00 as the end of string terminator.
here is what I constructed, but it quits early when the data is 0x00.
any ideas to overcome this.
char const command_Cam_OFF[] = {0x81,0x01,0x04,0x00,0x03,0xFF};
#define Send_command(String) putcint(String);
void putcint( int c)
{
fputc (c,Streamname);// WHERE STREAMNAME IS DEFINED IN THE USE RS232 ETC
}
void main()
{
Send_Command(command_Cam_OFF);
etc
etc
}
i know i can probably use
fputc (Streamname,%c%c%c%c%c,0x81,0x01,0x04,0x00,0x03,0xFF);
but it is nowhere near as elegant as having the command defined as a string constant
any help will result in beer tokens of your choice :-)
Mike |
|
|
Sherpa Doug Guest
|
|
Posted: Sun Aug 20, 2006 6:58 am |
|
|
Putc() deals in bytes. It doesn't know stings or care about string terminataors. 0x00 is just another byte.
Is it possible that you are sending this stream to a PC and the PC is throwing out nulls? Some PC comm software does that by default. I think Hyperterminal does that which is another reason it should be vigorously expunged from every Windows PC on the planet. (Oddly Hyperterminal for OS/2 was a fine program, a completely different animal)
SherpaDoug |
|
|
Ttelmah Guest
|
|
Posted: Sun Aug 20, 2006 7:14 am |
|
|
The problem is nothing to do with putc, but that C, sees an ascii '0' as an end of string, so never calls putc with this value.
There are a number of possible routes. The normal 'workround', is to use another character as an escape. So in C itself, the '\' is used this way.
So, for this one value:
Code: |
char const command_Cam_OFF[] = {0x81,0x01,0x04,0x5C0x30,0x03,0xFF};
#define Send_command(String) putcint(String);
void putcint( int c) {
static int1 esc_flag=false;
if (c=='\') {
esc_flag=true;
return;
}
if (esc_flag) {
if (c=='0') c=0;
esc_flag=false;
}
fputc (c,Streamname);
// WHERE STREAMNAME IS DEFINED IN THE USE RS232 ETC
}
void main() {
Send_Command(command_Cam_OFF);
etc
etc
}
|
Then the '\' character, if required, has to be sent as '\\', and the ascii '0', is sent as '\0'.
Best Wishes |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Sun Aug 20, 2006 7:18 am |
|
|
Sherpa,
i am single stepping through the code using ICDU-40
the listing shows
................ fputc (c,streamname);
*
007D: MOVF 22,W
007E: BTFSS 0C.4
007F: GOTO 07E
0080: MOVWF 19 // mike - this is putting the byte in TxD register
....................
.................... } // end of function
0081: RETLW 00
....................
so that part seems sound
i think the problem is here :-
.................... Send_Command(command_Cam_IF_Clear);
00BD: CLRF 21
00BE: MOVF 21,W
00BF: CALL 00D
00C0: IORLW 00 // mike- i think it got the byte, INCOR it with zero
00C1: BTFSC 03.2 // mike - the data byte was zero, so exit
00C2: GOTO 0C7 // mike - exit the routine
00C3: INCF 21,F
00C4: MOVWF 22
00C5: CALL 07D
00C6: GOTO 0BE
00C7 is the next part of main code
so the #define has inserted the code above as putcint(string) |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Sun Aug 20, 2006 8:03 am |
|
|
Ttelmah
I dont like using the "\" as a flag to signify an escape sequence.
I really want to leave the char const string as its raw data, otherwise supportability and readabilty in the future is compromised.
Mike |
|
|
Ttelmah Guest
|
|
Posted: Sun Aug 20, 2006 10:15 am |
|
|
Unless you use some form of indicator, I'm afraid you cannot use the 'shortcut'. The shortcut is designed to deal with strings, and in C, '0' is the string terminator character. You can use any character you want as an indicator. If (for instance), you never use the backspace character, or a 'high' character like 0xff, then you can simply use these, and output a zero when these are encountered.
Best Wishes |
|
|
Sherpa Doug Guest
|
|
Posted: Sun Aug 20, 2006 11:05 am |
|
|
On closer inspection Ttelmah is right. You are using an odd extension of CCS C that allows passing strings to putc(). In K&R C this would be forbidden so the whole point would be moot.
To solve your problem you need some way to tell the printing function how long the string is. Escape sequences work and are commonly used but I don't like the asthetics any more than you. Another less common option is to use the first byte to hold the string length in binary. Or if all your strings can be padded to the same length, then make a printing function that just prints that length.
SherpaDoug |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Sun Aug 20, 2006 11:41 am |
|
|
I am coming to the conclusion ( after several beers) , that the solution is to directly manipulate the bytes, stuffing them into a buffer, which the serial isr just pumps out.
Mike |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Sun Aug 20, 2006 12:05 pm |
|
|
MikeW wrote: | I am coming to the conclusion ( after several beers) , that the solution is to directly manipulate the bytes, stuffing them into a buffer, which the serial isr just pumps out.
Mike |
Mike,
Look at the CCS example EX_STISR.C in the \examples folder. It's an example of an interrupt driven transmit routine. I use this routine (slightly modified) all the time. And I send 0x00 all the time - no issues.
Have a look at it - I hope it helps. |
|
|
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Sun Aug 20, 2006 12:34 pm |
|
|
How about this method....
I think the term 'string' should be avoided for this problem. This is a stream of bytes, NOT characters, and as such should be treated as a byte stream.
You can use fputc to send an individual byte (or char 0 to 255). It's the string parser that calls this that, as has been mentioned, will cause the headache. So replace this with a helper function/macro that sends a number os bytes instead. i.e
Code: | char const command_Cam_OFF[] = { 0x81, 0x01, 0x04, 0x00, 0x03, 0xFF };
#define SendCommand(x) {int8 i; for(i=0; i<sizeof((x));i++) { fputc((x)[i], PC_STREAM); }}
void main()
{
SendCommand(command_Cam_OFF);
...
}
|
Only drawback is that it gets inlined, but it does look more elegent (if you have the FLASH space !!) _________________ Regards,
Simon. |
|
|
Ttelmah Guest
|
|
Posted: Sun Aug 20, 2006 2:20 pm |
|
|
The term 'string', does apply, but is also the cause of the problem....
A 'string' in C, is a linear array of characters, terminated by a 0. The 'const' shortcut, handles strings _only_. For anything else (which if you want to have a '0' in the definition, you are dealing with), then you need to go DIY.
Not exactly a major problem.
Best Wishes |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Mon Aug 21, 2006 2:39 am |
|
|
Telmah,
yes, I know its not exactly a major problem, but pointers and strings and char consts are not my strengths.
I tried mr Baxters solution, and it doesnt work. it doesnt get to the strings at all.
sorry to be a pain, but i was hoping for a quick solution that i could just pop in, and get on with hte rest of the project
below is what is compiled from me Baxters suggestion
char const command_Cam_OFF[] = {0x81,0x01,0x04,0x00,0x03,0xFF};
.................... Send_Command(command_Cam_OFF);
0079: CLRF 22
007A: MOVF 22,W
007B: SUBLW 03
007C: BTFSS 03.0
007D: GOTO 088
007E: ADDWF 22,W
007F: MOVWF 04
0080: MOVF 00,W
0081: MOVWF 27
0082: MOVF 27,W
0083: BTFSS 0C.4
0084: GOTO 083
0085: MOVWF 19 // mike - this is loading the TxD reg with totally wrong values
0086: INCF 22,F
0087: GOTO 07A |
|
|
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Mon Aug 21, 2006 4:09 am |
|
|
Mike,
It was a typo in my code !! if you remove the brackets around the x in the body of the macro definition then the macro is correctly expanded by the compiler and it does the right thing. i.e.
Code: | char const command_Cam_OFF[] = { 0x81, 0x01, 0x04, 0x00, 0x03, 0xFF };
#define SendCommand(x) {int8 i; for(i=0; i<sizeof(x);i++) { fputc(x[i], PC_STREAM); }}
void main()
{
SendCommand(command_Cam_OFF);
...
}
|
you also may want to put
as a global as the compiler may get a bit upset with that if the macro isn't the first call in a function or main. _________________ Regards,
Simon. |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 21, 2006 4:22 am |
|
|
What is proposed by Mr Baxter, will work, but just needs a little 'tweak' or two to make it work. There are a couple of 'potential' problems (which may cause problems).
The first 'potential' problem, is with the use of the local counter 'i'. Normally in C, this would be fine, but CCS, distinguishes 'local' variables, by adding the name of the subroutine to the declaration. I have seen too many problems appear in CCS C, when variables are declared inside an unnamed function, to 'trust' this. Hence I'd use a single global variable for the counter. Then the use of brackets round 'x' in the fputc, will cause problems with the expansion. This should work:
Code: |
int8 send_ctr;
#define SendCommand(x) {for(send_ctr=0;\
send_ctr<sizeof(x);send_ctr++)\
{fputc(x[send_ctr],PC_STREAM);}}
const int command_Cam_OFF[] = {0x81, 0x01, 0x04, 0x00, 0x03, 0xFF};
|
With this 'SendCommand(command_Cam_OFF);', does generate the required sequence.
Best Wishes |
|
|
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Mon Aug 21, 2006 4:26 am |
|
|
Ttelmah,
Just what I said in my previous post !!!
BTW : You can call me Simon. No need to be so formal _________________ Regards,
Simon. |
|
|
|
|
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
|