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);
}
}
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.
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
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
*******
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