Hallo zusammen, Ich habe ein kleines Problem. Und zwar muss ich einen dsPIC programmieren. Erste Aufgaeb dabei ist eine Kommunikation zwischen µC und PC per UART herzustellen. Ich hab keine Erfahrungen mit dem dsPIC und mit allg. µC immernoch Anfänger. Nun zum Problem: Eine Verbindung besteht. Ich kann vom PC ein Zeichen senden, dieses wird am Controller empfangen und darauf eine Zeichenfolge zurückgesendet. Dies lässt sich Anhnd von LEDs und dem Terminal feststellen. Das Problem ist, dass nicht das ankommt was gesendet wurde sondern völliges Zeichen wirrwarr. Vielleicht kann mir ja hier jemand helfen? Meine Vermutung ist die Baudrate. Dem PC glaube ich mal das es dort stimmt (auf 115200 eingestellt). Danke im vorraus, Flo
Ich hab vergessen zu erwähnen: dsPIC33EP512MU810 8Mhz Quarz mikromedia workstation 7 Gruß Flo
Hallo, Ich habe dein Code nicht angeschaut, ich tippe mal esliget an dem Takt von dsPIC und/oder falscher BRGVAL Einstellung. Florian T. schrieb: > 8Mhz Quarz Das sagt nicht, wie schnell läuft das teil? Hier mal meine kleiner Ausschnitt (dsPIC33EP512MU814), was ohne Problem funtzt, die wichtigsten Stellen habe ich mal raus kopiert:
1 | #define SYS_FREQ 120000000UL // Mikrocontroller Takt 120Mhz = 60Mips
|
2 | #define FCY (SYS_FREQ/2) // instruction cycle time
|
3 | |
4 | #define BAUDRATE 115200UL
|
5 | #define BRGVAL ((FCY / BAUDRATE)/ 16UL) - 1UL
|
1 | /********************************************************************************
|
2 | * *
|
3 | * Funktion: OSCswitching *
|
4 | * *
|
5 | *------------------------------------------------------------------------------*
|
6 | * Description:
|
7 | ********************************************************************************/
|
8 | void OSCswitching(void) |
9 | {
|
10 | |
11 | /*
|
12 | * Configure oscillator to operate the device at Fcy = 60Mhz
|
13 | * Fosc = Fin*M/(N1*N2)
|
14 | * Fcy = Fosc/2
|
15 | * Fosc = 10Mhz * 48/(2 * 2) = 120MHz for 10MHz input clock
|
16 | * 60Mips
|
17 | *
|
18 | */
|
19 | PLLFBD = 46; /* M = 48 */ |
20 | CLKDIVbits.PLLPOST = 0; /* N1 = 2 */ |
21 | CLKDIVbits.PLLPRE = 0; /* N2 = 2 */ |
22 | |
23 | CLKDIVbits.DOZEN = 0; /* Processor clock and peripheral clock ratio forced to 1:1 */ |
24 | |
25 | RCONbits.SWDTEN = 0; //Disable Watch Dog Timer |
26 | |
27 | __builtin_write_OSCCONH(0b011); //Initiate clock switch to HS with PLL |
28 | |
29 | __builtin_write_OSCCONL(0b001); //Start clock switching |
30 | |
31 | while (OSCCONbits.COSC != 0b011) //Wait for clock switch to occur |
32 | |
33 | while(OSCCONbits.LOCK!=1) {}; //Wait for PLL to lock |
34 | }
|
Hier mal die UART Einstellung:
1 | U3MODEbits.USIDL = 0; /* Continue in Idle mode */ |
2 | U3MODEbits.LPBACK = 0; /* Disable LoopBack */ |
3 | U3MODEbits.PDSEL = 0b00; /* 8-bit data, no parity */ |
4 | U3MODEbits.STSEL = 0; /* One Stop bit */ |
5 | |
6 | U3BRG = BRGVAL; /* Baud rate generator value*/ |
7 | |
8 | IFS5bits.U3RXIF = 0; /* Clear interrupt flag */ |
9 | IPC20bits.U3RXIP = 1; /* Set to highest priority */ |
10 | IEC5bits.U3RXIE = 1; /* Enable receive interrupts */ |
11 | |
12 | |
13 | U3MODEbits.UARTEN = 1; /* Enable UART module 1 */ |
14 | U3STAbits.UTXEN = 1; /* Enable transmission, overrides TRIS settings */ |
Gruß Hermann
Wie schnell er läuft? Das würde ich auch gern wissen. Quarz hat 8Mhz, Instruction Cycle Time ist (glaube ich) 2. Meines Erachtens habe ich auf den extern Taktquelle geschaltet. => µC Takt: 4Mhz Oder habe ich da falsch gedacht?
Florian T. schrieb: > Wie schnell er läuft? Das würde ich auch gern wissen. Oszi dran dann weist du es;-) Oder einfach mal Pin toggeln Z.B. so, mit Oszi oder LED anklemmen: PIN = high delay_s(1) PIN = low Wenn PIN zu schnell oder zu langsam toggelt, dann weißt du das da was nicht stimmt ;-)
1 | #define delay_ns(d) { __delay32( (unsigned long) ((d)*(FCY)/1000000000UL)); }
|
2 | #define delay_us(d) { __delay32( (unsigned long) ((d)*(FCY)/1000000UL)); }
|
3 | #define delay_ms(d) { __delay32( (unsigned long) ((d)*(FCY)/1000UL)); }
|
4 | #define delay_s(d) { __delay32( (unsigned long) ((d)*(FCY)/1UL)); }
|
Mach mal folgendes, setze void OSCswitching(void) bei dir 1:1 ein, dann solltest du 96Mhz haben. Dann füge diesen abschnitt bei dir:
1 | #define SYS_FREQ 96000000UL // Mikrocontroller Takt 96Mhz = 48Mips
|
2 | #define FCY (SYS_FREQ/2) // instruction cycle time
|
3 | |
4 | #define BAUDRATE 115200UL //Baudrate bei dir anpassen!!!
|
5 | #define BRGVAL ((FCY / BAUDRATE)/ 16UL) - 1UL
|
UxBRG = BRGVAL; /* Baud rate generator value*/ Gruß Hermann
Florian T. schrieb: > Quarz hat 8Mhz, Instruction Cycle Time ist (glaube ich) 2. > Meines Erachtens habe ich auf den extern Taktquelle geschaltet. > > => µC Takt: 4Mhz Dann solltest du auch richtig einsetzten: #define F_CPU ( 8000000 / 2 ) // Und nicht 4, wie bei dir #define UBRG(x) ((( F_CPU / x ) / 16 ) - 1 )
Hermann danke schonmal für die Anworten und Tipps. Der delay_test.c war erfolgreich. LED war 2s an (soweit ich das mit meiner Handystoppuhr sagen kann). uart_test.c hat trotzdem nicht funktioniert. Immernoch undefinierte Zeichen. Statt dem String "test" kommen folgende Hexwerte: B1 2B B4 C8 F8 00 Die '00' sind denk ich i.O.. Bei den anderem Werten varriert es zum Teil auch ein wenig ( 91 2B B4 CC F8 00 ). Als ich dein OSCswitching() einfügen wollte ging gar nichts mehr. Vielleicht weitere Tipps? Flo EDIT: Das mit meinen falsch angegeben F_CPU: ich hatte verschiedene Einstellungen versucht und doch die falsch kopiert ;)
wie sieht die Funktion 'putsUART1()' aus? Was macht die? Ich tippe hier auf falsch eingestelltes Terminal oder falscher Clock, da der String "test" ja aus 4 Zeichen besteht und du 6 erhälst, die auch variiren... [EDIT]: Ansonsten versuchs mal hiermit (von Microchip code example Seite für dsPIC33E/F). Wenn dies auch nicht funktioniert mit den entsprechenden einstellungen hast du ein anderes Problem:
1 | /**********************************************************************
|
2 | * © 2006 Microchip Technology Inc.
|
3 | *
|
4 | * FileName: main.c
|
5 | * Dependencies: Header (.h) files if applicable, see below
|
6 | * Processor: dsPIC33FJ256GP710
|
7 | * Compiler: MPLAB® C30 v3.00 or higher
|
8 | * Tested On: dsPIC33FJ256GP710 HP16
|
9 | *
|
10 | * SOFTWARE LICENSE AGREEMENT:
|
11 | * Microchip Technology Incorporated ("Microchip") retains all ownership and
|
12 | * intellectual property rights in the code accompanying this message and in all
|
13 | * derivatives hereto. You may use this code, and any derivatives created by
|
14 | * any person or entity by or on your behalf, exclusively with Microchip's
|
15 | * proprietary products. Your acceptance and/or use of this code constitutes
|
16 | * agreement to the terms and conditions of this notice.
|
17 | *
|
18 | * CODE ACCOMPANYING THIS MESSAGE IS SUPPLIED BY MICROCHIP "AS IS". NO
|
19 | * WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
|
20 | * TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
|
21 | * PARTICULAR PURPOSE APPLY TO THIS CODE, ITS INTERACTION WITH MICROCHIP'S
|
22 | * PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
|
23 | *
|
24 | * YOU ACKNOWLEDGE AND AGREE THAT, IN NO EVENT, SHALL MICROCHIP BE LIABLE, WHETHER
|
25 | * IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR BREACH OF STATUTORY DUTY),
|
26 | * STRICT LIABILITY, INDEMNITY, CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL,
|
27 | * PUNITIVE, EXEMPLARY, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF
|
28 | * ANY KIND WHATSOEVER RELATED TO THE CODE, HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN
|
29 | * ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
30 | * ALLOWABLE BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO
|
31 | * THIS CODE, SHALL NOT EXCEED THE PRICE YOU PAID DIRECTLY TO MICROCHIP SPECIFICALLY TO
|
32 | * HAVE THIS CODE DEVELOPED.
|
33 | *
|
34 | * You agree that you are solely responsible for testing the code and
|
35 | * determining its suitability. Microchip has no obligation to modify, test,
|
36 | * certify, or support the code.
|
37 | *
|
38 | * REVISION HISTORY:
|
39 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
40 | * Author Date Comments on this revision
|
41 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
42 | * Rob Welch 11/28/06 Original Release
|
43 | *
|
44 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
45 | * ADDITIONAL NOTES:
|
46 | * Small, bare bones program to guide designers with UART implementation
|
47 | * To run program, plug DB9 cable to Terminal (9600,8,N,1) -
|
48 | * Data sent from TERMINAL END will be represented as binary equivalent
|
49 | * of ASCII on 7 LSB LEDs of HPC16 Explorer board
|
50 | *
|
51 | * Data is sent from HPC16 by pressing S3 - S6. A single letter will
|
52 | * be transmitted upon each keypress.
|
53 | *
|
54 | * Peripheral Library was not utilized, Bit Addressing was used in order
|
55 | * to show all details involved in initialization of UART.
|
56 | *
|
57 | *
|
58 | * The Processor starts with the Internal oscillator without PLL enabled and then the Clock is switched to PLL Mode.
|
59 | *
|
60 | **********************************************************************/
|
61 | #include <p33FJ256GP710.h> |
62 | |
63 | _FOSCSEL(FNOSC_FRC); // Internal FRC oscillator |
64 | _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE); |
65 | // Clock Switching is enabled and Fail Safe Clock Monitor is disabled
|
66 | // OSC2 Pin Function: OSC2 is Clock Output
|
67 | // Primary Oscillator Mode: XT Crystanl
|
68 | |
69 | |
70 | #define TRUE 1
|
71 | #define FALSE 0
|
72 | |
73 | unsigned char S3Flag, S4Flag, S5Flag, S6Flag; |
74 | |
75 | void __attribute__ ((interrupt, no_auto_psv)) _U2RXInterrupt(void) { |
76 | LATA = U2RXREG; |
77 | IFS1bits.U2RXIF = 0; |
78 | }
|
79 | void __attribute__ ((interrupt, no_auto_psv)) _U2TXInterrupt(void) { |
80 | IFS1bits.U2TXIF = 0; |
81 | }
|
82 | |
83 | void InitClock() { |
84 | PLLFBD = 38; // M = 40 |
85 | CLKDIVbits.PLLPOST = 0; // N1 = 2 |
86 | CLKDIVbits.PLLPRE = 0; // N2 = 2 |
87 | OSCTUN = 0; |
88 | RCONbits.SWDTEN = 0; |
89 | |
90 | // Clock switch to incorporate PLL
|
91 | __builtin_write_OSCCONH(0x01); // Initiate Clock Switch to |
92 | // FRC with PLL (NOSC=0b001)
|
93 | __builtin_write_OSCCONL(0x01); // Start clock switching |
94 | while (OSCCONbits.COSC != 0b001); // Wait for Clock switch to occur |
95 | |
96 | while(OSCCONbits.LOCK != 1) {}; |
97 | }
|
98 | |
99 | void InitUART2() { |
100 | // This is an EXAMPLE, so brutal typing goes into explaining all bit sets
|
101 | |
102 | // The HPC16 board has a DB9 connector wired to UART2, so we will
|
103 | // be configuring this port only
|
104 | |
105 | // configure U2MODE
|
106 | U2MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func |
107 | //U2MODEbits.notimplemented; // Bit14
|
108 | U2MODEbits.USIDL = 0; // Bit13 Continue in Idle |
109 | U2MODEbits.IREN = 0; // Bit12 No IR translation |
110 | U2MODEbits.RTSMD = 0; // Bit11 Simplex Mode |
111 | //U2MODEbits.notimplemented; // Bit10
|
112 | U2MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not |
113 | U2MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here) |
114 | U2MODEbits.LPBACK = 0; // Bit6 No Loop Back |
115 | U2MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55') |
116 | U2MODEbits.URXINV = 0; // Bit4 IdleState = 1 (for dsPIC) |
117 | U2MODEbits.BRGH = 0; // Bit3 16 clocks per bit period |
118 | U2MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity |
119 | U2MODEbits.STSEL = 0; // Bit0 One Stop Bit |
120 | |
121 | // Load a value into Baud Rate Generator. Example is for 9600.
|
122 | // See section 19.3.1 of datasheet.
|
123 | // U2BRG = (Fcy/(16*BaudRate))-1
|
124 | // U2BRG = (37M/(16*9600))-1
|
125 | // U2BRG = 240
|
126 | U2BRG = 240; // 40Mhz osc, 9600 Baud |
127 | |
128 | // Load all values in for U1STA SFR
|
129 | U2STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!) |
130 | U2STAbits.UTXINV = 0; //Bit14 N/A, IRDA config |
131 | U2STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15 |
132 | //U2STAbits.notimplemented = 0; //Bit12
|
133 | U2STAbits.UTXBRK = 0; //Bit11 Disabled |
134 | U2STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph |
135 | U2STAbits.UTXBF = 0; //Bit9 *Read Only Bit* |
136 | U2STAbits.TRMT = 0; //Bit8 *Read Only bit* |
137 | U2STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved |
138 | U2STAbits.ADDEN = 0; //Bit5 Address Detect Disabled |
139 | U2STAbits.RIDLE = 0; //Bit4 *Read Only Bit* |
140 | U2STAbits.PERR = 0; //Bit3 *Read Only Bit* |
141 | U2STAbits.FERR = 0; //Bit2 *Read Only Bit* |
142 | U2STAbits.OERR = 0; //Bit1 *Read Only Bit* |
143 | U2STAbits.URXDA = 0; //Bit0 *Read Only Bit* |
144 | |
145 | IPC7 = 0x4400; // Mid Range Interrupt Priority level, no urgent reason |
146 | |
147 | IFS1bits.U2TXIF = 0; // Clear the Transmit Interrupt Flag |
148 | IEC1bits.U2TXIE = 1; // Enable Transmit Interrupts |
149 | IFS1bits.U2RXIF = 0; // Clear the Recieve Interrupt Flag |
150 | IEC1bits.U2RXIE = 1; // Enable Recieve Interrupts |
151 | |
152 | U2MODEbits.UARTEN = 1; // And turn the peripheral on |
153 | |
154 | U2STAbits.UTXEN = 1; |
155 | // I think I have the thing working now.
|
156 | }
|
157 | |
158 | void InitPorts() { |
159 | // S3 (portD Pin 6, chosen as trigger for sending 'M' to UART)
|
160 | // S6 (portD Pin 7, chosen as trigger for sending 'C' to UART)
|
161 | // S5 (portA Pin 7, chosen as trigger for sending 'H' to UART)
|
162 | // S4 (portD Pin 13, chosen as trigger for sending 'P' to UART)
|
163 | |
164 | TRISD = 0x20C0; // D6,7,13 inputs |
165 | AD1PCFGHbits.PCFG23 = 1; // This is important. RA7 is muxxed with AN23, |
166 | // So we need to config the pin as DIGITAL
|
167 | TRISA = 0x0080; // only 0th bit needs be output. A7 is input |
168 | S3Flag = S4Flag = S5Flag = S6Flag = 0; // Some Debounce Flags |
169 | }
|
170 | |
171 | void SoftwareDebounce() { |
172 | if(PORTDbits.RD6 == FALSE) { |
173 | if( S3Flag == FALSE ) { |
174 | S3Flag = TRUE; |
175 | U2TXREG = 'M'; |
176 | }
|
177 | }
|
178 | else { |
179 | S3Flag = FALSE; |
180 | }
|
181 | if(PORTDbits.RD7 == FALSE) { |
182 | if( S6Flag == FALSE ) { |
183 | S6Flag = TRUE; |
184 | U2TXREG = 'C'; |
185 | }
|
186 | }
|
187 | else { |
188 | S6Flag = FALSE; |
189 | }
|
190 | if(PORTAbits.RA7 == FALSE) { |
191 | if( S5Flag == FALSE ) { |
192 | S5Flag = TRUE; |
193 | U2TXREG = 'H'; |
194 | }
|
195 | }
|
196 | else { |
197 | S5Flag = FALSE; |
198 | }
|
199 | if(PORTDbits.RD13 == FALSE) { |
200 | if( S4Flag == FALSE ) { |
201 | S4Flag = TRUE; |
202 | U2TXREG = 'P'; |
203 | }
|
204 | }
|
205 | else { |
206 | S4Flag = FALSE; |
207 | }
|
208 | }
|
209 | int main(void) { |
210 | |
211 | InitClock(); // This is the PLL settings |
212 | |
213 | InitUART2(); // Initialize UART2 for 9600,8,N,1 TX/RX |
214 | |
215 | InitPorts(); // LEDs outputs, Switches Inputs |
216 | |
217 | while(1) { // The ever versatile Infinite Loop! |
218 | SoftwareDebounce(); |
219 | }
|
220 | }
|
putsUART1 ist eine Funktion aus der Bibliothek <uart.h> des xc16 Compilers Ich hoffe doch mal, dass ich die so einfach verwenden kann. Naja wenn ich am Terminal einfach mal einseitig die Baudrate ändere bekomme ich auch unterschiedlich lange Antworten. Aber danke für deine Antwort. Flo Edit: Ich hatte mir das Beispiel auch schon angeschaut und dachte ich hätte alles beachtet. Außerdem würde ich doch gerne die lib verwenden. Warum das Rad neu erfinden?
Ich hab jetzt mal das Beispiel (das gibts auch passend für meinen µC) probiert und an den nötigen Stellen angepasst (Anschlussbelegung UART, FOSC, etc). Tatsächlich es funktioniert. Abgesehen vom 'H', das mag nicht. Also gar nicht. Schätze das liegt aber an meinem Board und müsste mit entsprechenden Anpassungen auch klappen. Ich versuch jetzt mal das Beispiel mit meinem ersten Code zu "paaren", vielleicht klappts. Falls noch wer Vorschläge hat wo mein Fehler liegen könnte, immer her damit. Dank an alle, Flo EDIT: Mir ist grad noch aufgefallen: Hab mein 8Mhz Wert zur Berechnung der BdRate genommen obwohl das Beispiel den internen FRC verwendet. Und trotzdem funktionierts?
Ok. Meine letzte Frage kann ich mir selbst beantworten. Hab fehler mit Fehler geschlagen. Der interne FRC hat nominal 7.37Mhz. Zur Berechnung von FOSC hab ich für M 38 statt 40 genommen. Hat dann wohl zufällig noch gepasst. FOSC = ( FIN * M ) / ( N1 * N2 ) Baudrate gewünscht 9600 alt: FIN = 8Mhz, M = 38 => FOSC = 76 000 000 => BRGVAL = 246 neu: FIN = 7.37Mhz, M = 40 => FOSC = 73 700 000 => BRGVAL = 238
Patrick B. schrieb: > Ich tippe hier auf falsch eingestelltes Terminal oder falscher Clock, da > der String "test" ja aus 4 Zeichen besteht und du 6 erhälst, die auch > variiren... Florian T. schrieb: > Abgesehen vom 'H', das mag nicht. Also gar nicht. Schätze das liegt aber > an meinem Board und müsste mit entsprechenden Anpassungen auch klappen. Besorg dir mal ein Oszilloskop, dann gehts auch schneller voran. Damit kannst die Fehler schneller einkreisen. Gruß Hermann
Ja. Also ein eigenes hab ich nicht und kann ich mir auch nicht leisten. Ich hätt hier zwar eventuell Zugriff auf eines aber ich wüsst auch gar nicht wo ich da was abgreifen soll (http://www.mikroe.com/mikromedia/dspic33ep/ mit der workstation 7). Ich habs jetzt mit angehängtem Code zum laufen gebracht. Ist ein Mix aus allem hier angebotenen inklusive meiner Lösung. Musste den internern FRC verwenden. Beim Versuch am Anfang des Programs auf das externe Quarz mit PLL zu wechseln hat nichts funktioniert. Was die Geschwindigkeit angeht dürfte es da kein Problem geben. Ob 8MHz oder den 7.37MHz ist Wurst. Solange ich sauber per UART kommunizieren kann ist die Genauigkeit auch egal. Danke an alle die geantwortet haben Flo PS: Das nächste Problem wartet bestimmt schon :D
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.