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

RS232 between 2 PIC

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



Joined: 23 Aug 2005
Posts: 93

View user's profile Send private message Visit poster's website

RS232 between 2 PIC
PostPosted: Fri Feb 27, 2009 9:56 am     Reply with quote

Hi, I got a problem..
I'm trying to connect two Pic's together with RS232.
Its a 18F2525 with HW UART and a 18F97J60 with a SW UART.
The 18F2525 is running on 5V and the 18F97J60 on 3,3V, common GND.
I'm using pin RC6-7 on 18F2525 and RH4-5 on the 18F97J60.
The baudrate is 1200, 8 bits and even parity.
But It seems that the 18F97J60 isn't reading its RCV pin at all.
By using an oscilloscope I can see that its sending to the 18F2525 but not
receiving anything. I'm also using an non inverting buffer driver that makes the 3,3V to 5V on the TX from 18F97J60.
By using another SW uart on the 18F97J60 against a PC I can see that
the pic is working fine, but not against the second pic?
Also the HW UART on the second PIC is working against a PC.
Can it have something to do with the VCC?
Or is there something odd about the two pins RH4-5?
here is the init for the 18F97J60:
Code:

 setup_wdt(WDT_OFF);
 setup_timer_0(RTCC_INTERNAL);
 enable_interrupts(INT_TIMER0);
 enable_interrupts(GLOBAL);

And the fuses:
Code:

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

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NOPROTECT                //Code not protected from reading
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES PRIMARY                  //Primary clock is system clock when scs=00
#FUSES ECCPE                    //Enhanced CCP PWM outpts multiplexed with RE6 thorugh RE3
#FUSES ETHLED                   //Ethernet LED enabled
#FUSES WAIT                     //Wait selections for Table Reads and Table Writes
#FUSES MCU                      //Microcontroller Mode
#use delay(clock=12000000,RESTART_WDT)
#use rs232(baud=1200,parity=E,xmit=PIN_H4,rcv=PIN_H5,bits=8,errors)

And the rs232 for 18F2525:
Code:

#int_rda
void serial_isr() {
#use rs232(baud=1200, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=E, ERRORS, RESTART_WDT)

 BYTE in_char;
 //BRG16=ON;BRGH=ON;SPBRG=0x19;SPBRGH=0x41; //set 300 baud

       in_char=getc();

      if(in_char=='?'||in_char==0x06)// || in_char=='0')  //request start or ACK
      {
         next_in=1;              //starta buffer pekare
         data_valid=TRUE;

      }
      if(data_valid)
      {
         r_buffer[next_in] = in_char;
         next_in++;

         if(in_char==0x0A){    //check if LF 0x0A
           data_valid=FALSE;   //stop reading=
           rs232_flag=TRUE;    //string ready
          }
         if(next_in>=BUFFER_SIZE){
           data_valid=FALSE;
           next_in=0;         //start again
         }
      }

}
/////////////////////////////////////////////////////////////////////////////
#int_tbe
void serial_tx_isr() {

   if(t_buffer[t_next_out]=='~')tx_flag=TRUE;//set 300 baud

   else
      putc(t_buffer[t_next_out]);
   t_next_out=(t_next_out+1) % T_BUFFER_SIZE;
   if(t_next_in==t_next_out)
     {disable_interrupts(INT_TBE);tx_able=FALSE;}

}

void bputc(int8 c) {
   short restart;
   int ni;
   if(fast_Loop&&fast_Loop_enable) fast_loop_handler(); //check between every sign
   restart=t_next_in==t_next_out;
   t_buffer[t_next_in]=c;
   ni=(t_next_in+1) % T_BUFFER_SIZE;
   while(ni==t_next_out);
   t_next_in=ni;
   if(restart)
     {enable_interrupts(INT_TBE); tx_able=TRUE;}
}

Any ideas?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 27, 2009 12:28 pm     Reply with quote

Quote:
here is the init for the 18F97J60:
Code:
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);

You didn't show the getc() code for the 18F97J60. If a Timer0 interrupt
occurs while the software UART is receiving a byte, the reception will
be disrupted. The byte will be received incorrectly. You can fix this by
telling the compiler to automatically disable interrupts when sending or
receiving a char with a software UART, by adding DISABLE_INTS to the
#use rs232() statement. Example:
Quote:
#use rs232(baud=1200,parity=E,xmit=PIN_H4,rcv=PIN_H5,bits=8,errors,DISABLE_INTS)


If this doesn't work, then:
1. Post your compiler version.
2. Try a much more simple test program.
Tagge



Joined: 23 Aug 2005
Posts: 93

View user's profile Send private message Visit poster's website

PostPosted: Fri Feb 27, 2009 1:40 pm     Reply with quote

Thanks, good hint.
I got compiler ver 4.068
I'm using a very simple test program, just "bouncing" a char to the 18F2525.
I made some more testing and I can see that the 18F2525 is receiving
the sent chars right, but the answer isn't read by 18F97j60.
In the TX line from 18f97J60 there is a buffer line driver and therefore
that is 5V to 18f2525. But tx from 18F2525 is 5V the whole way to 18f97J60.
Therefore I'm still wondering if the difference in VCC is an issue..
some pins in 18F97J60 is told to not work over VCC in this case 3,3V,
and the RX line is 5V! Although I couldn't find that it would be the case
with port H.
I'm going to test to pull down the line anyway if it helps. It maybe could
work with a couple of resistors only?
I haven't made the hardware therefore I just have to adjust me to it :(
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 27, 2009 1:48 pm     Reply with quote

The 18F97J60 data sheet say this, on the first page:
Quote:
5.5V Tolerant Inputs (digital-only pins)


But this section says that pins RH4 and RH5 are not "digital only".
They are analog/digital pins.
Quote:
TABLE 1-5: PIC18F86J60/86J65/87J60 PINOUT I/O DESCRIPTIONS

RH4/AN12/P3C
RH5/AN13/P3B


This section says that analog/digital pins may not have a voltage on them
that is higher than Vdd + 0.3v (which is 3.3v + .3v = 3.6 volts).
Quote:
27.0 ELECTRICAL CHARACTERISTICS
Absolute Maximum Ratings (ƒ)
Voltage on any combined digital and analog pin with respect to VSS .... -0.3V to (VDD + 0.3V)

So it's possible that you have damaged pin RH5 (used for Rx).
Tagge



Joined: 23 Aug 2005
Posts: 93

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 03, 2009 10:10 am     Reply with quote

Thanks PCM programmer,
I fixed the levels and they are now correct I think..
A new PIC is added and,
Im having about 3 V at the RH5 pin. But the PIC is still unaware of any incoming signals, chars.
I can see at an oscilloscope that there is incoming characters but the PIC just dont read them as chars, only as '0' ?.
I tested by using kbhit() to wait for incoming chars. And it accepts them but as said as '0' NULL's....
Is there something else about the RH5 pin?
From data sheet:
When the external memory interface is enabled, four of
the PORTH pins function as the high-order address
lines for the interface. The address output from the
interface takes priority over other digital I/O. The
corresponding TRISH bits are also overridden.
PORTH pins, RH4 through RH7, are multiplexed with
analog converter inputs. The operation of these pins as
analog inputs is selected by clearing or setting the
PCFG3:PCFG0 control bits in the ADCON1 register.
PORTH can also be configured as the alternate
Enhanced PWM output channels B and C for the
ECCP1 and ECCP3 modules. This is done by clearing
the ECCPMX Configuration bit.

Could it be the something with the PWM at RH5? altough RH4 is working correctly as TX. Or something with over ridden I/O? by some other function, setting? that makes the RH5 a non digital input?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 03, 2009 11:45 am     Reply with quote

Quote:
I'm using a very simple test program, just "bouncing" a char to the 18F2525.
I made some more testing and I can see that the 18F2525 is receiving
the sent chars right, but the answer isn't read by 18F97j60.

Post the 18F97J60 code.

If you're attempting to use #int_rda for pin RH5, it won't work. It only
works with a hardware UART, not a software UART.

That's I want to see your code. Post the simple "bounce" program for
the 18F97J60.
Tagge



Joined: 23 Aug 2005
Posts: 93

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 03, 2009 12:35 pm     Reply with quote

Hi, one of the 18F97J60 "bounce" codes.. have tried several more to Smile
With receiving buffer for strings and what ever..
And I'm not using HW Uart and therefore no #int, just calling the test()
from main. The reading of 18F97J60 is always only Null..
Code:
void test(void)
{
#use rs232(baud=1200,parity=E,xmit=PIN_H4,rcv=PIN_H5,bits=8,DISABLE_INTS)

char in_char=0;

   putc('?'); //testing, tx ok
   //printf("/?!\r\n");//opening message, ok !!!
   in_char=timed_getc();
   //if(in_buffer[i]==0x0a) ok_flag = true; // LF detected, quit
   
//send it to PC, works Ok
  #use rs232(baud=1200,parity=E,xmit=PIN_E2,rcv=PIN_E1,bits=8)
    printf("Char: %c\r\n",in_char);
}

//the timed getc
Code:
char timed_getc()
{
long timeout;
char retval;

   timeout=0;
   while(!kbhit() && (++timeout< 50000)) 
      delay_us(10);
   if(kbhit())
      retval = getc();
   else
      retval = 0;
   return(retval);
}

Not, this one is the "master" and when it sends the '?' then the "slave" answers (isr controlled)and it does I've checked. Its sending a string and I can se it on an oscilloscope, but the 18F97J60 doesnt understand it..
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 03, 2009 3:10 pm     Reply with quote

Try a very simple test program. Connect the 18F97J60 to a MAX232-type
chip, and connect it to your PC. Then run a terminal program on your PC.
Type some characters by hand. Does it echo the characters back to the
PC ? (Make sure that "local echo" is disabled in the terminal program).

Also, don't use parity. Set the terminal program for 1200, N, 8, 1.
Code:
#include <18F97J60.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=12000000)
#use rs232(baud=1200, xmit=PIN_H4, rcv=PIN_H5)

//================================
void main()
{
char c;

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

}
zagoaristides



Joined: 08 Jul 2007
Posts: 15
Location: Cordoba - Argentina

View user's profile Send private message Visit poster's website ICQ Number

What about this... Pic 18F2553 int_rda problem
PostPosted: Sat Apr 11, 2009 6:07 pm     Reply with quote

Mate, I have a big problem trying to communicate 2 18F2553 and I think your experience can help me. Look at this code I made for 2 PICs comunicate. I can't make the 2553 to enter in the RS232 interrupt routine. Am I missing some configuration? The circuit in Proteus is very simple, 2 pics, 2 MAX487, and inverter with the RE and DE shortcircuited Well thanks a lot.

.h for the Master
Code:
#include <18F2553.h>
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //Resistor/Capacitor Osc
#FUSES NOPROTECT //Code not protected from reading

#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV28 //Brownout reset at 2.5V
#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 NOEBTR //Memory not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected

#FUSES MCLR //Master Clear pin enabled
#use delay(clock=20000000)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=Slaves,enable=PIN_A0)

#define EnviarInf output_high(PIN_C5) //Esta línea solo para Master
#define RecibirInf output_low(PIN_C5) //Esta línea solo para Master

#define BUFFER_SIZE 100

struct TCOM{

int1 tramaLista; //trama lista
int1 tramaProcesada;
int1 timeout; // tiempo de espera por Ack
int1 writing; // saber que estoy escribiendo
int1 reading; // para saber si estoy leyendo
int16 cnt_a_Tx; // cant de bytes a Tx al Slave
int16 cnt_a_Rx; // cant de bytes a Rx del Slave
int16 cntTx; // cant. de bytes Tx al Slave
int16 cntRx; // cant. de bytes Rx del Slave
int1 RxAck;
int ID_Slave;
BYTE Buffer[BUFFER_SIZE]; // bytes almacenados esperando por ser procesados
} myCOM;


.h for the Slave
Code:
#include <18F2553.h>
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
//#FUSES RC_IO //Resistor/Capacitor Osc
#FUSES NOPROTECT //Code not protected from reading
//#FUSES NOOSCSEN //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT //Reset when brownout detected
//#FUSES BORV25 //Brownout reset at 2.5V
#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 NOEBTR //Memory not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected

#use delay(clock=20000000)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=Master,enable=PIN_A0)

#define BUFFER_SIZE 100

struct TCOM{

int1 tramaLista; //trama lista
int1 tramaProcesada;
int1 timeout; // tiempo de espera por Ack
int1 writing; // saber que estoy escribiendo
int1 reading; // para saber si estoy leyendo
int16 cnt_a_Tx; // cant de bytes a Tx al Slave
int16 cnt_a_Rx; // cant de bytes a Rx del Slave
int16 cntTx; // cant. de bytes Tx al Slave
int16 cntRx; // cant. de bytes Rx del Slave
int1 RxAck;
int ID_Slave;
int1 Slave_Active; //Esta línea no va en la definición del Master
BYTE Buffer[BUFFER_SIZE]; // bytes almacenados esperando por ser procesados
} myCOM;



C�digo:
Code:
#include "Here the path where you save the Master.h or Slave.h file written above"
#int_TIMER0
void TIMER0_isr()
{
disable_interrupts(int_TIMER0);
myCOM.timeout = true; // Hay problemas, no ha llegado el Ack
}

#int_RDA
void Dato_de_Slave()
{
int dato;
dato = fgetc(Slaves);
myCOM.cntRx++; ///Cada vez que entra suma 1. La primera es ID, luego Cant Bytes, Luego Datos
switch (myCOM.cntRx)
{
case 1: if (dato == myCOM.ID_Slave) // Slave respondio bien reenviando su dirección. Solo cunado se escribe
myCOM.RxAck = true;
break;
case 2: if ((myCOM.writing == true) && (dato == myCOM.cnt_a_Tx - 2)) // Solo la cnt de bytes, -add y -cnt
myCOM.RxAck = true; ///ya que el esclavo solo responde con Cant. Bytes
else if (myCOM.reading == true) // Llego la cant. a Rx del Slave
{
myCOM.cnt_a_Rx = dato;
myCOM.RxAck = true;
}
case 3: if ((myCOM.writing == true) && (dato == 0xFF)) // Comando de Rx el slave toda la Transferencia
myCOM.RxAck = true;
}

// el que sigue sería como un case especial cuando se pasó el primero y el segundo y ahora estamos leyendo
if ((myCOM.reading == true) && (myCOM.cntRx > 2)) // Recibiendo los datos y ya se enviaron y recibieron
// con éxito los Ack de (Dirección + R/W) y (Cant. de Bytes)
myCOM.Buffer[myCOM.cntRx - 3] = dato; // myCOM.cntRx - 3 porque para el primero myCOM.cntRx = 3 o sea 0
}

void InitMaster()
{
myCOM.tramaLista = false;
myCOM.timeout = false;
myCOM.writing = false;
myCOM.reading = false;
myCOM.cnt_a_Tx = 0;
myCOM.cnt_a_Rx = 0;
myCOM.cntTx = 0;
myCOM.cntRx = 0;

setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_timer_2(T2_DIV_BY_16,255,16);
setup_timer_3(T3_DISABLED|T3_DIV_BY_8);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
setup_oscillator(False);
//set_tris_C(0b10000000);
}

void write_slaves(int dato)
{
char caca = ('A');
EnviarInf;
fputc(caca, Slaves);
RecibirInf;
}

short waitAckSlave()
{
myCOM.RxAck = false;
clear_interrupt(int_TIMER0); // si a los 3.4 seg no hay ack de Slave
enable_interrupts(int_TIMER0); // hay problemas. Aqui activo el TIMERO
RecibirInf;
do{
} while ((myCOM.timeout == false) && (myCOM.RxAck == false));
disable_interrupts(int_TIMER0);
EnviarInf;
return myCOM.RxAck;
}

int waitCantRead()
{
myCOM.RxAck = false;
clear_interrupt(int_TIMER0); // si a los 3.4 seg no hay ack de Slave
enable_interrupts(int_TIMER0); // hay problemas. Aqui activo el TIMERO
RecibirInf;
do{
} while ((myCOM.timeout == false) && (myCOM.RxAck == false));
disable_interrupts(int_TIMER0);
EnviarInf;
return myCOM.RxAck;
}

short write_slave(int address, int cnt, int *dato) /// 1,20,11111111
{
int i, ack, control;
myCOM.writing = true; // Estamos escribiendo
myCOM.cnt_a_Tx = cnt+2; // Mas dir y cnt de bytes
myCOM.cnt_a_Rx = 3; // Ack por Address, por Cant., por Fin
myCOM.cntTx = 0;
myCOM.cntRx = 0;
myCOM.timeout = false;
myCOM.ID_Slave = address;
control = address; ///address se paso como 1
control = control << 1;
control = control & 0b11111110; ///0 para decirle que vamos a escribir Ouput
write_slaves(control); // Dirección y modo escritura
myCOM.cntTx++;
ack = waitAckSlave();
if (ack == false)
return false;
write_slaves(cnt); ///Cantidad de bytes, cnt se pasó como 20
myCOM.cntTx++;
ack = waitAckSlave();
if (ack == false)
return false;
for (i = 0; i < cnt; i++) //0 a cnt-1 = cnt bytes
{
write_slaves(dato[i]);
myCOM.cntTx++;
}
ack = waitAckSlave(); // Espera comando 0xFF de buena recepcion del Slave Active

myCOM.writing = false; // Reseteamos las variables para una nueva comunicación
myCOM.cnt_a_Tx = 0;
return ack;
}

short read_slave(int address)
{
char ack, control;
myCOM.reading = true; // Estamos leyendo
myCOM.cnt_a_Tx = 3;
myCOM.cntTx = 0;
myCOM.cntRx = 0;
myCOM.timeout = false;
myCOM.ID_Slave = address;
control = address;
control = control << 1;
control = control | 0b00000001;
write_slaves(control); // Dirección y modo lectura
myCOM.cntTx++;
ack = waitAckSlave();
if (ack == false)
return false;
ack = waitCantRead(); // Si sale de aqui sin problem myCOM.cnt_a_Rx tiene el valor
write_slaves(myCOM.cnt_a_Rx); // Envio Ack al Slave, o sea la misma Cant a Rx por Master
myCOM.cntTx++;
do{ // Despues habilitar un timeOut para no colgar indefinido al Master
} while (myCOM.cntRx - 2 != myCOM.cnt_a_Rx); // Mientras la cantidad de bytes leidos sea menor a
// myCOM.cnt.Rx - 1 de (Dirección+R/W) - 1 de (Byte de Cant.Bytes)
// que es = cnt e igual a 20 en este ejemplo

write_slaves(0xFF); // Envío de comando de Recepcion completada

myCOM.reading = false; // Reseteamos las variables para una nueva comunicación
myCOM.cnt_a_Rx = 0;
myCOM.tramaLista = true;
myCOM.tramaProcesada = false;
return true;
}


For the master
Code:

void main()
{
char buffer[20];
char i;
InitMaster();
delay_ms(100); // Para Inicializar los Slaves
for (i = 0; i < 20; i++)
buffer[i] = 1+i;
write_slave(1, 20, buffer);

read_slave(1);

do{
} while (true);
}



For the Slave
Code:

void main()
{
char i;
char buffer[20];
InitSlave();
for (i = 0; i < 20;i++)
buffer[i] = myCOM.ID_Slave+2*i; //Llenamos el buffer con algo
do{
if (myCOM.writing == true) //si en la interrupción notamos que el Master quiere leer ==> Esclavo debe escribir
write_master(20, buffer);
}while(true);
}
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