Pic to Pic Usart

General discussion on mikroC.
Author
Message
Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

Pic to Pic Usart

#1 Post by Tanky321 » 04 Jun 2009 17:16

Im trying to communicate between two 16F628A's, in what should be very simple. I tried with Manchester, but that failed, and USART isn't going much better! :x

Simply my program is to read PORTA, when any bit goes high it transmits an appropriate number, eventually via RF, but now just with a wire.

On the receiving end, each number will have a corresponding binary number output on PORTA.

I have the PORTA receiver always high(0xFF), when the appropriate number is received, a particular bit is turned low.

I dont have much skill in C or any programming, can anyone help?

Receiver

Code: Select all

/*This Program recevies a USART signal via RF
from a handheld remote, that is then translated
to a binary output on PORTA*/


unsigned short i;


void main() {
INTCON.GIE = 0;                   // Disable interrupts

cmcon = 7;                        //Declare Variables
VRCON = 0;
PORTA = 1;                        //Init. PORTA
PORTB = 0;                        //& PORTB
TRISA = 0x00;
TRISB = 0xFF;

Usart_Init(2400);                  //Establish USART at 2400bps


while(1){


if (Usart_Data_Ready()){
i= Usart_Read();

if (i == 1){
   PORTA = 0xFE;}

else if (i == 2){
   PORTA = 0xFD;}
   
else if (i == 3){
   PORTA = 0xFB;}

else if (i == 4){
   PORTA = 0xF7;}

else if (i == 5){
   PORTA = 0xEF;}
   
else if (i == 6){
   PORTA = 0xDF;}
   
else if (i == 7){
   PORTA = 0xBF;}
   
else if (i == 8){
   PORTA = 0x7F;}

else PORTA = 0xFF;

}
}}

Transmitter

Code: Select all




unsigned short i;




void main() {
INTCON.GIE = 0;                   // Disable interrupts

cmcon = 7;
VRCON = 0;
PORTA = 0;
PORTB = 0;
TRISA = 0xFF;
TRISB = 0x00;

Usart_Init(2400);                  //Establish USART at 2400bps

while (1){



      if (PORTA.F0){
             i=1;}
      else if (PORTA.F1){
             i=2;}
      else if (PORTA.F2){
             i=3;}
      else if (PORTA.F3){
             i=4;}
      else if (PORTA.F4){
             i=5;}
      else if (PORTA.F5){
             i = 6;}
      else if (PORTA.F6){
             i = 7;}
      else if (PORTA.F7){
             i = 8;}

    Usart_Write(i);
    
}
}

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#2 Post by drdoug » 04 Jun 2009 18:40

I did not test your code but it looks like it could/should work.
I don't think I read exactly what the problem is? No transmitted signal, no received signal, garbage data?
Did you turn off MCLR in your config?
Pull down's on your input pins?
Debounce your inputs?
Test your transmitter with a PC terminal to verify (rs232 level converter)?
Test your receiver with a PC terminal to verify(rs232 level converter)?

You may also want to check out this topic and some others on this forum http://www.mikroe.com/forum/viewtopic.p ... c&start=30

Provide some more info and I'll try to help.

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#3 Post by Tanky321 » 04 Jun 2009 19:24

Thanks drdoug,

The entire thing doesnt work, I have the receiver on my EP5. When turned on PORTA is 11110011 which is strange because I declare it 0xFF.

I have MCLR turned off in the transmitter as well as the receiver.

All the inputs on the transmitter have 8.2k pull downs.

Im not sure about debouncing, Im going to look into that.

I havent tested with the PC, im not sure how to do that either.

By looking at that other post I guess if I pull up all my inputs and transmit the state of PORTA It might be a better idea? That way the receiving program is relatively easy.

Thanks again.

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#4 Post by drdoug » 04 Jun 2009 20:35

I forgot to mention that RA 5 is input only ( I think - this is also the MCLR pin). Do you see the transmit side light flicker when you press a button? Have you tried a simple flashing LED routine to make sure your initialization is correct?

I have an EP4 but it should be easy to test the PIC-PC communication with the EP5 (You may have to jumper the pins to get it to work porperly with the EP5 Uart pins??). There is an example in the manual, help, and examples section.

I think getting the transmitter working is easiest. Connect the EP5 to the computer and use the mE terminal program for testing. Try this code

Code: Select all

unsigned short i;

void main() {
INTCON.GIE = 0;                   // Disable interrupts

CMCON = 7;
VRCON = 0;
PORTA = 0;
PORTB = 0;
TRISA = 0xFF;
TRISB = 0x00;

Usart_Init(2400);                  //Establish USART at 2400bps

while (1){


   Usart_Write('A');
   Delay_ms(1000);
   
}
} 
Once connected, you should see the 'A' on the terminal screen every second. If this works, you can move to the next challenge. If not, verify the hardware and software settings.

For your main code, you may try something like this on the transmitter

Code: Select all

unsigned short i;




void main() {
INTCON.GIE = 0;                   // Disable interrupts

CMCON = 7;
VRCON = 0;
PORTA = 0;
PORTB = 0;
TRISA = 0xFF;
TRISB = 0x00;

Usart_Init(2400);                  //Establish USART at 2400bps

while (1){



 if (Button(&PORTA, 0, 100, 1)) Usart_Write(1);
 if (Button(&PORTA, 1, 100, 1)) Usart_Write(2);
 if (Button(&PORTA, 2, 100, 1)) Usart_Write(4);
 if (Button(&PORTA, 3, 100, 1)) Usart_Write(8);
 if (Button(&PORTA, 4, 100, 1)) Usart_Write(16);
 if (Button(&PORTA, 5, 100, 1)) Usart_Write(32);
 if (Button(&PORTA, 6, 100, 1)) Usart_Write(64);
 if (Button(&PORTA, 7, 100, 1)) Usart_Write(128);
    
}
} 
and the receiver as below. NOTE: RA5 is still only an input but you get the idea I think.

Code: Select all

unsigned short i;


void main() {
INTCON.GIE = 0;                   // Disable interrupts

cmcon = 7;                        //Declare Variables
VRCON = 0;
PORTA = 1;                        //Init. PORTA
PORTB = 0;                        //& PORTB
TRISA = 0x00;
TRISB = 0xFF;

Usart_Init(2400);                  //Establish USART at 2400bps


while(1){


if (Usart_Data_Ready()){
   i= Usart_Read();
   PORTA = i;
   } // end if (Usart_Data_Ready())
} // end while(1)
} // end main

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#5 Post by Tanky321 » 04 Jun 2009 20:56

Thanks drdoug!

Im going to try this out, and il report back with my findings! Thanks!

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#6 Post by Tanky321 » 05 Jun 2009 03:40

Hmmm, im definitely transmitting something, but not the right thing!

On the receiving end im getting €, which looks like the Euro sign!

Im guessing that this may all have to do with my clock speed? Currently its set to 8Mhz, internal.

Other Hardware parameters are:

WDT_OFF

LVP_OFF

MCLR_OFF

INTOSC_OSC_NOCLKOUT


In the mETerminal my settings are:

Baud:9600
Stop Bits: One Stop Bit
Parity:None
Data bits: Eight

RTS: OFF
DTR: OFF

This is all with the top piece of code:


Code: Select all

unsigned short i;

void main() {
INTCON.GIE = 0;                   // Disable interrupts

CMCON = 7;
VRCON = 0;
PORTA = 0;
PORTB = 0;
TRISA = 0xFF;
TRISB = 0x00;

Usart_Init(2400);                  //Establish USART at 2400bps

while (1){


   Usart_Write('A');
   Delay_ms(1000);
   
}
} 
Thanks alot!

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#7 Post by Tanky321 » 05 Jun 2009 04:19

Actually I got the Transmitter and receiver to work, now my problem is getting what would be output on RA4 and RA5 to RB4 and RB5. And also, the outputs are latching at the moment, is there a way to set it up so PORTA will revert back to its original state?

Thanks alot!!

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#8 Post by drdoug » 05 Jun 2009 04:47

RA4 is an open drain so you will need to put in a pull up resistor on it and it should be able to work. I added in the PORTB.F5 reference (you can also add PORTB.F4 if you can not get that open drain thing to work.
I also accounted for reverting back to its original (0 not 1) state but you get the idea. You can make the delay longer if you want. This is not the best solution but it will get you started. Ultimately for a wireless setup you will want the receiver on an interrupt and perhaps the delay before reset if it is more than a few milliseconds.

Also, for the transmitter, you will want to send some type of preamble and header info to verify you are communicating with the correct unit ( and to account for noise).

Code: Select all

unsigned short i;


void main() {
INTCON.GIE = 0;                   // Disable interrupts

cmcon = 7;                        //Declare Variables
VRCON = 0;
PORTA = 1;                        //Init. PORTA
PORTB = 0;                        //& PORTB
TRISA = 0x00;
TRISB = 0xFF;

Usart_Init(2400);                  //Establish USART at 2400bps


while(1){


if (Usart_Data_Ready()){
   i= Usart_Read();
   PORTA = i;
   if ( i == 32) {
      PORTB.F5 = 1;
     }
  Delay_ms(500);
  PORTA = PORTB.F5 = 0;  // turn off Ports after 500 ms
   } // end if (Usart_Data_Ready())
} // end while(1)
} // end main 

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#9 Post by Tanky321 » 05 Jun 2009 13:55

Thanks!

Ive got everything working pretty well, im going to start on the preamble next.

Only thing different with the program below is that im using inverted binary numbers 1111 1110 1111 1101 etc.

Now my only problem is getting RB4 and RB5 to work with the delay if I send 239 or 223 they work, but each respective bit stays off until the next number is asserted.

Code: Select all


unsigned short i;


void main() {
INTCON.GIE = 0;                   // Disable interrupts

cmcon = 7;                        //Declare Variables
VRCON = 0;
PORTA = PORTB.F4 = PORTB.F5 = 1;  //Init. PORTA
PORTB = 0;                        //& PORTB
TRISA = 0x00;
TRISB = 0x00;
TRISB.F1 = 1;

Usart_Init(2400);                  //Establish USART at 2400bps


while(1){


if (Usart_Data_Ready()){
   i= Usart_Read();
   PORTA = i;
   }
   
   if ( i == 239) {
      PORTB.F4 = 0;
     }
     
   if ( i == 223) {
      PORTB.F5 = 0;
     }
   Delay_ms(100);
   PORTA = 0XFF;
   PORTB.F4 = PORTB.F5 = 1;

   //PORTB.F4 = 1;
   //PORTB.F5 = 1;
    // end if (Usart_Data_Ready())
} // end while(1)
} // end main

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#10 Post by drdoug » 05 Jun 2009 14:47

You need to reset your i variable when you change the Port value otherwise it will reassert each time through your loop. Or put it inside the uart data ready loop.

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#11 Post by Tanky321 » 09 Jun 2009 04:58

Thanks!

I have one more question, is it possible to invert the logic of the USART? It seems as if normal state is high, is there a way for normal state to be low (0)?

Thanks!

drdoug
Posts: 1074
Joined: 16 Aug 2007 03:49
Location: St. Louis, MO

#12 Post by drdoug » 09 Jun 2009 13:44

I inverted the signal using a simple transistor circuit and got it to work with a cheap 433 rf system (don't forget to invert the receive end also). Also, you may try the soft uart which can be inverted in the software.
Some have had success with the manchester encoding which is designed for rf system but I did not get it to work although I was an even bigger newb at the time.

blips
Posts: 30
Joined: 11 Nov 2007 22:28

#13 Post by blips » 10 Jun 2009 09:22

you can also use a simple TTL inverter buffer driver IC.

Tanky321
Posts: 40
Joined: 07 Dec 2008 15:29

#14 Post by Tanky321 » 10 Jun 2009 13:37

Thanks guys,

I know I could use the inverter external circuits, but I was wondering if there was anyway other that software usart to invert it internally. I mean not that one inverter would be a huge deal externally, but any less real estate is better!

blips
Posts: 30
Joined: 11 Nov 2007 22:28

#15 Post by blips » 10 Jun 2009 13:53

Not possible in the usart module I think.
Give soft usart a try

Post Reply

Return to “mikroC General”