Sari la conținut
ELFORUM - Forumul electronistilor

Problema conectare 2 PIC-uri pe RS232 prin MAX232


mircang9

Postări Recomandate

Salutare la toata lumea,In schema alaturata, daca nu folosesc diodele D1, D2si nici rezistenta R, DOAR pentru schema cu un singur microcontroller PIC ( PIC16F887 ) schimbul bidirectional de date se face bine. Acum vreau sa pun doua PIC-uri pentru ca interfata din calculatorsa transmita si sa receptioneze date cu doua PIC-uri sau chiar mai multe. Intentia este sa folosesc pana la urma 7 PICuri. Interfata trimite interogari individuale pentru un PIC la un moment dat. Toate PICurile primesc la un moment dat interogarea ( un cod de adresa ) dar doar un singur PIC isi recunoaste adresa si raspunde la un moment dat.Interogarea se face ciclic. Interfata din PC trimite o adresa de interogare pentru PIC1. Apoi PIC1 raspunde. Dupa ce interfata a afisat datele de la PIC1 trimite apoi interogare pentru PIC2 care la randul lui trimite raspuns. Apoi dupa ce interfata a prelucrat datele primite si de la PIC2, reia interogarea pentru PIC1 si asa mai departe.Schema din figura am incercat-o cu D1 si rezistenta R doar pentru PIC1 si nu merge. Am folosit doar, D1 fara, R si tot nu merge. Daca leg direct cele doua PICuri ca in schema fara D1,2 si R nu cumva se arde pinul TX de la PICuri intrucat sunt configurati ca iesire, si cand unul din cele doua PICuri trimite pe pinul sau TX date, aceste date se transmit si pe pinul TX de la celalalt PIC. De exemplu daca pe TX PIC1 trimite 0 atunci acel 0 logic se trimite si la pinul TX de la PIC2 producandu-se astfel un scurt circuit ( si se poate arde pinul TX de la PIC2 ) intrucat cum pinul TX de la PIC2 este in starea inactiva ( mark - 1 logic ) un 0 logic aplicat produce un scurt circuit.Rata este de 75 bps. Si deci fronturile de 0/1 logic persista oarecum.Cum pot sa fac ? Ce schema electrica sa folosesc ? :jytuiyu

post-23035-139829320399_thumb.jpg

Link spre comentariu
  • Răspunsuri 7
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • mircang9

    4

  • francezu

    3

  • Liviu M

    1

Top autori în acest subiect

Imagini postate

Cred ca mai simplu si mai usor e sa faci toti pinii TX ai picurilor intrari si cand un anumit pic trebuie sa transmita date, reconfigurezi TX-ul lui ca iesire, transmiti datele si il faci la loc intrare.

Link spre comentariu

In completare la cele spuse de Liviu : ideea este sa nu lasi nici unul din uC-uri sa transmita "strong-hi", adica pinul sa fie configurat ca iesire si sa fie pus pe 1 logic. Pentru a rezolva problema se leaga un rezistor pull-up la pin si se pune bit-ul corespunzator din registrul de iesire pe 0. Este ceva asemanator bus-urilor OneWire, I2C. Pentru a transmite 1 logic, se configureaza pin-ul ca intrare(rezistor-ul pull-up va produce un nivel 1 logic, considerand ca la momentul respectiv alt uC legat la bus nu transmite 0); pentru a transmite 0 logic se configureaza pin-ul ca iesire; deci transmisia datelor se face prin manipularea registrului de configurare a port-ului, nu a registrului de iesire. Oricum trebuie sa iti faci o librarie , si nu poti folosi un PIC cu port UART.

Link spre comentariu

Cred ca ambele variante sunt implementabile cum ati spus amandoi: 1) cu UART-urile de la PIC-urisi configurarea lui TX/RC6 la PIC16F887 cu TRISC6. La un moment dat doar PIC-ul care transmitedate are TRISC6=0 in timp ce toate celelalte au TRISC6=1.2)La un moment dat doar PIC-ul ce transmite isi schimba TRISC6=0/1, in timp ce restulPIC-urilor au TRISC6=1 setat ca intrare. Nu vad de ce nu s-ar putea folosi si UARTurile.Prima varianta ( varianta lui Liviu ) este preferabila sub toate aspectele atat hardware cat sisoftware. Programul utilizeaza UART-urile si deci ocupa mai putin spatiu in memoria de program.Dpdv hardware nu mai pun acea rezistenta de pull-up.A doua varianta ( varianta lui Francezu ) adauga o componenta in plus ( rezistenta de pull-up )si ocupa mai multa memorie de program deoarece trebuie implementata in program siUARTul software. Iata un exemplu pentru implementarea UARTUlui la 75 bps.Durata unui bit este 1/75=13.3 ms. Sa presupunem ca trimitem registrul a=0b01001110.Subrutina (libraria) de transmitere seriala ar arata cam asa:static volatile unsigned char ET1 @ 0x20;static volatile bit a_0 @ ((unsigned)&a*8)+0;static volatile bit a_1 @ ((unsigned)&a*8)+1;static volatile bit a_2 @ ((unsigned)&a*8)+2;static volatile bit a_3 @ ((unsigned)&a*8)+3;static volatile bit a_4 @ ((unsigned)&a*8)+4;static volatile bit a_5 @ ((unsigned)&a*8)+5;static volatile bit a_6 @ ((unsigned)&a*8)+6;static volatile bit a_7 @ ((unsigned)&a*8)+7;tempo(unsigned int time){ // if time = 1 durata este de 13.3 ms realizata cu Timer1.}void transmit(char a){ // transmite TRISC6=0; // trece linia in space ( zero logic ) tempo(1); if(a_7==1) // bitul MSB. { TRISC6=1; } if(a_7==0) { TRISC6=0; } tempo(1); if(a_6==1) { TRISC6=1; } if(a_6==0) { TRISC6=0; } tempo(1); if(a_5==1) { TRISC6=1; } if(a_5==0) { TRISC6=0; } tempo(1); if(a_4==1) { TRISC6=1; } if(a_4==0) { TRISC6=0; } tempo(1); if(a_3==1) { TRISC6=1; } if(a_3==0) { TRISC6=0; } tempo(1); if(a_2==1) { TRISC6=1; } if(a_2==0) { TRISC6=0; } tempo(1); if(a_1==1) { TRISC6=1; } if(a_1==0) { TRISC6=0; } tempo(1); if(a_0==1) // LSB { TRISC6=1; } if(a_0==0) { TRISC6=0; } tempo(1); TRISC6=1; // bitul de stop ( un bit de stop si fara paritate ). tempo(1); TRISC6=1; // trece inapoi linia in stare mark ( unu logic ) }main(){ ... unsigned char b; TRISC6 = 1; RC6 = 0; // aici iesirea este in unu logic de la rezistenta de pull-up ... a = b; // se incarca in registrul a de transmisie registrul b. transmit(a); }Pe cand pentru varianta lui Liviu pentru subrutina de transmisie trebuie doar atat: void send( char byte ) { /* output one byte */ while( TXIF == 0 ) /* set when register is empty */ { Nop(); } TXREG = byte;}Asa ca eu cred ca voi opta pentru varianta lui Liviu intrucat daca implementez si UARTul ca mai susnu mai ajunge memoria de program. Deoarece fiecare PIC transmite informatii de la patru posturisupravegheate. Chiar si cu varianta PRO C Compiler cu optimizarea spatiului de memorie adica utilizarea intregii memorii, fata de varianta LITE C Compiler care nu scrie toata memoria de programsi are deci limitare. Am vorbit de PIC16F887 insa voi folosi defapt PIC16F690. PIC16F887 il folosesc ca pot face debugg si pot testa programele pe care apoi le bag in cele 7 microcontrollere PIC16F690ca nu-s dispus sa cumpar acel ICD header ( care e la vreo 200 RON ) ca sa fac debugg si pe PIC16F690.Va multumesc foarte mult pentru raspunsuri ***O sa va anunt rezultatele obtinute *** :rade:

Link spre comentariu

Varianta propusa de Liviu este perfect functionala si este de preferat fata de ce am explicat eu; am vrut insa doar sa prezint potentialul pericol de scurtcircuit, ce deriva din topologie- daca din diverse motive soft-ul din PIC o ia "pe aratura" si TX-ul ramane activ mai mult decat trebuie, cand un alt PIC va incerca sa transmita poate sa apara scc intre tx-uri. Daca se dezvolta un protocol "stufos", cu activarea/dezactivarea tx-urilor de catre master si acknowledge(confirmare) de la slave se pot evita astfel de probleme.

Link spre comentariu

Da, intradevar. Masterul ( calculatorul cu interfata ce face interogari ciclic pentru fiecare PIC )trimite interogarea pentru un PIC. PICul raspunde cu date dupa care asteapta cam 100 ms ( cred suficiente ) pana masterul ar trebui sa afiseze datele pe interfata. Dupa ce afiseaza datele pe interfata, masterul trimite interogare pentru al 2-lea PIC si asa mai departe. M-am gandit ca as mai putea sa setez watchdogul la valoarea de reset la perioada cea mai mica sau mica ( de ordinul milisecundelor ). Si daca ramane blocat TX-ul sau UARTul sa zicem sa reseteze PICu. Oricum dupa ce transmite bitul de stop fac TRISC6=1 si chiar daca ramane blocat TX-u nu se produce scc pentru ca "switchul" format cu poarta tristate este deschis ( inalta impedanta ). De exemplu scriu asa: ... // dupa ultima apelare a subrutinei de send(0xXX) clrwdt() TRISC6=1; // aici ar trebui sa sara imediat in starea de asteptare a urmatoarei interogari de la // master. Daca nu o face se reseteaza tot PICu // asteapta interogare // rutina de asteptare interogare: while( RCIF == 0 ) { ClrWdt(); // sau Nop() } Daca se reseteaza cu watchdog ar trebui sa ajunga repede la rutina de asteptare interogare de la master. Pe timpul blocarii daca masterul nu primeste datele de la acest PIC cu probleme ( asa cum e in faza actuala ) se blocheaza si masterul. Aici trebuie sa fac cumva la master sa treaca la urmatorul PIC sa-l interogheze chiar daca nu a primit raspuns de la PICul cu pricina in timp ce ii incrementeaza contorul de neraspunsuri asociat PICului cu pricina. Daca nu primeste sa zicem raspunsuri de 10 ori consecutiv ( contorul de neraspunsuri ajunge la valoarea 10 ) sa zicem, atunci masterul anunta utilizatorul ca PICu cu pricina are probleme si nu-i raspunde. Fiecare PIC sa aiba asociat in interfata master un contor de neraspunsuri ( o variabila unsigned int care trebuie sa ramana zero sau mai mica decat 10 neraspunsuri ). :dans:

Link spre comentariu

Aici trebuie sa fac cumva la master sa treaca la urmatorul PIC sa-l interogheze chiar daca nu a primit raspuns de la PICul cu pricina

Faci o rutina de receptie cu time-out. Dupa trimiterea unei comenzi masterul asteapta raspuns de la slave-ul adresat pentru o perioada determinata; daca nu a raspuns in acest timp memoreaza eroarea de comunicatie si trece la urmatorul. Se poate face cu timer hardware, cu bucle for/while cu durate de executie precalculate, etc.
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări