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

PIC18F1320 Hardware RS232 Problem

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



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

PIC18F1320 Hardware RS232 Problem
PostPosted: Thu Apr 20, 2006 2:57 pm     Reply with quote

If B0 is used for the receive pin, serial characters are received. If B4 is used, they are not. CCS version 3.214

Any ideas, anyone? Thanks.

Code:

#include <18F1320.h>
#use delay(clock=8000000)
#fuses NOWDT, INTRC, NOFCMEN, NOBROWNOUT, NOPUT,
#fuses NOCPD, NOSTVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTC,
#fuses NOEBTR, NOEBTRB, NOPROTECT, NOCPB, NOWRTB

#use rs232(baud=9600,parity=N,xmit=PIN_B1,rcv=PIN_B4)
// If B0 is used for the receive pin, then it works.

void main()
{
  char number;                //variable used to send number to chip-B
  setup_adc_ports(0);         //no analog
  setup_oscillator(osc_8mhz); //internal oscillator

  set_tris_a(0x00);
  set_tris_b(0x10);        //input is PIN_B4 for RCV
  //set_tris_b(0x01);      //input is PIN_B0 for RCV
  output_a(0b00000000);
  output_b(0b00000000);

  while (1)             
  {
    number = getc();
    output_toggle(pin_b6);  //toggles LED when receiving
   // otherwise gets stuck in getc().
   // Only works if B0 is used for the receive pin.
  }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 20, 2006 3:29 pm     Reply with quote

If you use Pin B4 for receive (and B1 for xmit), the compiler will
generate code for the hardware UART.

In the EUSART section of the 18F1320 data sheet, it says that to
setup the UART, you must do the following with regard to TRIS:
Quote:
• TRISB<4> bit must be set ( = 1) and
• TRISB<1> bit must be set ( = 1).

But in your program, you have got this statement:
Code:
output_b(0b00000000);


If you look at the generated code in the .LST file, you'll see that
the output_b() function sets the TRIS for Port B to all zeros, which
means all outputs. This violates the UART setup requirement
as stated above.
Quote:
... output_a(0b00000000);
0086: MOVLW 00
0088: MOVWF TRISA
008A: CLRF LATA
... output_b(0b00000000);
008C: MOVWF TRISB
008E: CLRF LATB


You're using CCS's "standard i/o" mode. This is the default mode
of the compiler. In that mode, if you use the CCS port and pin i/o
functions, the compiler will automatically set the TRIS for you.


I would revise your program as shown below.

1. Move the setup_oscillator() function to the first line in the program.
You're setting up the oscillator, so it makes sense to do this immediately.

2. Use the proper CCS constants for the setup_adc_ports() function.
Don't use "magic numbers", such as 0, as a parameter.

3. Get rid of all the TRIS stuff. You don't need it. The CCS library
code will handle setting up the TRIS for the UART.

4. Since you're using toggle_pin() later in the program, you need
to initialize that one pin. So just use "output_low(PIN_B6)" to do this.

5. It's the custom in the C language to use all caps for constants.
You should follow this.

Code:
void main()
{
char number;   

setup_oscillator(OSC_8MHZ); 
setup_adc_ports(NO_ANALOGS);   

output_low(PIN_B6);

while (1)             
  {
   number = getc();
   output_toggle(PIN_B6);
  }
}
Storic



Joined: 03 Dec 2005
Posts: 182
Location: Australia SA

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

PostPosted: Thu Apr 20, 2006 6:15 pm     Reply with quote

I have been using the 18F1320 micro and I let the software do the work, (no tris).
Code:
#use rs232(Stream=RS485,baud=9600,xmit=PIN_B1,rcv=PIN_B4,bits=8,enable=PIN_A7)
#use rs232(Stream=Term,baud=9600,xmit=PIN_B7,rcv=PIN_B6,bits=8,DISABLE_INTS)

   ...

   setup_adc_ports(0);
   ...
   setup_oscillator(OSC_8MHZ|OSC_INTRC);




I am using 2 comms (RS485 LAN and a PC interface).
I have not setup the PC coms to recieve only to display on PC via hyperterminal
Code:
   fprintf(Term,"Unit %u>...........",...... );


I am still working on my RS485 LAN.

Andrew
_________________
What has been learnt if you make the same mistake? Wink
johnl



Joined: 30 Sep 2003
Posts: 120

View user's profile Send private message

PostPosted: Sun Apr 23, 2006 7:06 pm     Reply with quote

PCM Programmer,

Yes, it was the output instruction causing the pin direction to change. What threw me was the fact that it wasn't a problem when the software serial connnection was used.

Storic,

Your idea of letting the compiler do the tris work is helpful.

Thanks to both.

Problem solved.

Johnl
rina_1220



Joined: 02 Oct 2007
Posts: 20

View user's profile Send private message

PostPosted: Tue Nov 20, 2007 10:06 am     Reply with quote

I have tested the following code
Code:

#include <18f1320.h>

#FUSES   INTRC_IO, NOWDT, NOPROTECT, PUT, NOBROWNOUT, NOLVP, NOMCLR, NOFCMEN, NOSTVREN, DEBUG

#use delay(clock=4000000)
#use rs232(baud=9600, bits=8, parity=N, xmit=PIN_B1, rcv=PIN_B4)

void main()
{
   char number;
   setup_oscillator(OSC_4MHZ);
   
   output_low(PIN_B3);

   while (1)             
   {
      //number = getc();
      while(!kbhit());
      output_toggle(PIN_B3);
   }
}


but it only works when i use "getc()" instead of kbhit(). kbhit never works. Or it gets stuck or it always returns 1, no matter if i've pressed the keyboard or not.
But when I change the TX pin OR the RX pin, instead of usin the hardware ones it works fine. why's that?

I need to use kbhit, cause i have to do a timed-out getc (actually i have it working for pic16F876A, but i need to use it in pic18f1320), so the program must not be stuck on that line forever
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 20, 2007 11:22 am     Reply with quote

I'll show you how to research this.

Put both lines of code into the program. In the Project Options, set
the .LST file to be in Symbolic format. Compile the program. Then
look at the .LST file.

You immediately see that getc() includes doing a call to kbhit().
But it does one thing more. It actually gets the character from
the UART. This will clear the "character ready" flag inside the UART.
(Assuming there is only one character in the UART's receive fifo).
Simply doing a kbhit() does not do this. This behavior is described
in the PIC data sheet.
Code:

...    while (1)               
...    { 
...       number = getc(); 
0036:  BTFSS  PIR1.RCIF
0038:  BRA    0036
003A:  MOVFF  RCREG,number

...       while(!kbhit()); 
003E:  BTFSS  PIR1.RCIF
0040:  BRA    003E
....................       output_toggle(PIN_B3); 
0042:  BCF    TRISB.3
0044:  BTG    LATB.3
....................    } 
0046:  BRA    0036
.................... } 
rina_1220



Joined: 02 Oct 2007
Posts: 20

View user's profile Send private message

PostPosted: Tue Nov 20, 2007 12:37 pm     Reply with quote

is this just PIC18 family that has this behavior? I have never seen it happen with PIC16F
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 20, 2007 12:41 pm     Reply with quote

Just research it in the same way.
rina_1220



Joined: 02 Oct 2007
Posts: 20

View user's profile Send private message

PostPosted: Thu Nov 22, 2007 6:08 am     Reply with quote

I think I did understand.
Thanks
Ttelmah
Guest







PostPosted: Thu Nov 22, 2007 8:12 am     Reply with quote

It is worth perhaps explaining what is happening 'below the skin'.

First start with what async serial data 'is'.
The line idles 'high', and drops to signal a 'start'.

The hardware serial, when it sees this 'low', will automatically start clocking in the data, and (depending on the word length selected), typically 9 bit times latter, will set it's 'buffer full' flag, to say that it has received a character.
Kbhit, reflects this flag. This flag will _remain_ set, _till the character is read_.
This flag will typically be set soon after the chip wakes up (since if you use a MAX232 chip, it takes a little while to raise the line). Hence it is worth performing a 'if kbhit' test near the start of the program, and receiving the 'garbage' first character, to clear the buffer.

For software serial, all 'kbhit' reflects, is the level of the line. If it is high, kbhit will return 'false', while if it is low, kbhit will return 'true'. If you repeatedly call kbhit, on a software serial line, without calling getc, eventually the line will go high, and kbhit will switch to returning 'false'. On the hardware serial, this _will not happen_, till the character is read.

Getc, on the hardware serial, will return a character if one is waiting, and then exit immediately. If one is not waiting, it'll wait till one arrives.

Getc, on the software serial, will wait till the line goes low, and then clock in a character, and return.

Now, on the 'TRIS', the key is that both kbhit, and getc, actually read the I/O pin. In CCS, if you read a pin, and standard_io mode is selected, the compiler automatically sets the TRIS. For the hardware UART, it set the TRIS during the chip's initialisation, and then the original code overrode this...

Best Wishes
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