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

[resolved] can't disable uart

 
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

[resolved] can't disable uart
PostPosted: Wed May 23, 2007 11:31 am     Reply with quote

I'm trying to write an application that will share 2 pins from a 16f688 between the uart and a LCD module. On power up, I check to see if a special character ('C') is receive in the serial buffer, if not the uart is disabled and the pins are used for the LCD.

If the character is detected, the serial port is used until a quit character is generated and then again the uart is disabled and the LCD is init'd and then used until power is removed.

My code is listed below, shortened as much as possible to show the problem, which is: if I leave a getc in that last function in place I am not able to fully disable the uart and the LCD won't function, cleared but won't display characters. If I comment the getc out, the entire code sample works properly minus the function the was commented out.

CCS PCM C Compiler, Version 4.018

I know there is a bit of code here, but this is the only way I can show the issue.

Code:

//   Dan King                           ////
//                                    ////
//   4/11/2007                           ////
////////////////////////////////////////////////////

#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)

////////////////////////////////////////////////////
// Constants and variables
//PortA      0      
//         1      
//         2      LCD - enable
//         3      not used - in only
//         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    
#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 6
#BIT   LCD_RD          = PORTC.4
#BIT   LCD_RS          = PORTC.5

#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;

int      i;

#define      BUFFER_SIZE 16
#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();


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

 
void main(){
   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);

   if (!config){                     //no config char so disable uart
      disable_interrupts(INT_RDA);      //no serial comms so no int
      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);
   }
   else
      printf("\r\n ready for config\r\n");   

// loop until reset
   while(1){
      if (config){
         if (bkbhit)
            execute_cmd();   
      }
      else{
         lcd_cmd(0x01);               //clear the display
         lcd_gotoxy(1,2);
         printf(displays,"Temp");
         
          delay_ms(500);
      }
   }   
}
///////////////////////////////////////////////////
// serial port ISR
#int_rda
rda_isr(){
   static int t;
   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
}

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

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


// 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");
         meas = get_16b_num();

         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 = getchar();            //causes problems !!!!!
        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);
}


I hope someone has the time to review and I appreciate any assistance.

Rgds,

Dan


Last edited by dan king on Wed May 23, 2007 2:14 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 23, 2007 1:06 pm     Reply with quote

Are you calling the function with the getc() in it ?
In other words, is your program hanging on the getc() statement ?

The getc() function waits in a polling loop until a character is available
from the UART.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed May 23, 2007 1:13 pm     Reply with quote

I only call the function with the getc if the serial port has been accessed using the 'C' character, otherwise the function "should" never be called after that.

Waiting while using the getc is desireable in this case since I'm doing nothing but waiting for user input _if_ the serial port has been accessed.

I'm using this to allow a user to change some alarm threshold values, that are stored in eeprom memory. The only time they have a chance to do this is upon power up, and then they only have a 2 second window to type the 'C' character using hyperterm. If they miss that window, I want the uart to be completely disabled since I then use these same pins for the LCM.

BTW - if the serial port is not to be accessed, there isn't any rs-232 hardware connected to the pins, they only route to the LCM at that point.

Thanks.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed May 23, 2007 1:49 pm     Reply with quote

You need a timed loop with kbhit() sensing as PCM suggested, something like this:

Code:

 x = 100;
 
 do {
     x--;
     if(kbhit()
       { c = getchar();  }

     if(c>='0' && c<='9')
       {
        if( n < sizeof(buff))
          { buff[n++] = c;
            putchar(c);             
          }
       }
     else
       { x = 0;}       //  To quit when receive a char 
   
     delay_ms(10);  //  Trimm this delay according to your need
   }while (x);
 



Humberto
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed May 23, 2007 1:58 pm     Reply with quote

Hi Humberto,

I think I misled you with my last post. The function with the getc that is causing the problem isn't the routine to detect if the 'C' was pressed, that's handled in the INT_RDA interrupt handler. After 2 seconds if I don't receive that char 'C' the uart should be completely disabled.

The routine that is causing the problem (get_16b_num), shouldn't even be called after the 2 second timeout but for some reason, if I comment out the getc in it the code works for the lcd module, that's why I think the uart is not being completely disabled.

Thanks and let me know if I'm still not seeing the light Smile

Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

[resolved] can't disable uart
PostPosted: Wed May 23, 2007 2:14 pm     Reply with quote

I think the real reason for the problem was poorly structured code. After looking through the structure in the main loop I can now see that the compiler probably was "confused" on what I was trying to do and therefore was re-implementing the serial port when I expected it wasn't. The code below is simply re-arranged and works properly now.

I only included the main section of the code since that is really the only section that needed to be altered.

Thanks for the help.

Dan


Code:

void main(){
   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 (bkbhit)
         execute_cmd();   
   }

   if (!config){                     //no config char so disable uart
      disable_interrupts(INT_RDA);      //no serial comms so no int
      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);
   }
   //else
      //printf("\r\n ready for config\r\n");   

// loop until reset
   while(1){
      
         lcd_cmd(0x01);               //clear the display
         lcd_gotoxy(1,2);
         printf(displays,"Temp");
         
          delay_ms(500);
   }   
}
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