CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

char array shows too many bits per char

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

char array shows too many bits per char
PostPosted: Wed Jan 06, 2016 12:04 pm     Reply with quote

Hi All,

I've got a strange issue with (possibly?) typing and I'm hoping I can have some light shed on it. I'm finding that my char array I'm using to process serial is showing extra bits for certain bytes.

For example, an ascii '0' works fine, shows up as 0x30.
However, when I attempt to send something like 0xEF, the byte is appearing as 0xFFEF. I'm trying to figure out how that is even possible?

I have a char array I use to process incoming serial data, rs232MsgInBuff2.

When i read serial bytes in, the RDA ISR copies them over to this buffer. I don't believe there are any issues with the ISR, as it's pretty simple routine that copies over incoming serial until it gets a <CR><LF>
Code:

/*Declares*/
char rs232MsgInBuff[25];
char rs232MsgInBuff2[25];
int8 rs232DataByte = 0;



The message I'm sending in which I noticed this issue is as follows:
[0x30][0xEF][0x0D][0x0A]

When I echo this back to my PC terminal:
Code:

fprintf(PCCTRL,"[%X][%X]\r\n",rs232MsgInBuff2[0],rs232MsgInBuff2[1]);


I see:
[0x30][0xFFEF]

I am attempting to process this command in a separate function as such:


Code:

   switch (rs232MsgInBuff2[0])
   {
         case 0x30:
         //fprintf(PCCTRL,"[%X][%X]\r\n",rs232MsgInBuff2[0],rs232MsgInBuff2[1]);
       
         if (rs232MsgInBuff2[1] == 0x30){
            /*Do Stuff*/
         } else if (rs232MsgInBuff2[1] == 0xEF){
           /*Do Other Stuff*/
         }
         break;
/*SNIP*/
}


This does NOT enter the rs232MsgInBuff2[1] == 0xEF condition.
if I change it to rs232MsgInBuff2[1] == 0xFFEF, it drops in just fine.

Is my array somehow losing its type? Is there some other funny business going on?

Thanks in advance for any info.
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 12:21 pm     Reply with quote

Are you possibly on the latest compiler?.
Read the readme. It looks as if you might be triggering the Unicode option?.
Haven't got is handy on this computer, but remember noting it in the readme with the download.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 12:30 pm     Reply with quote

KTrenholm wrote:

When I echo this back to my PC terminal:

fprintf(PCCTRL,"[%X][%X]\r\n",rs232MsgInBuff2[0],rs232MsgInBuff2[1]);

I see:
[0x30][0xFFEF]


When I make a little test program and run it in MPLAB (vs. 8.92) simulator,
it doesn't show "0x" in front of the numbers. It displays this:
Code:
[30][EF]

Therefore, either you typed the "0x" in the post, or your terminal program
is doing it. If the terminal program is putting in the "0x", I submit that it's
probably also prefixing the 0xFF as well.

Test program:
Code:
#include <18F4620.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS, stream=PCCTRL)

char rs232MsgInBuff[25];
char rs232MsgInBuff2[25];
int8 rs232DataByte = 0;

//=====================================
void main()
{
rs232MsgInBuff2[0] = 0x30;
rs232MsgInBuff2[1] = 0xEF;

fprintf(PCCTRL,"[%X][%X]\r\n",rs232MsgInBuff2[0],rs232MsgInBuff2[1]);

while(TRUE);
}


Also, you should have told us the following in your post:
1. Your PIC.
2. Your CCS compiler version.
3. Name of your terminal program
4. #use rs232 statement.
5. Preferably a full test program so we can see everything.
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 12:42 pm     Reply with quote

PCM programmer wrote:


Also, you should have told us the following in your post:
1. Your PIC.
2. Your CCS compiler version.
3. Name of your terminal program
4. #use rs232 statement.
5. Preferably a full test program so we can see everything.


My mistake, I reflexively put the "0x" before the hex out of habit.
I am seeing [30][FFEF]
I have used this command in my more recent MPLAB code with no issues, the one I'm working on here is legacy and uses CCS.

1) I'm on a PIC24FV32KA302
2) I am on an older CCS version V4.132
3) I'm using PuTTy for my terminal.
4) #USE RS232 (STREAM=PCCTRL, BAUD=19200, BITS=8, PARITY=N, UART1, ERRORS)

5) I can't post full code but I can give a bit more context.

The ISR for the UART is as follows:
Code:

/*Globals*/
#define BUFFER_DATA_SIZE 25
char rs232MsgInBuff[BUFFER_DATA_SIZE];
char rs232MsgInBuff2[BUFFER_DATA_SIZE];
int8 rs232DataByte = 0;

#INT_RDA
void RDA_isr(void)
{
#USE FAST_IO(A)
#USE FAST_IO(B)
   long timeout = 0;
   char c;

   restart_wdt();

   while (kbhit(PCCTRL) &&(++timeout<50000)) {
      //Get String until encounter <CR><LF>
      c = fgetc(PCCTRL);
      if (c != 13) {
         if (c!= 10) {
            if(rs232DataByte < BUFFER_DATA_SIZE) {
               rs232MsgInBuff[rs232DataByte++] = c;
            }
         }
      }
      else {
         //Only copy over complete messages for processing
         memcpy(rs232MsgInBuff2,rs232MsgInBuff,BUFFER_DATA_SIZE);
         memset(rs232MsgInBuff, '\0', sizeof(rs232MsgInBuff));
         rs232DataByte = 0;
      }
   }
}


When a message is received it waits in the rs232MsgInBuff2 until processed in my main program loop.

Code:


void rs232_response(void)
{
#USE FAST_IO(A)
#USE FAST_IO(B)

   unsigned int16 temp_uint16;
   char temp_char[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   int8 invalid_value;
   
   switch (rs232MsgInBuff2[0])
   {
         case '\0':
         break;
         
         case 0x30:
         fprintf(PCCTRL,"[%X][%X]\r\n",rs232MsgInBuff2[0],rs232MsgInBuff2[1]);
       
         if (rs232MsgInBuff2[1] == 0x30){
            /*Subcommand 1*/
         } else if (rs232MsgInBuff2[1] == 0xEF){
            /*Subcommand 1*/
         }
         break;
         
      case 0x81:
         /*Other Commands*/
         break;
       /*SNIP*/
       default:
       break;
}
memset(rs232MsgInBuff2, '\0', sizeof(rs232MsgInBuff2));
}


Let me know if there's any other info/context you need
jeremiah



Joined: 20 Jul 2010
Posts: 1355

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 12:47 pm     Reply with quote

The pic24 series is a 16bit chip (hence the sign extension to FFEF...while leading zeros are defaulted to discarded so 0030 shows up as just 30). Try %02X instead and see if that keeps it down to 2 digits.

EDIT: That said, if you aren't going to be sending exclusively ascii (values less than 0x80), then you should probably make your arrays unsigned chars instead of signed chars.
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 12:53 pm     Reply with quote

jeremiah wrote:
The pic24 series is a 16bit chip (hence the sign extension to FFEF...while leading zeros are defaulted to discarded so 0030 shows up as just 30). Try %02X instead and see if that keeps it down to 2 digits.

EDIT: That said, if you aren't going to be sending exclusively ascii (values less than 0x80), then you should probably make your arrays unsigned chars instead of signed chars.


The problem isn't with how it prints (that's just how I found the problem). The issue seems to be that the PIC seems to see the value as actually 0xFFEF, which is why it doesn't drop into my if statement.
Code:

if (rs232MsgInBuff2[1] == 0xEF){
}


however it DOES drop into
Code:

if (rs232MsgInBuff2[1] == 0xFFEF){
}


Which means the PIC itself thinks that a char value is 0xFFEF? I'm just not sure how that can happen?
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 12:54 pm     Reply with quote

jeremiah wrote:

EDIT: That said, if you aren't going to be sending exclusively ascii (values less than 0x80), then you should probably make your arrays unsigned chars instead of signed chars.


You might have something here, my MPLAB code where this works uses an array of unsigned int8, not char. I'll take a look into it.

EDIT:
I changed the type of the buffers to unsigned with no change in behavior.
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 1:32 pm     Reply with quote

Code:
/*Globals*/
 #define BUFFER_DATA_SIZE 25
 unsigned int8 rs232MsgInBuff[BUFFER_DATA_SIZE];  // change 1
 unsigned int8 rs232MsgInBuff2[BUFFER_DATA_SIZE];  // change 2 - do these first
 int8 rs232DataByte = 0;

 #INT_RDA
 void RDA_isr(void)
 {
 #USE FAST_IO(A)
 #USE FAST_IO(B)
    long timeout = 0;
    unsigned int8 c; // change 3 - do this first too

    restart_wdt();

    while (kbhit(PCCTRL) &&(++timeout<50000)) {
       //Get String until encounter <CR><LF>
       c = fgetc(PCCTRL);
       if (c != 13) {
          if (c!= 10) {
             if(rs232DataByte < BUFFER_DATA_SIZE) {
                rs232MsgInBuff[rs232DataByte++] = c & 0x00ff; // try this if 1, 2 and 3 don't work
             }
          }
       }
       else {
          //Only copy over complete messages for processing
          memcpy(rs232MsgInBuff2,rs232MsgInBuff,BUFFER_DATA_SIZE);
          memset(rs232MsgInBuff, '\0', sizeof(rs232MsgInBuff));
          rs232DataByte = 0;
       }
    }
 }
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 1:35 pm     Reply with quote

newguy wrote:
Code:
/*Globals*/
 #define BUFFER_DATA_SIZE 25
 unsigned int8 rs232MsgInBuff[BUFFER_DATA_SIZE];  // change 1
 unsigned int8 rs232MsgInBuff2[BUFFER_DATA_SIZE];  // change 2 - do these first
 int8 rs232DataByte = 0;

 #INT_RDA
 void RDA_isr(void)
 {
 #USE FAST_IO(A)
 #USE FAST_IO(B)
    long timeout = 0;
    unsigned int8 c; // change 3 - do this first too

    restart_wdt();

    while (kbhit(PCCTRL) &&(++timeout<50000)) {
       //Get String until encounter <CR><LF>
       c = fgetc(PCCTRL);
       if (c != 13) {
          if (c!= 10) {
             if(rs232DataByte < BUFFER_DATA_SIZE) {
                rs232MsgInBuff[rs232DataByte++] = c & 0x00ff; // try this if 1, 2 and 3 don't work
             }
          }
       }
       else {
          //Only copy over complete messages for processing
          memcpy(rs232MsgInBuff2,rs232MsgInBuff,BUFFER_DATA_SIZE);
          memset(rs232MsgInBuff, '\0', sizeof(rs232MsgInBuff));
          rs232DataByte = 0;
       }
    }
 }


See above post. I changed everything to unsigned, I even replaced fgetc with just a straight read of U1RXREG to ensure I'm unsigned all the way through.

I also have tried masking the top byte off. No change.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 1:58 pm     Reply with quote

KTrenholm wrote:

Which means the PIC itself thinks that a char value is 0xFFEF? I'm just not sure how that can happen?

1) I'm on a PIC24FV32KA302
2) I am on an older CCS version V4.132

What about this item in the CCS versions list ?
Quote:

4.136 Memory managment for EP chips has improved including DMA access
4.136 A number of updates and bug fixes made to addressmod and _packed
4.136 PCD now treats constant numbers less than 256 as an int8 (was int16)
4.135 Some register names that were changes are now fixed
4.135 A bug with pointers to ROM in some expresions is now fixed
4.135 A compiler error when using a variable pin for some ENH16 ports is fixed
4.135 A memcpy() bug in PCM for some data types is fixed
4.135 The compiler now uses hardware UART inverting on PIC18 parts that allow it
4.134 An IDE problem was fixed that caused error messages to pop up
4.133 A number of updates a fixes for the PIC24EP chips are in
4.133 PIC24 SPI_XFER function now uses 16 bit transfers if it can
4.133 A bug causing the WDT_NOSL fuse to be ignored is fixed
4.133 A problem with very large rom arrays is fixed
4.133 Some typing issues with structure assignments are now resolved


Last edited by PCM programmer on Wed Jan 06, 2016 2:20 pm; edited 1 time in total
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 2:14 pm     Reply with quote

PCM programmer wrote:
KTrenholm wrote:

1) I'm on a PIC24FV32KA302
2) I am on an older CCS version V4.132

What about this item in the CCS versions list ?
Quote:

4.141 Various chip specific built in functions fixes have been made
4.141 A problem on some chips with strings in #rom is fixed
4.141 A PIC24 problem with some bit arrays is fixed
4.140 An access violation when using bit_ functions is fixed
4.139 A problem relocating the int vector to high memory on the ENH16 parts is fixed
4.139 A compiler error when using a variable pin for some ENH16 ports is fixed
4.139 A syntax error with void functions as pointers is fixed
4.139 Some packed structure problems have been fixed
4.138 Some additional #zero_ram problems on PIC24 parts are fixed
4.138 Problems with addressmod related (packed and rom pointers) issues are fixed
4.138 Newest parts have been added
4.137 A problem with #zero_ram on the ENH16 parts is fixed
4.136 Memory managment for EP chips has improved including DMA access
4.136 A number of updates and bug fixes made to addressmod and _packed
4.136 PCD now treats constant numbers less than 256 as an int8 (was int16)
4.135 Some register names that were changes are now fixed
4.135 A bug with pointers to ROM in some expresions is now fixed
4.135 A compiler error when using a variable pin for some ENH16 ports is fixed
4.135 A memcpy() bug in PCM for some data types is fixed
4.135 The compiler now uses hardware UART inverting on PIC18 parts that allow it
4.134 An IDE problem was fixed that caused error messages to pop up
4.133 A number of updates a fixes for the PIC24EP chips are in
4.133 PIC24 SPI_XFER function now uses 16 bit transfers if it can
4.133 A bug causing the WDT_NOSL fuse to be ignored is fixed
4.133 A problem with very large rom arrays is fixed
4.133 Some typing issues with structure assignments are now resolved


Interesting, if this is the case though, shouldn't my masking with 0x00FF solve the issue?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 2:57 pm     Reply with quote

It's still 0xEF. It's likely promoting it to a signed 16-bit value, which is 0xFFEF.
Try doing the following, shown in bold below:
Quote:
if (rs232MsgInBuff2[1] == (int8)0xEF){
}


I don't have PCD so I can't test any of this. All I can do is make suggestions.
KTrenholm



Joined: 19 Dec 2012
Posts: 43
Location: Connecticut, USA

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 3:34 pm     Reply with quote

PCM programmer wrote:
It's still 0xEF. It's likely promoting it to a signed 16-bit value, which is 0xFFEF.
Try doing the following, shown in bold below:
Quote:
if (rs232MsgInBuff2[1] == (int8)0xEF){
}


I don't have PCD so I can't test any of this. All I can do is make suggestions.


I did find that assigning to an int8 rather than reading out of the array DOES remove the FF.

Code:

unsigned int8 cmd;
cmd =  rs232MsgInBuff2[1];
if (cmd == 0xEF){
/*stuff*/
}


So I guess for now I can just avoid reading directly out of the array. I'd still be curious as to why this happens though, and why a byte like 0x30 has no problem being compared from an array.

So from what I can figure, maybe it has something to do with reading it out of the array?
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Wed Jan 06, 2016 3:56 pm     Reply with quote

It could be the direct logical comparison on an array element that is/was doing it. The compiler could have sign extended the 0xef to 0xffef to fill a 16 bit register upon which it was doing the comparison. By forcing the compiler to "extract" the array element and put it in a byte variable, you're also forcing it to bypass the seemingly automatic sign extension it was previously performing.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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