Forum: Mikrocontroller und Digitale Elektronik dsPIC33E - UART


von Flo (Gast)


Angehängte Dateien:

Lesenswert?

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

von Florian T. (florian_t91)


Lesenswert?

Ich hab vergessen zu erwähnen:

dsPIC33EP512MU810
8Mhz Quarz
mikromedia workstation 7

Gruß Flo

von Hermann U. (Firma: www.pcb-devboards.de) (gera82)


Lesenswert?

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

von Florian T. (florian_t91)


Lesenswert?

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?

von Hermann U. (Firma: www.pcb-devboards.de) (gera82)


Lesenswert?

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

von Hermann (Gast)


Lesenswert?

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 )

von Florian T. (florian_t91)


Angehängte Dateien:

Lesenswert?

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 ;)

von Patrick B. (p51d)


Lesenswert?

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
}

von Florian T. (florian_t91)


Lesenswert?

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?

von Florian T. (florian_t91)


Lesenswert?

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?

von Florian T. (florian_t91)


Lesenswert?

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

von Hermann U. (Firma: www.pcb-devboards.de) (gera82)


Lesenswert?

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

von Florian T. (florian_t91)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.