|
|
View previous topic :: View next topic |
Author |
Message |
dan king
Joined: 22 Sep 2003 Posts: 119
|
[resolved] can't disable uart |
Posted: Wed May 23, 2007 11:31 am |
|
|
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
|
|
Posted: Wed May 23, 2007 1:06 pm |
|
|
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
|
|
Posted: Wed May 23, 2007 1:13 pm |
|
|
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
|
|
Posted: Wed May 23, 2007 1:49 pm |
|
|
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
|
|
Posted: Wed May 23, 2007 1:58 pm |
|
|
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
Dan |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
[resolved] can't disable uart |
Posted: Wed May 23, 2007 2:14 pm |
|
|
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);
}
}
|
|
|
|
|
|
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
|