|
|
View previous topic :: View next topic |
Author |
Message |
oxxyfx
Joined: 24 May 2007 Posts: 97
|
Communication between two PICs |
Posted: Thu May 24, 2007 2:14 pm |
|
|
Hello,
I am trying to build a circuit with 2 PIC's. One is a 16F506 doing some A/D conversion on an RSSI signal. The result of this conversion and some calculation should be a nubmer between 0-255. This number should be sent over to the second PIC of this circuit - which is a 12F629 - used as a servo controller.
Based on the value received the servo will move left or right. I looked through most of the posts regarding RS232 communication and I am not sure that is the right way to go. One other way would be to use a different PIC servo controller ex. 16F627 and connect 8 output pins of the first to 8 input pins of the second - read the binary values and convert it to decimal to use it in the servo pulse calculation.
Are there any other - simpler - ways to resolve such communication?
I am open to any suggestions,
Thank you. |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Thu May 24, 2007 2:33 pm |
|
|
You may skip that alltogether.
Hook up 2 wires, with pullups.
if pin x1 is low go left
if pin x2 is low go right
if neither stay put. |
|
|
jimcbride
Joined: 05 Apr 2006 Posts: 23
|
|
Posted: Thu May 24, 2007 4:05 pm |
|
|
Does the 0-255 number give you direction as well as speed?
Assuming both chips have harware uart, why not use serial? I have done this with two pics myself. One master and one slave. The slave drives two motors as well as reads and tallies encoder counts sending the results back to the master. The hardware uart runs in the background so commands won't tie up the master all that long. Also if you are only sending from master to slave you only need 2 wires. (One wire if both uC share a ground.) The only trick is sending 0-255 instead of characters on the uart. Have a look at my interrupt routines that read and write memory locations to send/receive data. You should get the idea and adapt it to only one byte. Interupt routines are not necessary in your case. In this code I am using a mini-ITX motherboard to talk to a Uc over uart.
Code: | void encodeTx(){
int add0,add1,add2,add3;
add0 = &encoderLt - 32; //encoderLt is signed int32, 4 mem byte locations
add1 = &encoderLt - 31;
add2 = &encoderLt - 30;
add3 = &encoderLt - 29;
tx_buffer[0] = read_bank(0,add0);
tx_buffer[1] = read_bank(0,add1);
tx_buffer[2] = read_bank(0,add2);
tx_buffer[3] = read_bank(0,add3);
add0 = &encoderRt - 32; //encoderRt is signed int32, 4 mem byte locations
add1 = &encoderRt - 31;
add2 = &encoderRt - 30;
add3 = &encoderRt - 29;
tx_buffer[4] = read_bank(0,add0);
tx_buffer[5] = read_bank(0,add1);
tx_buffer[6] = read_bank(0,add2);
tx_buffer[7] = read_bank(0,add3);
enable_interrupts(INT_TBE);
}
#int_TBE//Transmitt Buffer Empty(so send)
TBE_isr()
{
fputc(tx_buffer[txi],PIC2ITX);
txi = (txi + 1) % tx_buff_size;
if(txi == 0){
disable_interrupts(INT_TBE);
// tx = 0;
}
}
void decodeRx()
{
dirL = rx_buffer[0];
dirR = rx_buffer[1];
leftRequest0 = rx_buffer[2];
rightRequest0 = rx_buffer[3];
pidLoopFlag = 0;
//delay_ms(10);
//encodeTx();
// tx = 1;
}
#int_RDA//Received DAta
RDA_isr()
{
rx_buffer[rxi] = fgetc(PIC2ITX);
rxi = (rxi + 1) % rx_buff_size;//0 is position 1
if(rxi == 0){
decodeRx();
}
} |
|
|
|
oxxyfx
Joined: 24 May 2007 Posts: 97
|
|
Posted: Thu May 24, 2007 4:30 pm |
|
|
Thanks.
I though about the 2 wire solution. I am not sure how will impact the design, I have to meditate on that.
Jim, thanks for the solution, this is the same serial communication I was thinking about. I think both chips have hardware uart, since both can set the rs232 communication up on pins.
I wrote some code for the receiving part so far
the .h file:
Code: |
#include <12F629.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal clock
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPUT //No Power Up Timer
#FUSES BROWNOUT //Reset when brownout detected
#use delay(clock=20000000)
#use rs232(baud=4800,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8,ERRORS)
|
the .c file
Code: |
#include "servo_control_12F629.h"
#use fast_io (a)
#define On 1
#define Off 0
#define Servo PIN_A5 //define pin for outgoing signal
int16 Pulse;
int16 Low_pulse;
int16 High_pulse;
int16 Pause;
char timed_getc() {
long timeout;
timeout=0;
while(!kbhit()&&(++timeout<50000)) // 1/2 second
delay_us(10);
if(kbhit())
return(getc());
else {
return(0);
}
}
#INT_RA
void ra_interrupt() {
Byte a;
a = timed_getc();
}
void main()
{
int a;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RA);
set_tris_a(0b00000001); //configure A0 to be an input port
Output_low(Servo); //clear the potput port
Pulse = 1500;
Low_pulse = 690;
High_pulse = 2310;
While(true) {
Pulse = a*180 +690; //Calculate Pulse lenght
Pause = 20000 - Pulse; //Calculate interval lenght
Output_high(Servo); //Set port on high
delay_us(Pulse); //Wait for the duration of the pulse
Output_low(Servo); //Set port low
delay_us(Pause);
}
}
|
Will this code receive my byte?
Thanks. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu May 24, 2007 4:47 pm |
|
|
The local variable "a" declared inside the ra_interrupt() function is not visible in the main().
Declare it as global.
Humberto
Last edited by Humberto on Thu May 24, 2007 10:56 pm; edited 2 times in total |
|
|
oxxyfx
Joined: 24 May 2007 Posts: 97
|
|
Posted: Thu May 24, 2007 4:54 pm |
|
|
Thanks, I was also thinking about that... Here it is:
Code: | #include "servo_control_12F629.h"
#use fast_io (a)
#define On 1
#define Off 0
#define Servo PIN_A5 //define pin for outgoing signal
int16 Pulse;
int16 Low_pulse;
int16 High_pulse;
int16 Pause;
int a;
char timed_getc() {
long timeout;
timeout=0;
while(!kbhit()&&(++timeout<50000)) // 1/2 second
delay_us(10);
if(kbhit())
return(getc());
else {
return(0);
}
}
#INT_RA
void ra_interrupt() {
Byte a;
a = timed_getc();
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RA);
set_tris_a(0b00000001); //configure A0 to be an input port
Output_low(Servo); //clear the potput port
Pulse = 1500;
Low_pulse = 690;
High_pulse = 2310;
While(true) {
Pulse = a*180 +690; //Calculate Pulse lenght
Pause = 20000 - Pulse; //Calculate interval lenght
Output_high(Servo); //Set port on high
delay_us(Pulse); //Wait for the duration of the pulse
Output_low(Servo); //Set port low
delay_us(Pause);
}
} |
Also, there is something I don't understand about this serial communication. I am reading the 'a' value from the serial buffer and some posts refer to it as 'one character'. However my '255' is 3 characters long... Am I right in assuming that? In that case what happens to the 5 and the other 5? Or there is something I am missing here...
I know this is a newbie question, but that's what I am to this serial communication....
Thx. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu May 24, 2007 5:03 pm |
|
|
Quote: |
However my '255' is 3 characters long... Am I right in assuming that?
|
The serial communication is a binary bit frame transaction, so your ´255´ is 0b11111111 (Binary) and 0xFF (Hexa) and is one character long.
int8 a;
a = 255;
printf(" %u", a); will transmit 0b11111111 and print ´255´
But if you code:
printf("255"); will transmit 3 characters 0x32 0x35 0x35
Humberto
Last edited by Humberto on Thu May 24, 2007 10:12 pm; edited 1 time in total |
|
|
oxxyfx
Joined: 24 May 2007 Posts: 97
|
|
Posted: Thu May 24, 2007 5:18 pm |
|
|
Thanks,
I really love this forum. This makes my life much easyer I think.
Now that you are so helpful, let me pick your brain for one more thing which has been bothering me...
Each PIC has a CLKOUT and a CLKIN pin. I've been searching back abd forth the internet for this and I couldn't find anything relevant.
Assuming that both PIC's have internal 20Mhz oscillator, in order to sync the clocks for these two without using external xtal, can one connect the pins from the two PICs the following way:
Pic1 CLKOUT -> Pic2 CLKIN
Pic1 CLKIN -> Pic2 CLKOUT Also disable the internal oscillator on Pic2 and set Pic2 to External OSC?
This again may be out of this world question, but to me it seems logical that one should be able to sync 2 pic's clock together in the same circuit.
Thx. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu May 24, 2007 5:37 pm |
|
|
Quote: |
Assuming that both PIC's have internal 20Mhz oscillator,
|
Bad assumption. Read the datasheet and you will learn that the internal oscillator
available in the PIC12F629 is 4Mhz.
You can connect CLKOUT >>> CLKIN in one way only.
Humberto |
|
|
oxxyfx
Joined: 24 May 2007 Posts: 97
|
|
Posted: Thu May 24, 2007 6:14 pm |
|
|
Thanks for that, I have the datasheet beside me, just didn't look at it.
So Pic1 Clkout connected to Pic2 Clkin will supply Pic 2 with the external oscillator?
In this case on Pic2 the #Fuse EC_IO will apply right?
Also on Pic1 I will have to #FUSES INTRC which enables the Internal oscillator and alows the clkout pin to be enabled. Right?
Thanks. |
|
|
Guest
|
|
Posted: Thu May 24, 2007 6:38 pm |
|
|
look on your pinout to make sure you use the hardware uart. CCS will let you use any i/o pins for serial comm, but only dedicated ones will be hardware, the others are software uart. In other words, with harware uart, you send out data at the baud rate in the background, but you can do other things while the data is clocked out. With a software uart, you can't do anything while the data is being clocked out.
If you use the hardware uart, you should have no trouble communicating between both pics even though they have different clock sources. They could even be running at different clock speeds. Different clock speeds are more accurate than others. Once again, check out the datasheet under uart. Data sheets can be hard to understand if you try to take it all in at once. Focus on one thing at a time. |
|
|
oxxyfx
Joined: 24 May 2007 Posts: 97
|
|
Posted: Thu May 24, 2007 7:10 pm |
|
|
That is a good point. I looked/shearched through the datasheets, and I couldn't find any refereces to uart or usart. Are these the same?
I've also looked through the Microchip's website and searched for devices with either of these. I found some with AUSART, EUSART, but I haven't seen any UART. Again, I must be missing something....
That means I cannot use these two for serial communication with the above code? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu May 24, 2007 10:03 pm |
|
|
oxxyfx,
You are using INT_RA interrupt to get a char, is a conceptual error because to
trigger the INT_RA (wich is level triggered) you must configure such input as Analog Input,
while you are expecting an incoming serialy transmitted character wich is a digital signal.
Instead you can use the GP2 PIN (configured as Digital Input) wich is the External
Interrupt pin (edge triggered), then use #INT_EXT and use your interrupt handler.
Being GP2 edge triggered, you can select the trigger edge (rissing or falling) with
the built in CCS function ext_int_edge(H to L) to trigger with the falling edge of the
incoming char to detect the Start bit.
oxxyfx wrote:
Quote: |
So Pic1 Clkout connected to Pic2 Clkin will supply Pic 2 with the external oscillator?
|
Yes.
Quote: |
In this case on Pic2 the #Fuse EC_IO will apply right?
|
Yes.
Quote: |
Also on Pic1 I will have to #FUSES INTRC which enables the Internal oscillator and alows the clkout pin to be enabled. Right?
|
Yes.
Quote: |
I've also looked through the Microchip's website and searched for devices with either of these. I found some with AUSART, EUSART, but I haven't seen any UART. Again, I must be missing something....
|
From Wikipedia, the free encyclopedia
A UART, universal asynchronous receiver / transmitter is responsible for performing the main task in serial communications with computers.
A UART is usually an individual (or part of an) integrated circuit used for serial communications over a computer or peripheral device serial port. UARTs are now commonly included in microcontrollers (for example, PIC16F628). A dual UART or DUART (pronounced IPA: [dʊˈat]) combines two UARTs into a single chip. Many modern ICs now come with a UART that can also communicate synchronously; these devices incorporate the word synchronous into the acronym to become USARTs.
Guest wrote:
Quote: |
look on your pinout to make sure you use the hardware uart.
|
Your whole comments are right BUT, just not to misled to the original poster,
PIC12F629 doesn´t have hardware UART.
Humberto |
|
|
Ttelmah Guest
|
|
Posted: Fri May 25, 2007 3:02 am |
|
|
oxxyfx wrote: | That is a good point. I looked/shearched through the datasheets, and I couldn't find any refereces to uart or usart. Are these the same?
I've also looked through the Microchip's website and searched for devices with either of these. I found some with AUSART, EUSART, but I haven't seen any UART. Again, I must be missing something....
That means I cannot use these two for serial communication with the above code? |
OK.
UART. Standard abbreviation, for 'Universal Asynchronous Receiver Transmitter'. Standard 'chip speak'. Most are also capable of being programmed to use synchronous clocking as well, and are then USART's. Synchronous mode, is rarer, and often ignored. So a 'USART', can be used as a 'UART'. You can also have a 'SART', which only supports synchronous operation - these were used on some IBM kit years ago, which cannot support the normally used asynchronous modes.
Then latter UART versions have had extra features added to their basic operation (things like address recognition, automatic speed adjustment, wake up, etc.), and are then 'Advanced' versions, or 'Enhanced' versions, depending on what extras are added. AUSART's, and EUSART's. Again reverse compatible.
UART, is being used generically here, for any of the hardware ports, capable of supporting the asynchronous mode. UART, has a very specific meaning, as does USART, and would be understood by people working with just about any Micro, but the extended versions (AUSART, EUSART), are 'Microchip speak, being used by them to show their own extensions, and as such are really only a notation to 'look at the data sheet, and see what extras it has'...
Best Wishes |
|
|
inservi
Joined: 13 May 2007 Posts: 128
|
|
Posted: Fri May 25, 2007 3:51 am |
|
|
Hello,
It look to be a few later but why not use PWM with only one wire between the pics. You can use the timing you want. You need to send only two pulses after each A/D conversion, a long one (but not to long) for start (synchro) and the second one (PWM) for the value. The first pulse is there only for void to the receiver to wast to many time. It's fast and simple.
You can also imagine to use a light interupt and counter at the receiver side.
If this way is interesting for you then i will make a prototype.
Sorry for my poor English
Best regards,
dro. _________________ in médio virtus |
|
|
|
|
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
|