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

TTL serial link?

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







TTL serial link?
PostPosted: Mon Mar 24, 2003 8:47 am     Reply with quote

Hello All
Iím not having to good of luck!
What Iím trying to do is a TTL serial link.
The link is only one direction that is one PIC16F876 to another PIC16F876.
The max distance is 6í so I think that this will work just fine.
Will I know that it will work because I have had it working some?
But it will not work consistently.
This is what I have the xmit PIC is using pin B2 to transmit on and the receive PIC is receiving on pin C7. I also have the two system grounds connected to each other.
This is what is happening is that some times the receiving PIC will work just fine.
This is only just after start up and this is not consistent.
I can never get it to work if I start the receiver and then start the transmitter.
The transmitter hardware and software are all ways consistent and working I have tested this on another system.
It is like the receiver interrupting is not working or getting hung up.
The heartbeat LED are working all the time so I know that the PIC is running.
I have some of the LCD lines on port C but this is C0 to C3.
Will this be an issues with C7 my receive pin?
Will some of you guys look at this code and see if Iím missing some thing.

Thank you

Main Code:
#include <16F876.h>
#device PIC16F876 *=16
//#device CCSICD=True
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

#include <lcdcal.c>

#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7)
#define BUFFER_SIZE 32
byte buffer[BUFFER_SIZE];
byte next_in = 0;
byte next_out = 0;



#define HB_Low output_low(Pin_A5) //LED on pin 7 A5 output low
#define HB_High output_high(Pin_A5) //LED on pin 7 A5 output high
#define ints_per_ms 30 //The number of times that timer0 interrupts for 300ms heartbeat
#define bkbhit (next_in!=next_out)

static short int HBLED;
static int ms_count = ints_per_ms; //Set ms count for the 500ms heartbeat

#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 !!
}

#int_timer0
void heart_timer0() //This is the interrupt handler for the heartbeat
{
if ( --ms_count == 0 ) {
ms_count = ints_per_ms; //Reset the Ms counter for interrupt

if (HBLED == True) { //Test if Heartbeat LED is on
HB_Low; //Turns off HeartBeat LED
HBLED = False; //Set HBLED flag to false LED off
}
else { //Heartbeat LED is off
HB_High; //Turns on HeartBeat LED
HBLED = True; //Set HBLED true to false LED off
}
}
}


//Do not use getc in this program!!!
//Use this function to get serial input data
byte bgetc() { //Function used to get data from serial buffer
byte c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) \% BUFFER_SIZE;
return(c);
}



main() {

// port_b_pullups(TRUE); //Turns on week pulls up on port B for

lcd_init();

enable_interrupts(global);
enable_interrupts(int_RDA);
enable_interrupts(INT_Timer0); //Turns On Timer0 interrupt for Heartbeat LED

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 ); //Setup timer0 for button debounce
set_timer0(195); //Set timer0 for 10ms interrupt 9.984e-3 error for 10ms is 16us

lcd_putc(" Calibration Display");
delay_ms(3000);
printf(lcd_putc,"\f" );
while(bkbhit)
lcd_putc( bgetc() );
Delay_ms(500);
printf(lcd_putc,"\f" );

while (TRUE) {
delay_ms(50);
while(bkbhit)
lcd_putc( bgetc() );

}//While True
}//Main


LCD Driver Code:

// As defined in the following structure the pin connection is as follows:
// A0 enable
// A1 rs
// A2 rw
// C0 D4
// C1 D5
// C2 D6
// C3 D7
//
// LCD pins D0-D3 are not used.


struct lcd_pin_map { // This structure is overlayed
int data : 4; // on to an I/O port to gain
// boolean unused; // access to the LCD pins.
// boolean unused; // The bits are allocated from
// boolean unused; // low order up. ENABLE will
// boolean unused; // be pin B0.
} lcd;

/* Use #byte to assign variables to a RAM locations */
#use fast_io ( A ) /* don't set TRIS on each I/O statement */
#byte PORT_A = 5 /* set variable that maps to memory */
#byte lcd = 7 // Data lines on to port c (at address 7)
#bit enable = PORT_A.0
#bit rs = PORT_A.1
#bit rw = PORT_A.2

#define set_tris_lcd(x) set_tris_c(x)

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line


byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.

// The following are used for setting
// the I/O port direction register.

STRUCT lcd_pin_map const LCD_WRITE = {0x0}; // For write mode all pins are out
STRUCT lcd_pin_map const LCD_READ = {0xF}; // For read mode data pins are in




byte lcd_read_byte() {
byte low,high;
set_tris_lcd(LCD_READ);
rw = 1;
delay_cycles(1);
enable = 1;
delay_cycles(1);
high = lcd.data;
enable = 0;
delay_cycles(1);
enable = 1;
delay_us(1);
low = lcd.data;
enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}


void lcd_send_nibble( byte n ) {
lcd.data = n;
delay_cycles(1);
enable = 1;
delay_us(2);
enable = 0;
}


void lcd_send_byte( byte address, byte n ) {

rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
rs = address;
delay_cycles(1);
rw = 0;
delay_cycles(1);
enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}


void lcd_init() {
byte i;
set_tris_A( 0x00 );
set_tris_lcd(LCD_WRITE);
rs = 0;
rw = 0;
enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( byte x, byte y) {
byte address;

if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}

char lcd_getc( byte x, byte y) {
char value;

lcd_gotoxy(x,y);
rs=1;
value = lcd_read_byte();
rs=0;
return(value);
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 12998
R.J.Hamlett
Guest







Re: TTL serial link?
PostPosted: Mon Mar 24, 2003 9:11 am     Reply with quote

:=Hello All
:=Iím not having to good of luck!
:=What Iím trying to do is a TTL serial link.
:=The link is only one direction that is one PIC16F876 to another PIC16F876.
:=The max distance is 6í so I think that this will work just fine.
:=Will I know that it will work because I have had it working some?
:=But it will not work consistently.
:=This is what I have the xmit PIC is using pin B2 to transmit on and the receive PIC is receiving on pin C7. I also have the two system grounds connected to each other.
:=This is what is happening is that some times the receiving PIC will work just fine.
:=This is only just after start up and this is not consistent.
:=I can never get it to work if I start the receiver and then start the transmitter.
:=The transmitter hardware and software are all ways consistent and working I have tested this on another system.
:=It is like the receiver interrupting is not working or getting hung up.
:=The heartbeat LED are working all the time so I know that the PIC is running.
:=I have some of the LCD lines on port C but this is C0 to C3.
:=Will this be an issues with C7 my receive pin?
:=Will some of you guys look at this code and see if Iím missing some thing.
:=
:=Thank you
:=
:=Main Code:
:=#include <16F876.h>
:=#device PIC16F876 *=16
:=//#device CCSICD=True
:=#fuses HS,NOWDT,NOPROTECT,NOLVP
:=#use delay(clock=20000000)
:=
:=#include <lcdcal.c>
:=
:=#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7)
:=#define BUFFER_SIZE 32
:=byte buffer[BUFFER_SIZE];
:=byte next_in = 0;
:=byte next_out = 0;
:=
:=
:=
:=#define HB_Low output_low(Pin_A5) //LED on pin 7 A5 output low
:=#define HB_High output_high(Pin_A5) //LED on pin 7 A5 output high
:=#define ints_per_ms 30 //The number of times that timer0 interrupts for 300ms heartbeat
:=#define bkbhit (next_in!=next_out)
:=
:=static short int HBLED;
:=static int ms_count = ints_per_ms; //Set ms count for the 500ms heartbeat
:=
:=#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 !!
:=}
:=
:=#int_timer0
:=void heart_timer0() //This is the interrupt handler for the heartbeat
:={
:= if ( --ms_count == 0 ) {
:= ms_count = ints_per_ms; //Reset the Ms counter for interrupt
:=
:= if (HBLED == True) { //Test if Heartbeat LED is on
:= HB_Low; //Turns off HeartBeat LED
:= HBLED = False; //Set HBLED flag to false LED off
:= }
:= else { //Heartbeat LED is off
:= HB_High; //Turns on HeartBeat LED
:= HBLED = True; //Set HBLED true to false LED off
:= }
:= }
:=}
:=
:=
:=//Do not use getc in this program!!!
:=//Use this function to get serial input data
:=byte bgetc() { //Function used to get data from serial buffer
:= byte c;
:= while(!bkbhit) ;
:= c=buffer[next_out];
:= next_out=(next_out+1) \% BUFFER_SIZE;
:= return(c);
:=}
:=
:=
:=
:=main() {
:=
:=// port_b_pullups(TRUE); //Turns on week pulls up on port B for
:=
:= lcd_init();
:=
:= enable_interrupts(global);
:= enable_interrupts(int_RDA);
:= enable_interrupts(INT_Timer0); //Turns On Timer0 interrupt for Heartbeat LED
:=
:= setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 ); //Setup timer0 for button debounce
:= set_timer0(195); //Set timer0 for 10ms interrupt 9.984e-3 error for 10ms is 16us
:=
:= lcd_putc(" Calibration Display");
:= delay_ms(3000);
:= printf(lcd_putc,"\f" );
:= while(bkbhit)
:= lcd_putc( bgetc() );
:= Delay_ms(500);
:= printf(lcd_putc,"\f" );
:=
:=while (TRUE) {
:= delay_ms(50);
:= while(bkbhit)
:= lcd_putc( bgetc() );
:=
:= }//While True
:=}//Main
:=
:=
:=LCD Driver Code:
:=
:=// As defined in the following structure the pin connection is as follows:
:=// A0 enable
:=// A1 rs
:=// A2 rw
:=// C0 D4
:=// C1 D5
:=// C2 D6
:=// C3 D7
:=//
:=// LCD pins D0-D3 are not used.
:=
:=
:=struct lcd_pin_map { // This structure is overlayed
:= int data : 4; // on to an I/O port to gain
:=// boolean unused; // access to the LCD pins.
:=// boolean unused; // The bits are allocated from
:=// boolean unused; // low order up. ENABLE will
:=// boolean unused; // be pin B0.
:= } lcd;
:=
:=/* Use #byte to assign variables to a RAM locations */
:=#use fast_io ( A ) /* don't set TRIS on each I/O statement */
:=#byte PORT_A = 5 /* set variable that maps to memory */
:=#byte lcd = 7 // Data lines on to port c (at address 7)
:=#bit enable = PORT_A.0
:=#bit rs = PORT_A.1
:=#bit rw = PORT_A.2
:=
:=#define set_tris_lcd(x) set_tris_c(x)
:=
:=#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
:=#define lcd_line_two 0x40 // LCD RAM address for the second line
:=
:=
:=byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
:= // These bytes need to be sent to the LCD
:= // to start it up.
:=
:= // The following are used for setting
:= // the I/O port direction register.
:=
:=STRUCT lcd_pin_map const LCD_WRITE = {0x0}; // For write mode all pins are out
:=STRUCT lcd_pin_map const LCD_READ = {0xF}; // For read mode data pins are in
:=
:=
:=
:=
:=byte lcd_read_byte() {
:=byte low,high;
:= set_tris_lcd(LCD_READ);
:= rw = 1;
:= delay_cycles(1);
:= enable = 1;
:= delay_cycles(1);
:= high = lcd.data;
:= enable = 0;
:= delay_cycles(1);
:= enable = 1;
:= delay_us(1);
:= low = lcd.data;
:= enable = 0;
:= set_tris_lcd(LCD_WRITE);
:= return( (high<<4) | low);
:=}
:=
:=
:=void lcd_send_nibble( byte n ) {
:= lcd.data = n;
:= delay_cycles(1);
:= enable = 1;
:= delay_us(2);
:= enable = 0;
:=}
:=
:=
:=void lcd_send_byte( byte address, byte n ) {
:=
:= rs = 0;
:= while ( bit_test(lcd_read_byte(),7) ) ;
:= rs = address;
:= delay_cycles(1);
:= rw = 0;
:= delay_cycles(1);
:= enable = 0;
:= lcd_send_nibble(n >> 4);
:= lcd_send_nibble(n & 0xf);
:=}
:=
:=
:=void lcd_init() {
:=byte i;
:= set_tris_A( 0x00 );
:= set_tris_lcd(LCD_WRITE);
:= rs = 0;
:= rw = 0;
:= enable = 0;
:= delay_ms(15);
:= for(i=1;i<=3;++i) {
:= lcd_send_nibble(3);
:= delay_ms(5);
:= }
:= lcd_send_nibble(2);
:= for(i=0;i<=3;++i)
:= lcd_send_byte(0,LCD_INIT_STRING[i]);
:=}
:=
:=
:=void lcd_gotoxy( byte x, byte y) {
:=byte address;
:=
:= if(y!=1)
:= address=lcd_line_two;
:= else
:= address=0;
:= address+=x-1;
:= lcd_send_byte(0,0x80|address);
:=}
:=
:=void lcd_putc( char c) {
:= switch (c) {
:= case '\f' : lcd_send_byte(0,1);
:= delay_ms(2);
:= break;
:= case '\n' : lcd_gotoxy(1,2); break;
:= case '\b' : lcd_send_byte(0,0x10); break;
:= default : lcd_send_byte(1,c); break;
:= }
:=}
:=
:=char lcd_getc( byte x, byte y) {
:= char value;
:=
:= lcd_gotoxy(x,y);
:= rs=1;
:= value = lcd_read_byte();
:= rs=0;
:= return(value);
:=}

I think your first problem, is the handling initialisation. What you should do, is have a pull up resistor on the serial line. RS232 idles (at the TTL connections), high. Now with your system, if the receiver wakes up before the transmitter, the line will be floating, till the port pull up is enabled at the transmitter, and the receiver will either see garbage, or a continuous low. This then can leave the receiver in a confused state when the transmitter finally starts.
The second point (which relates to the first), is that if the hardware UART sees characters, before your handler is enabled, or you do not handle the data fast enough, and overrun error can get set. If this happens, the port will stop receiving, till this condition is cleared. You can detect this, by either testing the OERR bit directly, or using the 'ERRORS' ability in the RS232 code. You should add a detect and clear for this, into your receive handler (I suspect this is what is preventing the startup, with the error being set and never cleared).
You are doing a 'set_tris' operation on port C, but have not selected 'fast_io'. Your TRIS will be being overwritten by the default behaviour, and this may well cause unexpected behaviour.

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12999
Thomas Hauff
Guest







Re: TTL serial link?
PostPosted: Mon Mar 24, 2003 9:43 am     Reply with quote

:=I think your first problem, is the handling initialisation. What you should do, is have a pull up resistor on the serial line. RS232 idles (at the TTL connections), high. Now with your system, if the receiver wakes up before the transmitter, the line will be floating, till the port pull up is enabled at the transmitter, and the receiver will either see garbage, or a continuous low. This then can leave the receiver in a confused state when the transmitter finally starts.
:=The second point (which relates to the first), is that if the hardware UART sees characters, before your handler is enabled, or you do not handle the data fast enough, and overrun error can get set. If this happens, the port will stop receiving, till this condition is cleared. You can detect this, by either testing the OERR bit directly, or using the 'ERRORS' ability in the RS232 code. You should add a detect and clear for this, into your receive handler (I suspect this is what is preventing the startup, with the error being set and never cleared).
:=You are doing a 'set_tris' operation on port C, but have not selected 'fast_io'. Your TRIS will be being overwritten by the default behaviour, and this may well cause unexpected behaviour.
:=
:=Best Wishes

Thank You so much for the fast reply R.J. Hamlett
Ok will a 5K or 10K resistor provide enough current for a pull on the RS232 receiver line?
Iím trying to keep the required power down.
Would you be so kind to post an example of testing the OERR bit directly and a example of using this ĎERRORSí for the #use RS232 statement.
Do you have any suggestion on the Ďset_tris_cí issues?

Thank you so much Tom
___________________________
This message was ported from CCS's old forum
Original Post ID: 13003
Steve H
Guest







Input resistance...
PostPosted: Mon Mar 24, 2003 1:55 pm     Reply with quote

Looking at a Maxim MAX232 data sheet you can see thre receiver input resistance listed as 3-7 k ohms. This is probably typical of all RS232 chips out there.

So if you use 3k on a 5 volt supply you will only get 2.5 volts at the receiver, this is just barely above the MAX232's maximum input threshold of 2.4 volts.

Steve H.
___________________________
This message was ported from CCS's old forum
Original Post ID: 13019
Sherpa Doug
Guest







Re: Input resistance...
PostPosted: Mon Mar 24, 2003 2:07 pm     Reply with quote

:=Looking at a Maxim MAX232 data sheet you can see thre receiver input resistance listed as 3-7 k ohms. This is probably typical of all RS232 chips out there.
:=
:=So if you use 3k on a 5 volt supply you will only get 2.5 volts at the receiver, this is just barely above the MAX232's maximum input threshold of 2.4 volts.
:=
:=Steve H.

I believe that 3-7k is on the RS232 side of the chip. The TTL side of the chip should be a standard TTL input which is much higher than 3-7k. I don't think that Mr Hauff is using any converter chips. He is just connecting one PIC pin to another with a piece of wire. So a 10K resistor should be fine.

___________________________
This message was ported from CCS's old forum
Original Post ID: 13022
Thomas Hauff
Guest







Re: Chacking OERR bit?
PostPosted: Mon Mar 24, 2003 2:41 pm     Reply with quote

Hello All
I did not have any luck with the pull up resistor but I have to get it solder in I just used clip leads for now.
Also on luck with the ĎERRORSí word in the #use RS232 statement.
So moving to testing of the OERR bit this is the code Iím have written what do you guys think.
Is this the right road?

#byte RCSTA = 0x18

if (bit_test(RCSTA,1)){
bit_clear(RCSTA,4);
bit_set(RCSTA,4);
}

Thank you all!
Tom
___________________________
This message was ported from CCS's old forum
Original Post ID: 13025
Steve H
Guest







Oops 2
PostPosted: Mon Mar 24, 2003 3:13 pm     Reply with quote

I misread the post. I thought it said PIC to PC connection.

Nevermind!

I'll go hide under my rock now ;-)

Steve H.
___________________________
This message was ported from CCS's old forum
Original Post ID: 13028
R.J.Hamlett
Guest







Re: TTL serial link?
PostPosted: Mon Mar 24, 2003 4:10 pm     Reply with quote

:=:=I think your first problem, is the handling initialisation. What you should do, is have a pull up resistor on the serial line. RS232 idles (at the TTL connections), high. Now with your system, if the receiver wakes up before the transmitter, the line will be floating, till the port pull up is enabled at the transmitter, and the receiver will either see garbage, or a continuous low. This then can leave the receiver in a confused state when the transmitter finally starts.
:=:=The second point (which relates to the first), is that if the hardware UART sees characters, before your handler is enabled, or you do not handle the data fast enough, and overrun error can get set. If this happens, the port will stop receiving, till this condition is cleared. You can detect this, by either testing the OERR bit directly, or using the 'ERRORS' ability in the RS232 code. You should add a detect and clear for this, into your receive handler (I suspect this is what is preventing the startup, with the error being set and never cleared).
:=:=You are doing a 'set_tris' operation on port C, but have not selected 'fast_io'. Your TRIS will be being overwritten by the default behaviour, and this may well cause unexpected behaviour.
:=:=
:=:=Best Wishes
:=
:=Thank You so much for the fast reply R.J. Hamlett
:=Ok will a 5K or 10K resistor provide enough current for a pull on the RS232 receiver line?
:=Iím trying to keep the required power down.
:=Would you be so kind to post an example of testing the OERR bit directly and a example of using this ĎERRORSí for the #use RS232 statement.
:=Do you have any suggestion on the Ďset_tris_cí issues?
:=
:=Thank you so much Tom
A search in the archives here, should find the OERR handler. I posted an example a while ago, and there have been several other threads with this data (look for people talking about having problems with the serial port).
The resistor should be fine (it is only to ensure the line is actually high when undriven). Also since the RS232 idles high, very little power will be drawn.

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 13029
R.J.Hamlett
Guest







Re: Chacking OERR bit?
PostPosted: Mon Mar 24, 2003 4:17 pm     Reply with quote

:=Hello All
:=I did not have any luck with the pull up resistor but I have to get it solder in I just used clip leads for now.
:=Also on luck with the ĎERRORSí word in the #use RS232 statement.
:=So moving to testing of the OERR bit this is the code Iím have written what do you guys think.
:=Is this the right road?
:=
:=#byte RCSTA = 0x18
:=
:=if (bit_test(RCSTA,1)){
:= bit_clear(RCSTA,4);
:= bit_set(RCSTA,4);
:= }
:=
:=Thank you all!
:=Tom
Looks fine. :-)
Remember you can code the same as bits, which I think makes the intention clearer. So:
#bit OERR = 0x18.1
#bit CREN = 0x18.4

if (OERR) {
CREN=false;
CREN=true;
}

May be clearer in the future.
Also you must ensure you remove at least one character from the input buffer (technically there are three waiting if this bit is set), or the fault will recur.

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 13030
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