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 support@ccsinfo.com

Software UART on 18LF4550 receives, but does not send

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







Software UART on 18LF4550 receives, but does not send
PostPosted: Tue Apr 04, 2006 10:25 am     Reply with quote

I'm baffled with this; hopefully someone can see an obvious error that I must be overlooking. I'm simply testing basic "echo back the input" serial comms before integrating into another design, but am stuck here...

Hardware: PDIP 18LF4550 connected through a MAX232 level shifter to a PC serial port. I'm set up to use software RS232 on D1 (Rx) and D2 (Tx) because I want the hardware SPI and the SDO pin is shared with the hardware UART.

Software: RealTerm serial monitor program

Results: Consistently, the PIC sends its 'header' information ('Running...' and 'Buffered data =>') that should come back ahead of the bytes that were sent; however, it never echoes back the bytes that I sent to it. It's as though the PIC is not receiving what I send to it through the PC--so either the bytes aren't getting to the PIC or the PIC is not processing them correctly (either in the circuit or in the embedded code)

I've changed the TRISD to be inputs and outputs accordingly (they're set to all inputs in the attached code, but I've tried all outputs and Rx=input/Tx=output); switched the Rx and Tx pins (in the code as well as hardware) with the same result mentioned above.

Serial.c code listing:

Code:
#include "Serial.h"

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;

#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

void main() {

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(VREF_LOW|-2);
   setup_low_volt_detect(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_TIMER1|OSC_PLL_OFF);

   // Set the ports to outputs
   set_tris_a( 0x00 );
   set_tris_b( 0x00 );
   set_tris_c( 0x00 );
   set_tris_d( 0xff );

   enable_interrupts(global);
   enable_interrupts(int_rda);

   printf("\r\n\Running...\r\n");

               // The program will delay for 10 seconds and then display
               // any data that came in during the 10 second delay

   do {
      delay_ms(3000);
      printf("\r\nBuffered data => ");
      while(bkbhit)
        putc( bgetc() );
   } while (TRUE);
}



Serial.h code listing:
Code:

#include <18F4550.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT_NOSL            //Brownout enabled during operation, disabled during SLEEP
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1                     //No PLL PreScaler

#use delay(clock=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_D2,rcv=PIN_D1,bits=8)

Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Apr 04, 2006 10:51 am     Reply with quote

#int_rda is the hardware interrupt. You cannot use it with a software interrupt. I would probably bit bang the SPI instead of having to support a software uart.
dmendesf



Joined: 31 Dec 2005
Posts: 30

View user's profile Send private message

PostPosted: Tue Apr 04, 2006 1:48 pm     Reply with quote

Really you should use the hardware serial and software spi... in SPI a slave never starts talking without being requested, and in serial communicatios this is pretty common. In order to kbhit() work in a software serial you must cal it like 10x the baud rate... I´ts difficult to write a program like that (say goodbye to a lot of delays...). Just my opinion. The other parent is right about the serial interrupt too: it only works with a hardware serial.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 04, 2006 1:58 pm     Reply with quote

If you did want to create a receiver interrupt for a soft UART,
people normally use INT_EXT on Pin B0 for this.
MJ
Guest







Thanks very much
PostPosted: Tue Apr 04, 2006 2:08 pm     Reply with quote

All are good points--hardware vs software interrupts, using hardware UART and bit-banging the SPI, and using an external interrupt for software UART. I wish I had posted this request before I made prototype PCBs that implement it as-shown above.. Argh. Live and learn I guess.

I guess I'm still a bit confused why it's not responding to the externally-transmitted data, though--is it not getting into the kbhit() buffer because I'm not using the hardware UART?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 04, 2006 2:18 pm     Reply with quote

You're checking the bkbhit macro in your loop. Since you're not using
the hardware UART receiver pin, there will never be a receiver interrupt.
With no interrupt, the #int_rda isr is never called and therefore
next_in and next_out always stay equal, and bkbhit will always be false.

If you want to see it do something, use some code like this:
Code:

char c;

while(1)
  {
    c = getc();
    putc(c);
  }
dmendesf



Joined: 31 Dec 2005
Posts: 30

View user's profile Send private message

PostPosted: Tue Apr 04, 2006 2:20 pm     Reply with quote

It's not working because the interrupt is never called... so you never call getc(). Try this: (I'm not promising that it will work, neither that it will scale up to a full program)
Code:

#include "Serial.h"

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
int t;

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}

void main() {

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(VREF_LOW|-2);
   setup_low_volt_detect(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_TIMER1|OSC_PLL_OFF);

   // Set the ports to outputs
   set_tris_a( 0x00 );
   set_tris_b( 0x00 );
   set_tris_c( 0x00 );
   set_tris_d( 0xff );

   enable_interrupts(global);
   enable_interrupts(int_rda);

   printf("\r\n\Running...\r\n");

               // The program will delay for 10 seconds and then display
               // any data that came in during the 10 second delay

   do {
      delay_ms(3000);
      printf("\r\nBuffered data => ");
      while(bkbhit)
        putc( bgetc() );
   } while (TRUE);
}
MJ
Guest







PostPosted: Tue Apr 04, 2006 3:33 pm     Reply with quote

Ahh--that makes sense now; I'll give it a shot in a little bit and let you know. Thanks again!
MJ
Guest







PostPosted: Wed Apr 05, 2006 11:35 am     Reply with quote

Thanks to all for the help--here's what I've found out...

Interrupt: No interrupt is being called because I'm not using the hardware UART and I haven't designated anything else to call it (such as interrupt-on-change pin). Therefore, dmendesf's suggested code change did not work for this reason (but I do appreciate the input).

Polling: PCM programmer's code suggestion did work because it's constantly polling for any changes in the UART module, even though it's software-driven. If I changed nothing in the hardware setup, this is the route I'd have to go (polling continuously for changes). I guess an alternative would be to use another interrupt source such as PIN_B0.

I'm going to change my design to implement hardware UART and bit-banged serial primarily b/c my usage scenario has the UART always ready to receive (so I can expect things asynchronously), whereas the SPI controls an A/D chip. I control when the A/D chip performs its conversions, so had I recognized that difference in control schemes earlier I would have designed it differently.

Thanks for all the input,
Jeff
dmendesf



Joined: 31 Dec 2005
Posts: 30

View user's profile Send private message

PostPosted: Wed Apr 05, 2006 6:27 pm     Reply with quote

MJ wrote:
Thanks to all for the help--here's what I've found out...

Interrupt: No interrupt is being called because I'm not using the hardware UART and I haven't designated anything else to call it (such as interrupt-on-change pin). Therefore, dmendesf's suggested code change did not work for this reason (but I do appreciate the input).



I've modified your code to NOT use interrupts, so if it's now working it's because your queue algorithm doesn't work (or I've introduced a bug in it, but I doubt that). Think again: where in that code an interrupt is being serviced? I'm only talking about this because probably you have misunderstood what the interrupts does, so your doubt persists...
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