Forum: Mikrocontroller und Digitale Elektronik PIC32MX795F512L UART-Nummern


von Klatec (Gast)


Lesenswert?

Hallo Zusammen

Ich habe seit kurzen mit dem PIC32 begonnen und arbeite nach einander so 
manches Beispiel von Microchip durch. Ein Example mit einem UART habe 
ich auch zum laufen gebracht. Hier wird die UART mit 0 (Null) 
bezeichnet, erstens einmal gibt es beim oben angegebenen PIC keine 
Uart0, sondern diese heißen U1A,U1B,U2A,U2B,U3A,U3B. Durch die 
Port-Einstellungen konnte ich jedoch herausfinden dass es sich um die 
RF4 (RX) und RF5 (TX) handelt.
Nun möcht ich ein weiteres Beispiel testen und hier wird der UART1 
verwendet, nachfolgend der Code. Im Library Guide gibt es nur UART1 und 
2 von z.B. der Funktion OpenUART1.
Es muss doch eine Möglichkeit geben die UART's den Hardware Ein- 
Ausgängen zuzuorden. In den verschieden Beschreibungen konnte ich auch 
keine Hinweise finden. Bitte um Hilfe.
Danke.

Lg.
Johann K



/*********************************************************************
 *
 *                  DMA Uart echo example file
 *
 *********************************************************************
 * FileName:        uart_echo.c
 * Dependencies:  plib.h
 *
 * Processor:       PIC32MX
 *
 * Complier:        MPLAB C32 v1 or higher
 *                  MPLAB IDE v8 or higher
 * Company:         Microchip Technology Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the “Company”) for its PIC Microcontroller is intended
 * and supplied to you, the Company’s customer, for use solely and
 * exclusively on Microchip PIC Microcontroller products.
 * The software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id: dma_api_example.c 4261 2007-08-22 16:32:28Z aura $
 *
 ********************************************************************/

#include <stdlib.h>
#include <time.h>

#include <plib.h>



// prototypes
void  DmaDoUartEchoExample(int pbClk);

// some local data
int    DmaIntFlag;      // flag used in interrupts

// Configuration Bit settings
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, 
FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2

#if defined (_32MX460F512L_) || defined (_32MX360F512L_) || defined 
(_32MX795F512L_)
#define SYS_FREQ (80000000L)
#elif defined (_32MX220F032D_) || defined (_32MX250F128D_)
#define SYS_FREQ (40000000L)
#endif

#define  BAUDRATE  57600  // serial baudrate

/*********************************************************************
 * Function:        int main(void)
 *
 * PreCondition:    None
 *
 * Input:      None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:    Examples for the usage of the DMA Peripheral Lib
 *
 * Note:            None.
 ********************************************************************/
int  main(void)
{
  int  pbClk;    // the PB frequency

  // Configure the device for maximum performance but do not change the 
PBDIV
  // Given the options, this function will change the flash wait states, 
RAM
  // wait state and enable prefetch cache but will not change the PBDIV.
  // The PBDIV value is already set via the pragma FPBDIV option above..
  pbClk=SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);


  // receive some data from the UART port and echo it back
  DmaDoUartEchoExample(pbClk);


  return 1;
}




/*********************************************************************
 * Function:        void DmaDoUartEchoExample(int pbClk)
 *
 * PreCondition:    None
 *
 * Input:      pbClk  - the PB frequency
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:    Examples for receiving some data from the UART and 
echoing it back using the DMA Peripheral Lib.
 *           The received data is expected to end with a CR and has to 
be less than DmaGetMaxTxferSize() bytes in length.
 *           We'll enable the DMA interrupts to signal us when the 
transfer is done.
 *
 * Note:            None.
 ********************************************************************/
void DmaDoUartEchoExample(int pbClk)
{
  char     dmaBuff[256+1];    // we'll store the received data here
  DmaChannel  chn=DMA_CHANNEL1;  // DMA channel to use for our example
            // NOTE: the ISR setting has to match the channel number

  OpenUART1(UART_EN, UART_RX_ENABLE|UART_TX_ENABLE, 
pbClk/16/BAUDRATE-1);     // selected baud rate, 8-N-1

  putsUART1("\r\nType up to 256 characters long string followed by Enter 
key...\r\n\r\n");


  // configure the channel
  DmaChnOpen(chn, DMA_CHN_PRI2, DMA_OPEN_MATCH);

  DmaChnSetMatchPattern(chn, '\r');  // set \r as ending character

  // set the events: we want the UART2 rx interrupt to start our 
transfer
  // also we want to enable the pattern match: transfer stops upon 
detection of CR
  DmaChnSetEventControl(chn, 
DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN|DMA_EV_START_IRQ(_UART1_RX_IRQ));

  // set the transfer source and dest addresses, source and dest sizes 
and the cell size
  DmaChnSetTxfer(chn, (void*)&U1RXREG, dmaBuff, 1, sizeof(dmaBuff), 1);

  DmaChnSetEvEnableFlags(chn, DMA_EV_BLOCK_DONE);    // enable the 
transfer done interrupt: pattern match or all the characters transferred

  // enable system wide multi vectored interrupts
  INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
  INTEnableInterrupts();

  INTSetVectorPriority(INT_VECTOR_DMA(chn), INT_PRIORITY_LEVEL_5);    // 
set INT controller priority
  INTSetVectorSubPriority(INT_VECTOR_DMA(chn), 
INT_SUB_PRIORITY_LEVEL_3);    // set INT controller sub-priority

  INTEnable(INT_SOURCE_DMA(chn), INT_ENABLED);    // enable the chn 
interrupt in the INT controller

  DmaIntFlag=0;        // clear the interrupt flag

  // enable the chn
  DmaChnEnable(chn);

  // let the user know that he has to enter a string
  // for example, you could do something like:
  // printf("\r\nType a string less than 256 characters followed by 
Enter key...Will echo it using the DMA\r\n\r\n");

  // wait for the data to come in
  while(!DmaIntFlag);      // just block here. In a real application you 
can do some other stuff while the DMA transfer is taking place

  // ok, we've received the data in the buffer
  putsUART2("\r\nReceived the character string. Now echoing it 
back...\r\n\r\n");

  // now the TX part
  // reconfigure the channel
  DmaChnOpen(chn, DMA_CHN_PRI2, DMA_OPEN_MATCH);

  // set the events: now the start event is the UART tx being empty
  // we maintain the pattern match mode
  DmaChnSetEventControl(chn, 
DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN|DMA_EV_START_IRQ(_UART1_TX_IRQ));

  // set the transfer source and dest addresses, source and dest size 
and cell size
  DmaChnSetTxfer(chn, dmaBuff, (void*)&U1TXREG, sizeof(dmaBuff), 1, 1);

  DmaChnSetEvEnableFlags(chn, DMA_EV_BLOCK_DONE);    // enable the 
transfer done interrupt: pattern match or all the characters transferred

  INTEnable(INT_SOURCE_DMA(chn), INT_ENABLED);    // enable the chn 
interrupt in the INT controller

  DmaIntFlag=0;    // clear the interrupt flag

  DmaChnStartTxfer(chn, DMA_WAIT_NOT, 0);  // force the DMA transfer: 
the UART2 tx flag it's already been active

  // wait for data to be output
  while(!DmaIntFlag);      // just block here

  // DMA Echo is complete

  INTEnable(INT_SOURCE_DMA(chn), INT_DISABLED);    // disable further 
interrupts from the DMA controller

  putsUART1("\r\nEcho back completed...\r\n\r\n");


}

// handler for the DMA channel 1 interrupt
void __ISR(_DMA1_VECTOR, ipl5) DmaHandler1(void)
{
  int  evFlags;        // event flags when getting the interrupt

  INTClearFlag(INT_SOURCE_DMA(DMA_CHANNEL1));  // release the interrupt 
in the INT controller, we're servicing int

  evFlags=DmaChnGetEvFlags(DMA_CHANNEL1);  // get the event flags

    if(evFlags&DMA_EV_BLOCK_DONE)
    { // just a sanity check. we enabled just the DMA_EV_BLOCK_DONE 
transfer done interrupt
    DmaIntFlag=1;
    DmaChnClrEvFlags(DMA_CHANNEL1, DMA_EV_BLOCK_DONE);
    }
}

von Klatec (Gast)


Lesenswert?

Nochmals ein Stück nach vor.

von Carsten S. (dg3ycs)


Lesenswert?

Hallo Johann,

Klatec schrieb:
> Ich habe seit kurzen mit dem PIC32 begonnen und arbeite nach einander so
> manches Beispiel von Microchip durch. Ein Example mit einem UART habe
> ich auch zum laufen gebracht. Hier wird die UART mit 0 (Null)
> bezeichnet, erstens einmal gibt es beim oben angegebenen PIC keine
> Uart0, sondern diese heißen U1A,U1B,U2A,U2B,U3A,U3B. Durch die
> Port-Einstellungen konnte ich jedoch herausfinden dass es sich um die
> RF4 (RX) und RF5 (TX) handelt.

Also UART0 finde ich tatsächlich sehr merkwürdig, denn normalerweise 
sollte es ja bei UART1 beginnen. Was war das denn für ein Beispiel? 
Original von Microchip? evtl ein sehr altes?
Oder wurde irgendetwas anderes umdefiniert...?

Aber um zur aktuellen Frage zu kommen:
Hinsichtlich der Bezeichnungen wirfst du gerade glaueb ich nur die 
Modulbezeichnung und die Pinnahmen durcheinander.
Der PIC32MX795L hat 6 UARTS die mit UART1... UART6 benannt sind.
(Wobei die höheren Modulnummern abgespeckte Module bezeichnen die nur 
benutzt werden können wenn die unteren Module auch nur im Basismode ohne 
Hardwareflusssteuerung verwendet werden)

Zu diesen Modulen gehören dann die mit UxTX und UxRX bezeichneten IO 
Pins.
Beispielsweise besitzt das Modul UART1 die IOs !U1CTS, !U1RTS, U1RX, 
U1TX.

Klatec schrieb:
> Nun möcht ich ein weiteres Beispiel testen und hier wird der UART1
> verwendet, nachfolgend der Code. Im Library Guide gibt es nur UART1 und
> 2 von z.B. der Funktion OpenUART1.
> Es muss doch eine Möglichkeit geben die UART's den Hardware Ein-
> Ausgängen zuzuorden. In den verschieden Beschreibungen konnte ich auch
> keine Hinweise finden. Bitte um Hilfe.

Ja, die Gibt es. Zum einen kannst du ja an den Nummern erkennen welche 
IOs zu welchem UART Modul gehören. UART1 alles was mit U1xxx anfängt, 
UART2 alles mit U2xxx usw.!

Damit man aber nicht alleine anhand des Pin-Diagramms alles durchsuchen 
muss, was ja auch nicht ganz leicht ist da einige Anschlüsse ja einige 
Mehrfachfunktionen haben, gibt es im Übersichtsdatenblatt 
(PIC32MX5XX/6XX/7XX Family Data Sheet)eine entsprechende Tabelle.
Die UARTs findest du dabei auf Seite 36. Für die 100Pin TQFP -wenn du 
das P32ESK hast ist ja ein 100TQFP da verbaut- ist dabei die zweite 
Spalte relevant.  ICh habe dir aber jetzt auch mal nur den für dich 
relevanten TEil ausgeschnitten und freigestellt angehanden.

Für dein konkretes Beispiel wird ja der UART1 verwendet. Relevant sind 
also die Anschlussfunktionen U1RX und U1TX. In der Tabelle erkennt man 
dann das dies die Anschlüsse Nummer 52 & 53 sind.

Da findet man dann auch die Info welches Modul in deinem vorher 
erwähnten Beispiel mit dem obskuren UART0 genutzt wurde.
Du sagtest du hast die RF4 & RF5 ermittelt, das sind die Anschlüsse 59 & 
50. Laut Liste UART2 zugeordnet.

(Nur als Hinweis am Rande: Genau genommen ist es nicht ganz korrekt wenn 
man sagt der UART nutzt RF x..., denn die normale Adressierbare IO 
Funktion ist nur eine von mehreren möglichen Funktionen. Der PIN kann 
also ENTWEDER RF x ODER UARTx sein... - Allerdings weiß wohl trotzdem 
jeder was gemeint ist ;-) und das geht schon in die Erbsenzählerei)

Ach Ja:
Definiert sind diese Bezeichnungen in den Headerdateien zum Prozessor - 
beispielsweise P32MX795F512L.H und dem Header zur Libfunktion, hier 
UART.h
Aber das kann man auch einfach als gegeben hinnehmen.

Gruß
Carsten

P.S.: Nur um darauf hinzuweisen: Dieses Demot nutzt die UART Funktionen, 
allerdings ist es weniger dazu gedacht als UART Beispiel zu dienen 
sondern soll in erster Linie als Referenz für DMA Transfer herhalten.

von Carsten S. (dg3ycs)


Angehängte Dateien:

Lesenswert?

EDIT:
Anhang vergessen !!!

von Klatec (Gast)


Lesenswert?

Hallo Carsten

Danke vorerst für deine ausführliche Antwort.
Nach dem du etwas von Seite 36 geschrieben hast, bin ich auf die Suche 
eines anderen Datenplattes gegeangen, denn ich habe meins von RS-Comp. 
Beim Microchip habe ich dann jenes gefunden wo die UART so bezeichnet 
sind wie du beschrieben hast. Ich habe den ext. Stecker auf einen 
Testprint gelötet und habe nur einige Anschlüsse zur Verfügung und unter 
diesen (angepasst auf das Beispiel davor) ist auch die U2. Wenn ich nun 
die U2 nehme sollte das ganze funktionieren.

Nachfolgend ein Teil des Codes vom vorigen Beispiel.

In der Variable 'int uartN' (wird der Funktion übergeben) ist eine 0 
gestanden und ich habe angenommen es handlet sich um die UART0, könnte 
es auch der Kanal DMAUART 0 sein?
Aber dann weiß ich nicht wie die UART Nr. zugewiesen wird.

***********************************************************************
DMAUART_RES DMAUARTConfigure( int uartN, DMAUART_CONF_RXTX enRxTx,
                              int bRate, int nBits, DMAUART_PARITY 
pType, DMAUART_STOP stopBits)
// configures vuart uartN
// enRxTx   - enables RX/TX
// bRate    - baud rate   (must be standard value)
// nBits    - number of bits (5-9 typ.)
// pType    - parity (if present, parity odd/even)
// stopBits - number of stop bits (1-2)
{
    uart_cfg *p = &u[uartN];

    // 1. disable the RX and TX before modifying parameters
    p->txon = 0;
    p->rxon = 0;

    // 2. init input/output masks
    p->imask=(1<<DMAUART_RX_PIN);
    p->omask=(1<<DMAUART_TX_PIN);

    // 3. init FIFO buffers
    p->ib=ibuffers[uartN];   p->ibr=p->ibw=0;  // initially empty
    p->ob=obuffers[uartN];   p->obr=p->obw=0;

    // 4. check and set the baudrate
    p->brate = DMAUART_TBASE/bRate;
    if (p->brate*bRate != DMAUART_TBASE)
    {
        return DMAUART_RES_BR_ERROR;          // error if not exact 
multiple
    }

    p->oskip = p->brate * DMAUART_OVS;

    // 5. check and set the total number of bits
    p->wsize=nBits;
    // count start+wsize+parity+stop
    p->nbits=1+nBits+(stopBits+1);
    if(pType != DMAUART_PARITY_NONE)
    {
        p->nbits += 1;
    }

    if ( p->nbits>16)
    {
        return DMAUART_RES_BITNO_ERROR;          // error too many bits
    }

    // 6. store parameters
    p->parity = (pType != DMAUART_PARITY_NONE);
    p->odd = (pType & DMAUART_PARITY_ODD) != 0;
    p->stop = stopBits;              // 0 = 1 STOP, 1 = 2 STOP

    // 7. clear all error flags
    p->p_error=0;           // parity
    p->f_error=0;           // framing
    p->o_error=0;           // overrun

    // 8. init RX state machine
    p->bitcount=0;
    p->majority=0;
    p->value=0;
    p->bitvalue=0;
    p->state=S_START;
    p->skip=1;

    // 9. init TX state machine
    p->tskip = 1;
    p->tbit = 1;            // start high
    p->tstate = T_IDLE;
    p->tgap=2;              // default gap between consecutive

    // 10. enable the RX and TX as requested
    p->txon = (enRxTx & DMAUART_CONF_TX_ENABLE) != 0;
  p->rxon = (enRxTx & DMAUART_CONF_RX_ENABLE) != 0;
  DMAUART_IP;
  mCNClearIntFlag();
  mCNOpen(CN_ON, CN_ENABLE(DMAUART_RX_CN), 0);
  ConfigIntCN(DMAUART_IPL | CHANGE_INT_ON);

    return DMAUART_RES_OK;
} // openDMAUART

von Klatec (Gast)


Lesenswert?

So jetzt habe ich vergessen was ich noch fragen wollte.
Und zwar sind im Library Guide z.B. nur UART1 und 2 angeführt, siehe 
Auszug unten. Was ist mit 3, 4, 5, 6? Wenn ich z.B U3 nehme kommt ein 
Fehler Build. bitte. Danke.

******
OpenUART1
OpenUART2
Description: This macro configures the UART module
Include: plib.h
Prototype: void OpenUART1(unsigned int config1,
unsigned int config2, unsigned int ubrg);
void OpenUART2(unsigned int config1,
unsigned int config2, unsigned int ubrg);
Arguments: config1
*******

von Carsten S. (dg3ycs)


Lesenswert?

Hallo Johann,

Klatec schrieb:
> In der Variable 'int uartN' (wird der Funktion übergeben) ist eine 0
> gestanden und ich habe angenommen es handlet sich um die UART0, könnte
> es auch der Kanal DMAUART 0 sein?
> Aber dann weiß ich nicht wie die UART Nr. zugewiesen wird.

Wo hast du das Beispiel genau her?
Ich kann mich Irren, aber vom Programmierstil sieht es für mich etwas 
anders aus als die gewohnten Microchip Beispiele.

ZUdem müsste ich mir das gesamte Programm ansehen. Wenn ich den von dir 
geposteten Codeabschnitt ansehe, dann wird in diesem Abschnitt m.E. gar 
keine DIREKTE Adressierung der Hardware vorgenommen.

Wenn ich das jetzt richtig deute scheint die Konfiguration der UART 
Schnittstelle in einem Array aus Strukturen abgelegt zu sein und diese 
Funktion dient zur Änderung der dort abgelegten Werte.

"uartN" ist dabei meiner Meinung nach nur ein INDEX der angibt welche 
Struktur aus dem Array nun angesprochen wird.
Und der Index beginnt ja immer bei NULL.

>     uart_cfg *p = &u[uartN];

Hier wird dann wohl der ZEiger auf die jeweilige Struktur erzeugt.
Und mit diesem Zeiger wird dann im folgenden auf die einzelnen Elemente 
der Struktur zugegriffen.
Beispielsweise mit:
>    p->txon = 0;
>    p->rxon = 0;

Die Zuordnung welche jeweilige Struktur(durch den Index adressiert) nun 
für welche UART Schnittstelle gilt wird dann wohl in der Funktion 
realisiert die dann die einzelnen Elemente wieder ausliest und zwecks 
Konfiguration Interpretiert. DAs kann völlig unabhängig von den 
Indexnummer sein. Aber im genaues dazu zu sagen müsste ich das gaze 
Programm sehen.
(Man könnte das natürlich auch passend machen, dann müsste nur die 
Nummer NULL unbelegt bleiben was bedeutet das etwas Speicher 
verschwendet wird da die zugehörige Struktur trotzdem angelegt werden 
muss)

Klatec schrieb:
> So jetzt habe ich vergessen was ich noch fragen wollte.
> Und zwar sind im Library Guide z.B. nur UART1 und 2 angeführt, siehe
> Auszug unten. Was ist mit 3, 4, 5, 6? Wenn ich z.B U3 nehme kommt ein
> Fehler Build.

Ich habe noch nie mehr als zwei UARTs beim PIC32 benutzt, daher kann ich 
jetzt auch nur vermuten.
Aber ich vermute das in der Lib einfach nur zwei UART Module vorgesehen 
sind. Wenn dies so ist, dann müsstest du für die Verwendung der höheren 
UART-Nummern die entsprechenden Routinen selbst bauen. Das ist aber auch 
keine HExerei.

Gruß
Carsten

von Klatec (Gast)


Lesenswert?

Danke Carsten.

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.