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

code doesn't work on every 16f688
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

code doesn't work on every 16f688
PostPosted: Thu May 24, 2007 9:55 am     Reply with quote

I recently posted a problem where I was sharing some I/O pins between and LCD module and rs-232 access. I thought I had resolved the problem but it doesn't appear to be a code related issue because the problem came back. After further examination, I'm finding that the same exact code works in some of my stock of 16f688's but not in others. This is the same code without modification acting differently using the same test hardware by simply pulling the part out of the socket and trying another in the same hardware.

When I get a part that fails, LCD display is blank, if I remove access to the uart in the test code the LCD begins to work properly with that part but if I remove the comments to re-enable the uart the failed parts fail again to display on the LCD.

Has anyone seen this before? I'm really confused on how this could be happening. I have included my final test code for reference as I made some changes after my last post that I though had fixed the problems.

The test simply involves powering up the chip and LCD without any serial connections, no level shifters - nothing, and waiting for the LCD to display something. The LCD does appear to init as the telltale blocks disappear but other than that no display. The code is executing the main loop as I have tested that with simple port = high type tests. The LCD simply remains blank.

any help is much appreciated.

Thanks

Code:

#include <16f688.h>

#fuses INTRC_IO                  //internal rc osc with i/o ra4 and i/o on ra5
#fuses NOWDT                  //no watchdog
#fuses NOMCLR                  //internal MCLR
#fuses NOPROTECT               //no code protect
#fuses NOPUT                  //disabled power up timer
#fuses BROWNOUT                  //disabled brownout detect/reset
#fuses NOCPD                  //no EE read protect
#fuses NOIESO                  //no internal/external switchover mode
#fuses NOFCMEN                  //no monitor clock failsafe mode (auto switch if no clock)
#use delay(clock=8000000,INTRC_IO)   //after fuse to set intrc clock speed or use
                           //setup_oscillator(   );   
#use rs232(baud=9600,parity=N,xmit=PIN_C4,rcv=PIN_C5,errors)

#use fast_io(A)
#use fast_io(C)

////////////////////////////////////////////////////
// Constants and variables
//PortA      0      
//         1      
//         2      LCD - enable
//         3      not used
//         4      
//         5      

//PortC      0      LCD data bit0
//         1      LCD   data bit1
//         2      LCD data bit2
//         3      LCD data bit3
//         4      LCD rd          - rs-232 TX
//         5      LCD rs          - rs-232 RX

#byte PORTA       = 5    // port a = 0x05, b = 0x06, c = 0x07, d = 0x08, e = 0x09  address
#byte    PORTC      = 7

#byte    RCSTA    = 0x17
#bit    SPEN   = RCSTA.7
#bit    CREN   = RCSTA.4
#bit    TXEN   = 0x16.5
#bit    RCIE   = 0x8c.5
//#byte    TRISC    = 0x187


struct {
    BYTE    data:4;      // bits 0 - 3
} LCD_PORT;

#BYTE    LCD_PORT       = 7        //PORTC                             
#BIT   LCD_E           = PORTA.2
#BIT   LCD_RD          = PORTC.4
#BIT   LCD_RS          = PORTC.5

#bit    alarm          = PORTA.4

#define LCD_DATA        LCD_PORT.data
#define DATA_TO_LCD      set_tris_c(0)
#define DATA_FROM_LCD   set_tris_c(0x0f)

#define    WORD unsigned long        // Data type definitions
#include    <lcd_custom_pins.h>
///////////////////////////////////////////////////////////////////

int16    result;
float   meas;
float   alarm_val;
int1   config;
int1   message_flag;

int      i;
//////////////////////////////////////
#define      BUFFER_SIZE 8
#define      bkbhit (next_in != next_out)
int         buffer[BUFFER_SIZE];
int         next_in = 0;
int         next_out = 0;
///////////////////////////////////////////////////////
// General prototypes //

// local prototypes
void execute_cmd();
int bgetc();
int16 get_16b_num();

///////////////////////////////////////////////////
// serial port ISR
#int_rda
rda_isr(){
   static int t;
   
        if(kbhit()){
         buffer[next_in] = getc();
         if (buffer[next_in] == 'C')
            config = 1;
         t = next_in;
         next_in = (next_in + 1) % BUFFER_SIZE;
         if (next_in == next_out)
            next_in = t;      // buffer full
      }
}

////////////////////////////////////////////////////


/////////////////////////////////////////////////////MAIN


void main(){
   alarm = 0;
   message_flag = 0;
   config = 0;
   LCD_E = 0;

   setup_oscillator(OSC_8MHZ);       //sets the sw selectable internal rc clock speed
   SETUP_ADC_PORTS(NO_ANALOGS);      // no adc's
   setup_comparator(NC_NC_NC_NC);
   set_tris_a(0b11000001);            //a.3 is input only so can't use, ignores 0 for tris         
   set_tris_c(0b00100000);
   enable_interrupts(INT_RDA);
   enable_interrupts(global);

   delay_ms(2000);

   while (config){
      if (!message_flag){
         message_flag = 1;
         printf("\r\n ready for config\r\n");
      }
      if (bkbhit)
         execute_cmd();   
   }

   disable_interrupts(INT_RDA);      //no serial comms so no int
   disable_interrupts(global);
   SPEN = 0;
   TXEN = 0;
   CREN = 0;
   RCIE = 0;
   set_tris_c(0b00000000);
   
   LCD_E = 1;
   init_lcd();                     // Init LCD 
   LCD_data = 0;

   printf(displays,"test");   
   lcd_gotoxy(2,2);
   printf(displays,"test 2");
   delay_ms(2000);
   
// loop until reset
   while(1){
         lcd_cmd(0x01);               //clear the display
         lcd_gotoxy(1,2);
         printf(displays,"Temp");
         
          delay_ms(500);
   }   
}


///////////////////////////////////////////////////////////////////////////////


// function interprets commands received through the serial port
void execute_cmd(){
   int      temp,i;

   disable_interrupts(int_rda);

   temp = bgetc();
   switch (temp){   
      case 'h': printf("HELP\r\n");
         printf(" S to set a new alarm value\r\n");
         printf(" Q to quit config and start measuring\r\n");
         printf(" \r\n");
         break;
      
      case 'S': printf("Set alarm value\r\n");
         printf("enter alarm temperature \n\r");
         enable_interrupts(int_rda);
         meas = get_16b_num();
         disable_interrupts(int_rda);
         printf("\r\nalarm value is %3.1f\r\n",meas);
         break;
      case 'Q':
         printf("exiting, please unplug serial cable\r\n");
         delay_ms(1000);
         config = 0;
         SPEN = 0;
         TXEN = 0;
         CREN = 0;
         RCIE = 0;
         set_tris_c(0b00000000);

         LCD_E = 0;
         init_lcd();                     // Init LCD 
         LCD_data = 0;      
         break;

      default:
         break;
   }
   if (config)
      enable_interrupts(int_rda);
}

///////////////////////////////////////////////////
// function retrieves data from the buffer
int bgetc() {
   int c;
   while(!bkbhit);
   c = buffer[next_out];
   next_out = (next_out+1) % BUFFER_SIZE;
   return(c);
}


// Get a 8-bit decimal number from the console
// Return it when any non-numeric key is pressed (except backspace)
WORD get_16b_num(void)
{
    int16 val=0;
    char c, buff[5];
    int n=0, i=0;
   
    do {
      c = bgetc();
        if (c>='0' && c<='9')
        {
            if (n < sizeof(buff))
            {
                buff[n++] = c;
                 putchar(c);            
            }
        }
        else
            c = 0;
    } while (c);
    while (n--)
        val = (val * 10) + buff[i++] - '0';
    return(val);
}
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu May 24, 2007 10:29 am     Reply with quote

I don't know if this will help but I, recently, made a small project using a 16F688 part. It was running off of a battery pack and simply cycling some LED's for a fancy show (made a Knight Rider pinewood derby car). Sometimes the PIC would work, sometimes it wouldn't. I couldn't figure out what was going on. I thought I would take a shot in the dark and put a filter cap across VCC and GND of the PIC. It started working every time. I didn't think I need any filtering since I was running from a battery.

This one made my forehead a little flatter after I smacked it a few times over this one. If you don't have any filter caps you might want to try adding them. They definitely make a difference even if the supply is a battery.

Ronald
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 24, 2007 10:32 am     Reply with quote

Also, the Rev. A3 silicon has a large number of erratas on the USART.
You should try to get the A4 silicon. Check the rev of the chips that
you have.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu May 24, 2007 11:32 am     Reply with quote

Ok, this is probably a stupid question, but how do I know what rev of silicon I have? I've been looking through the data sheet, reviewed the erata notice and I can't seem to find it.

I would be disappointed to find out that I received old silicon since I just purchased these through Digikey recently. On the other hand, it sure would make me happy to know the cause of these issues.

Confused

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 24, 2007 11:54 am     Reply with quote

I know how to do it with MPLAB and ICD2. Plug in the ICD2 to your
board, and in the Programmer menu of MPLAB, select "Connect".
Look at the messages in the Output window of MPLAB.
One of them will show the silicon revision. Example:

Quote:
Connecting to MPLAB ICD 2
...Connected
Setting Vdd source to target
Target Device PIC18F452 found, revision = b5
...Reading ICD Product ID
Running ICD Self Test
...Passed
MPLAB ICD 2 Ready
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu May 24, 2007 12:58 pm     Reply with quote

Well, I guess that's not the problem. I have silicon rev-6 according to my ICD2. Took a bit to finally get connected because I've been using a pictstart plus to program the parts since debugging is only possible with another connector - that I don't have

Ronald,
Thanks for the suggestion but I do have typical filtering in place as well as running the power off of a lab supply until I get this ironed out.


Anything else, I'm glad to try anything at this point. The only way I was able to get the part that's failing to drive the LCD was to comment out the rs-232 parts of the code and then it would work. Keep in mind that some other parts work just fine with the full code in test.

Thanks,

Dan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 24, 2007 1:21 pm     Reply with quote

Your code doesn't compile, as posted. Can you post the missing parts
(lcd driver) ?
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu May 24, 2007 1:28 pm     Reply with quote

Sorry, here's the lcd driver:

Code:

//#define LCD_LINES   0x01
#define LCD_LINES   0x02          // set number of rows here to match LCD(2 and 4 supported)                       
//#define LCD_LINES   0x04


#define       BOOL    short          // 'short' is very short (1 bit) in this compiler
#define       ALL_OUT 0
#define       ALL_IN  0xff

#define       LCD_SETPOS   0x00
BOOL          disp_lcd, disp_serial;      // Flags to enable display O/Ps

Bool          IsLumex1x16;      //bool flag for unique display


/* Local prototypes */
void lcd_gotoxy(unsigned int x, unsigned int y);
void lcd_cmd(BYTE b);
void lcd_char(BYTE b);
void lcd_byte(BYTE &b);
void lcd_nybble(BYTE b);
void lcd_getposition(byte &msb,byte &lsb);

/* Display handler; redirects to LCD and/or serial

 */
void displays(BYTE b)
{
   byte   MSB,LSB;                   
    if (disp_lcd)
    {
        if (b == '\n')      // home position
            lcd_cmd(0x02);
        else if (b == '\r')   // carriage return
//      lcd_cmd(0xc0);
      {
      lcd_getposition(msb,lsb);   // read cursor position from LCD controller
      switch (MSB)
         {
         case 0:
            if (LCD_LINES == 0x01)
               {
               lcd_cmd(0x80);
               break;
               }
            else
               {
            lcd_cmd(0xc0); break;   //if line 1, a carriage return goes to line 2
               }

         case 4:          // if line 2, a carriage return goes to .....
            {
            if (LCD_LINES == 0x02)
               {
               lcd_cmd(0x80); break;      //line1
               }
            else if (LCD_LINES == 0x01)
               {
               lcd_cmd(0x80); break;
               }
            else    {
               lcd_cmd(0x90); break;      //line3
               }
            }
         case 1:          // if line 3, a carriage return goes to ....
            {
            if (lsb == 0)
               {
               lcd_cmd(0xc0);break;
               }
            else
               {
               lcd_cmd(0xd0);break;      //line 4
               }
            }
         case 5:          // if line 4, a carriage return goes to ....
            {
            if (lsb == 0 && LCD_LINES == 0x02)
               {
               lcd_cmd(0x80); break;
               }
            else if (lsb == 0 && LCD_LINES == 0x04)
               {
               lcd_cmd(0x90);break;
               }
            else
               {
               lcd_cmd(0x80);break;      //line 1
               }
            }
         default:
            lcd_getposition(msb, lsb);
            //printf("%u %u \r\n",msb,lsb);
            //printf("no match\n");
         }
      }
//   else if (b == '\c')
//            lcd_cmd(0x01);   // clear the display, has a bug. Any c sent (instead of \c) clears the display
        else
   {
   if (IsLumex1x16)
      {
      lcd_getposition(msb,lsb);
      if (lsb == 8)
         lcd_gotoxy(2,0);      
      }
   
        lcd_char(b);
   }
    }
//    if (disp_serial)
//    {
//        if (b == '\n')
//            putchar('\r');
//        putchar(b);
//    }
}

/* Display a byte in unsigned decimal format */
void disp_decbyte(BYTE b)
{
    printf(displays, "%u", b);
}

/* Initialise the LCD */
void init_lcd(void)
{
    int i;
   
    LCD_E = 0;                    /* Clear LCD clock line */
    DATA_TO_LCD;                  /* Ensure RS and RD lines are O/Ps */
    LCD_RD = LCD_RS = 0;
    delay_ms(15);                 /* Ensure LCD is stable after power-up */ 
    for (i=0; i<3; i++)           /* Force into 4-bit mode */
    {
        lcd_nybble(0x3);
        delay_ms(5);
    }
    lcd_nybble(0x2);
    delay_ms(5);

    lcd_cmd(0x28);                  /* Set 4-bit mode, 2 lines, 5x7 dots */
    lcd_cmd(0x08);                  /* display off */
    lcd_cmd(0x01);                  /* clear display */
    lcd_cmd(0x06);                  /* incrementing cursor,  cursor */
    delay_ms(10);
    lcd_cmd(0x0c);                  /* display on,no cursor blink, no char blink, to home pos */

}



/* Send a command byte to the LCD as two nybbles */       
void lcd_char(BYTE b)
{               
    DATA_TO_LCD;
    LCD_RD = 0;
    LCD_RS = 1;
    lcd_byte(b);
}

/* Send a command byte to the LCD as two nybbles */       
void lcd_cmd(BYTE b)
{             
    DATA_TO_LCD;
    LCD_RD = LCD_RS = 0;
    lcd_byte(b);
    if ((b & 0xfc) == 0)
        delay_ms(2);
}

/* Send a command byte to the LCD as two nybbles */       
void lcd_byte(BYTE &b)
{
    lcd_nybble(b >> 4);
    lcd_nybble(b);
    DATA_FROM_LCD;
    delay_us(40);
}

/* Send a command byte to the LCD as one nybble */       
void lcd_nybble(BYTE b)
{
    DATA_TO_LCD;
    LCD_E = 1;
    LCD_DATA = b;
    LCD_E = 0;
}



/* Go to an X-Y position on the display, top left is 1, 1
For the Samsung/Hitachi IC's the address for the start of each row is
1   00   1aaa aaaa = 1000 0000 = 0x80
2   40   1aaa aaaa = 1100 0000 = 0xc0
3   10   1aaa aaaa = 1001 0000 = 0x90
4   50   1aaa aaaa = 1101 0000 = 0xd0
*/
void lcd_gotoxy(unsigned int x, unsigned int y)
{
   int position;                       
   if (x == 1)
           position = 0x80;
   else if (x == 2)
      position = 0xc0;
    else if (x == 3)
      position = 0x90;
   else
      position = 0xd0;

   position += y;
   lcd_cmd(position);
}

//////////////////////////////////////////////////////

/* get the current cursor position from the LCD controller.
if the last printed position is on the end of a line, the cursor increments to the next
location which may not be the next row down. check address mapping for lcd controller
*/

void lcd_getposition(byte &MSB, byte &LSB)
{
      DATA_FROM_LCD;
      LCD_RD = 1;
      LCD_RS = 0;

      LCD_E = 1;
          MSB = LCD_DATA;   // MSB of address of current position
          LCD_E = 0;

      LCD_E = 1;
          LSB = LCD_DATA;   // LSB of address of current position
          LCD_E = 0;

}


Dan
w2drz



Joined: 27 Dec 2006
Posts: 55
Location: Western New York - USA

View user's profile Send private message Visit poster's website

code doesn't work on every 16f688
PostPosted: Thu May 24, 2007 4:28 pm     Reply with quote

Had simular problem with new PICC's failing to operate.

suggest to look at xtal overdrive problem.

tom
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 24, 2007 6:03 pm     Reply with quote

What specific line (or lines) in main() do you have to comment out,
to get the LCD to display something ?


(To answer the post above, he's not using a crystal. He's using the
internal 8 MHz oscillator. There's no overdrive issue in that case).
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu May 24, 2007 7:48 pm     Reply with quote

One of the last things I did before finishing up for the day was to back out the code until the display started working again. I had commented out ALL references to serial comms except the #use Rs232 ... and the display still didn't work, I then commented out the #use rs232 and the display started working.

I will re-verify this tomorrow when I get back in, but I'm pretty sure that was the case.

Your previous comment regarding the errata made so much sense because I have been witnessing a lot of strange cases where code that finally works on one micro doesn't necessarily work on all of them (all being 16f688's). Even so, I look forward to finding a solution but I running out of places to look.


Thanks for your help on this.

Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Fri May 25, 2007 6:29 am     Reply with quote

Ok, I think I'm going to chalk this last issue up to a bad chip since I broke out 5 fresh parts and they all program and operate correctly. Not sure what could have become damaged as the uart and the LCD work independently?? Just not together.

I'm very wary about using this part though as I did observe fresh parts operating differently with the same hex files prior to this. This last round of problems I had continued to use the same parts over and over again so my bad there I guess.

Any ideas on what could damage the part so certain ports get tri-stated? This was the first time I tried a 2 transistor interface (BS170's) to rs-232 instead of the maxim level shifters.

Many thanks to all.

Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Fri May 25, 2007 7:48 am     Reply with quote

Trying not to beat a dead horse but I was able to modify the test code to make minimal changes to get the LCD to display. I simply commented out the INT_RDA code segment, every other segment of code relating to the uart is in place including the #use rs232:
Code:

///////////////////////////////////////////////////
// serial port ISR
/*
#int_rda
rda_isr(){
   static int t;
   
        if(kbhit()){
         buffer[next_in] = getc();
         if (buffer[next_in] == 'c')
            config = 1;
         t = next_in;
         next_in = (next_in + 1) % BUFFER_SIZE;
         if (next_in == next_out)
            next_in = t;      // buffer full
      }
}
*/


and the LCD started to work again. Not sure if this helps, maybe it might spark a thought
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Fri May 25, 2007 7:55 am     Reply with quote

just for giggles, try taking out the if(kbhit){} part.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Fri May 25, 2007 7:59 am     Reply with quote

Acutally, I added that code for haha's. It's not there normally but in deperate times .....

Thanks though, I'm willing to try anything as my curiosity is killing me more than anything else at this point. I wonder if I should try a crystal osc instead of the internal RC, since the RC tolerance could vary from chip to chip?

It's starting to look as though binary is no longer just 0's and 1's Wink
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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