Vizitator alex20 Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 Buna ziua, Intampin o problema la programarea unui PIC24F16KA102. Doresc sa implementez comuncatie UART prin intermediul tool-ului PicKit-ului.Codul meu este urmatorul : void UART1Init(int BAUDRATE){ U1BRG = BAUDRATE; U1MODEbits.UARTEN = 1; // UART2 is Enabled U1MODEbits.USIDL = 0; // Continue operation at Idlestate U1MODEbits.IREN = 0; // IrDA En/Decoder is disabled U1MODEbits.RTSMD = 0; // flow control mode U1MODEbits.UEN = 0b10; // UTX, RTX, U2CTS, U2RTS are enable and on use. U1MODEbits.WAKE = 1; // Wake-up on start bit is enabled U1MODEbits.LPBACK = 0; // Loop-back is disabled U1MODEbits.ABAUD = 0; // auto baud is disabled U1MODEbits.RXINV = 0; // No RX inversion U1MODEbits.BRGH = 0; // low boud rate U1MODEbits.PDSEL = 0b00; // 8bit no parity U1MODEbits.STSEL = 1; // one stop bit U1STAbits.UTXISEL1 = 0b00; U1STAbits.UTXBRK = 0; // sync break tx is disabled U1STAbits.UTXEN = 1; //transmit is enabled U1MODEbits.RXINV = 1; //Invert RX and TX Idle state U1STAbits.UTXINV = 1;}void UART1putChar(unsigned char ch){ while(U1STAbits.UTXBF == 1); //wait till transmit buffer is not full anymore U1TXREG = (ch);}char UART1GetChar(){ char Temp; //wait for buffer to fill up, wait for interrupt while(IFS0bits.U1RXIF == 0); Temp = U1RXREG; //reset interrupt IFS0bits.U1RXIF = 0; //return my received byte return Temp;} Iar main-ul este : int main(void) { init(); TRISB=0x0004; UART1Init(25); while(1) { UART1putChar(UART1GetChar()); } return 0;} Outputul : heklloTX: 68 65 6B 6C 6C 6F RX: 85 TX: 68 65 6B 6C 6C 6F RX: 85 TX: 68 65 6B 6C 6C 6F RX: 88 TX: 68 65 6B 6C 6C 6F RX: 85 TX: 68 65 6B 6C 6C 6F RX: 63 0C TX: 68 65 6B 6C 6C 6F RX: 88 TX: 68 65 6B 6C 6C 6F RX: 88 TX: 68 65 6B 6C 6C 6F RX: 61 0C De unde pot proveni aceste probleme? Ce am configurat / codat gresit ? Va multumesc, Alex Link spre comentariu
Mondan Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 (editat) UART1Init(25); Ce Baudrate ai selectat din PICKIT2? Apoi vezi ca mai trebuiesc si ceva delay-uri. Destul de mici depinzand de baudrate. A, U1BRG = BAUDRATE; registrul asta ia o anumita valoare. Cat este boudrate-ul in acest caz? Coincinde cu cel de la PICKIT ? Editat Mai 15, 2016 de Mondan Link spre comentariu
Vizitator alex20 Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 In primul rand multumesc pentru raspuns. Baudrate-ul l-am calculat utilizand datasheet-ul controller-ului • FCY = 4 MHz (FOSC = 8MHz, FCY = FOSC/2) • Desired Baud Rate = 9600 => UxBRG = 25 UxBRG este un prescaler pentru Baud Rate-ul de 9600. Si intr-adevar, coincide cu cel selectat din PicKit. Ai mentionat ceva de niste delay-uri. Cat ar trebui sa fie de mari? Imi inchipui ca milisecunde ar fi indeajuns, intrucat are timp sa umple sau sa termine de manipulat registrii de scriere/citire. Unde ar trebui mai aceste delay-uri puse? Multumesc! Link spre comentariu
Mondan Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 1. Daca treci pe MikroC vei vedea ca se descarca gratis si e mult mai simplu. Initialize direct cu Baudrate, face el calcule si initializari de registri. Urmezi un exemplu de acolo si s-ar putea sa merga brici. 2. Pentru acelsi program eu as face asa: -as incepe cu un singur byte trimis din PICKIT fara terminatia clasinca 0x0a +0x0d =Enter. Sa zicem: h TX: 68 RX: 85TX: 68 RX: 88 - as desparti putin cele doua instructiuni: int main(void) { init(); TRISB=0x0004; UART1Init(25); while(1) {char c;c=UART1GetChar(); Delay 200mS UART1putChar(c);Delay 200mS } return 0;} - daca nici pana aici nu merge transmite cu PIC-ul cate un Byte la fiecare secunda: int main(void) { init(); TRISB=0x0004; UART1Init(25); while(1) { UART1putChar('A');Delay 1000mS sau Delau 5000mS } return 0;} Ar trebui sa trimita catre PICKIT o serie de "A". Daca nu il interpreteza bine ca "A" as folosit Logic Analyser tot de langa Serial Monitor din PIckit. Linia seriala IDLE e in 1 logic si bitul de start cand apare ii da 0 logic. As vede forma impulsului si as masura fiecare bit ce durata are. Daca si pana aici e corect....ne mai gandim. Eu am vazut acel 88 sau 85 ca raspuns din PIC. De asta m-am gandit ca ar fi o neconcordanta la baudrate. Sa verifici si cuartul. 8 din hexa e 1000 in binar 1000 0101 in loc de 68 sau 6f 01101000 sau 1111 1000 Eu as mai incerca si asta: As pune un LED sa licare la fiecare secunda sa vad daca compilatorul interpreteaza bine notiunea timpului: int main(void) { init(); TRISB=0x0004; UART1Init(25); while(1) { LED=ONDelay 500mS LED=OFFDelay 500mS } return 0;} Link spre comentariu
Vizitator alex20 Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 Am identificat prima problema. Eu mersesem pe ideea ca mi-am configurat cum trebuie oscilatorul pt 8MHz si mi-am creat singur rutina de delay : void wait(int ms){ int i=0, j=0; for (i = 0; i < ms; i++) for (j = 0; j < 8000; j++) asm("nop");} Pentru apel wait(1000), ciclul for va rula de 1000*8000 = 8 000 000 ori. Iar la 8MHz inseamna 1000 ms = 1 secunda. Dar aparent, un wait(1000) dureaza aprox 18 secunde, am determinat frecventa reala undeva pe la 500 kHz. Daca nu cer prea mult, imi poti spune ce am gresit in configurare? // FOSCSEL#pragma config FNOSC = FRCDIV // Oscillator Select (8 MHz FRC oscillator with divide-by-N (FRCDIV))#pragma config IESO = ON // Internal External Switch Over bit (Internal External Switchover mode enabled (Two-Speed Start-up enabled))// FOSC#pragma config POSCMOD = NONE // Primary Oscillator Configuration bits (Primary oscillator disabled)#pragma config OSCIOFNC = ON // CLKO Enable Configuration bit (CLKO output disabled; pin functions as port I/O)#pragma config POSCFREQ = HS // Primary Oscillator Frequency Range Configuration bits (Primary oscillator/external clock input frequency greater than 8 MHz)#pragma config SOSCSEL = SOSCHP // SOSC Power Selection Configuration bits (Secondary oscillator configured for high-power operation)#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Both Clock Switching and Fail-safe Clock Monitor are disabled) Link spre comentariu
Liviu M Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 Ce fel de oscilator vrei sa folosesti? Quarz extern sau oscilatorul intern? Link spre comentariu
Vizitator alex20 Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 Oscilatorul intern al PICului. http://ww1.microchip.com/downloads/en/DeviceDoc/39927c.pdf pagina 93 Am citit-o si rascitit-o. Nu pot seta ceasul sa mearga la 8MHz. Merge doar undeva la 500kHz. Nu am nici osciloscop la dispozitie pentru a spune exact. Este din configuration bits? Din rutina de initializare? Link spre comentariu
UDAR Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 (editat) Bucla aia , așa cum ai gândit-o , mi se pare că nu are cum să dureze 1000ms ci mult mai mult , chiar la 8MHz frecvența ceasului . Bucla internă se repetă într-adevăr de 8000000 de ori dar durata ei este de câteva µs , nu de una - o instrucțiune consumă minim 2µs ( dacă nu mă înșel ) și acolo ai mai multe instrucțiuni , nu numai NOP-ul ăla . PS Scuze dacă greșesc , sunt în faza de învățare cu PIC-ul . Editat Mai 15, 2016 de UDAR Link spre comentariu
Mondan Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 La serial trebuie folosit cuart (extern). La 1-2 bytei trimisi mai merge uneori oscilator intern dar un string lung nu merge. Pune cuart extern. Pai nu mi-ai raspuns la cateva. Daca transmiti serial din PIC o serie de A sa zicem ce ai la receptie? Atat pe UART sau Analizor serial cat si pe Logical Alalizer(PICKIT). Si pui pozele aici(o parte din Print screen). Link spre comentariu
Vezi Muti Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 La serial trebuie folosit cuart (extern). La 1-2 bytei trimisi mai merge uneori oscilator intern dar un string lung nu merge. Pune cuart extern. Cum ai ajuns la concluzia asta? Link spre comentariu
Mondan Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 <<http://ww1.microchip...eDoc/39927c.pdf pagina 93>> In astfel de cazuri eu plec de la cum vad forma pe Logic Analyser si trag concluzii despre ce e gresit in configuratie. Cum ai ajuns la concluzia asta? A........... fara chestii retorice. Spune ca e gresit si gata. Pentru restul am ajuns la concluzia asta dupa multa, multa practica. Exista resincronizare la receptia seriala intra-adevar pentru multe dev. Daca rising edge vine intr-un interval presatabili. Link spre comentariu
Liviu M Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 La PIC-urile pe 8 biti (PIC16 & PIC18), frecventa "reala" e frecventa oscilatorului /4. La asta am gasit numai ca Instruction cycle period (TY) equals two times the input oscillator time base period. La 8 MHz ar insemna o frecventa reala (pe instructiune) de 4 MHz => 250 ns/instructiune. Ca sa iasa oscilator intern de 8 MHz, mie imi da: - din schema de la pagina 91 - FRC - tabelul 9-1 (pag. 92) => POSCMD<1:0> = 11, FNOSC<2:0> = 000 (ultimul rand) De aici mie imi iese OSCCON = 0x0000. Restul registrilor (CLKDIV si OSCTUNE) i-as lasa in pace. La bitii de configurare (aia cu #pragma) as zice ca trebuie modificati: - FNOSC<2:0> = 000, probabil #pragma config FNOSC = FRC // Oscillator Select (8 MHz FRC), n-ai nevoie de divizor- switchover-ul nu cred ca te intereseaza in stadiul asta #pragma config IESO = OFF // Internal External Switch Over bit (Internal External Switchover mode enabled (Two-Speed Start-up enabled))Restul par OK. Link spre comentariu
Vezi Muti Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 (editat) <<http://ww1.microchip...eDoc/39927c.pdf pagina 93>> In astfel de cazuri eu plec de la cum vad forma pe Logic Analyser si trag concluzii despre ce e gresit in configuratie. A........... fara chestii retorice. Spune ca e gresit si gata. Pentru restul am ajuns la concluzia asta dupa multa, multa practica. Exista resincronizare la receptia seriala intra-adevar pentru multe dev. Daca rising edge vine intr-un interval presatabili. Exista pe dracu sincronizare la receptie dupa.... Dupa ce? Dupa cotele apelor? Userul de mai sus a formulat destul de bine problema pe care o are. Nu inteleg ce forme vezi tu pe Logic Analyser. Da' chiar. Cum arata ,functie de oscilator intern sau extern, pe LOGIC ANALYSER? poze? Nu a fost o intrebare retorica: Pe ce te bazezi cand dai astfel de sfaturi? Editat Mai 15, 2016 de Vezi Muti Link spre comentariu
Liviu M Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 In cazul in care oscilatorul intern e "decalibrat", sunt sanse ca comunicatia sa aibe de suferit, da' eu as zice ca daca merge un byte, merg toti. Adica ori e decalibrat si nu mai merge nimic, ori e calibrat si atunci merge de tot. Din experienta de pana acum (m-am jucat cu niste 18F14k50 + oscilator intern la o comunicatie seriala "atipica") n-am avut probleme cu oscilatorul intern. A, ca mi-am adus aminte, xc8 (si presupun ca si xc16) are deja o functie (un macro ?) pentru ms -> __delay_ms(), nu cred ca e cazul sa mai definesti alta. Link spre comentariu
Vizitator alex20 Postat Mai 15, 2016 Partajează Postat Mai 15, 2016 (editat) Va multumesc tuturor pentru raspunsuri. Stiu ca ar fi fost extrem de util un osciloscop sau un alt device (logic analyser samd) pentru depanare, dar in lipsa acestora ne descurcam prin trial and error. Nu cred ca este cazul sa facem un flame din cauza opiniilor diferite. Liviu_M, am modificat registrii respectivi. Legat insa de macro-ul __delay_ms() de care ai pomenit - aparent este definit intrucat recunoaste functia - nu o subliniaza, dar da eroare la compilare. Trebuie inclusa vreo biblioteca speciala? Daca da, cum se numeste? Editat Mai 15, 2016 de alex20 Link spre comentariu
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum