Ich versuche, einen PIC24FJ64GB002 für die UART-Kommunikation in MBLAB mit XC16 einzurichten. Ich verwende die USB-CDC-Demo, um mit einem Gerät zu kommunizieren, und ich versuche, diese Informationen mit dem PIC an ein Arduino weiterzuleiten. Ich bin verwirrt, mit welcher Frequenz die CPU läuft. Ich verwende einen externen 8-MHz-Quarz, bei dem in der Demo mehrere Bits gesetzt sind. Hier werden Bits gesetzt, die den Oszillator betreffen.
#include <p24FJ64GB002.h>
#include "system.h"
#include "usb.h"
/** CONFIGURATION Bits **********************************************/
_CONFIG1(
WDTPS_PS1 &
FWPSA_PR32 &
WINDIS_OFF &
FWDTEN_OFF &
ICS_PGx1 &
GWRP_OFF &
GCP_OFF &
JTAGEN_OFF
)
_CONFIG2(
POSCMOD_HS &
I2C1SEL_PRI &
IOL1WAY_OFF &
OSCIOFNC_ON &
FCKSM_CSDCMD &
FNOSC_PRIPLL &
PLL96MHZ_ON &
PLLDIV_DIV2 &
IESO_OFF
)
_CONFIG3(
WPFP_WPFP0 &
SOSCSEL_SOSC &
WUTSEL_LEG &
WPDIS_WPDIS &
WPCFG_WPCFGDIS &
WPEND_WPENDMEM
)
_CONFIG4(
DSWDTPS_DSWDTPS3 &
DSWDTOSC_LPRC &
RTCOSC_SOSC &
DSBOREN_OFF &
DSWDTEN_OFF
)
/*********************************************************************
* Function: void SYSTEM_Initialize( SYSTEM_STATE state )
*
* Overview: Initializes the system.
*
* PreCondition: None
*
* Input: SYSTEM_STATE - the state to initialize the system into
*
* Output: None
*
********************************************************************/
void SYSTEM_Initialize( SYSTEM_STATE state )
{
//On the PIC24FJ64GB004 Family of USB microcontrollers, the PLL will not power up and be enabled
//by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
//This allows the device to power up at a lower initial operating frequency, which can be
//advantageous when powered from a source which is not gauranteed to be adequate for 32MHz
//operation. On these devices, user firmware needs to manually set the CLKDIV<PLLEN> bit to
//power up the PLL.
{
unsigned int pll_startup_counter = 600;
CLKDIVbits.PLLEN = 1;
while(pll_startup_counter--);
}
switch(state)
{
case SYSTEM_STATE_USB_HOST:
PRINT_SetConfiguration(PRINT_CONFIGURATION_LCD);
break;
case SYSTEM_STATE_USB_HOST_CDC_BASIC:
BUTTON_Enable(BUTTON_USB_HOST_CDC_BASIC);
PRINT_SetConfiguration(PRINT_CONFIGURATION_LCD);
break;
}
}
Ich verwende dann diese Funktion, um den UART zu initialisieren
void UART_INIT()
{
AD1PCFGL = 0xFFFF;
__builtin_write_OSCCONL(OSCCON & 0xbf);
TRISBbits.TRISB15 = 0;
__builtin_write_OSCCONL(OSCCON | 0x40);
RPOR7bits.RP15R = 3;
U1BRG = 103; //set baud speed
U1MODE = 0x8000; //turn on module
U1STA = 0x8400; //set interrupts
IEC0bits.U1TXIE = 0;
IFS0bits.U1RXIF = 0;
IFS0bits.U1TXIF = 0;
}
Und diese Funktion, um ein Byte zu übertragen
void send(char c)
{
while(U1STAbits.UTXBF == 1);
U1TXREG = c;
}
Ich versuche herauszufinden, welcher Wert FCY definiert werden sollte. Ich nahm an, dass es 16 MHz (96 MHz / 3) / 2 sein würde, aber der Code funktionierte bei dieser Einstellung nicht. Könnte es ein anderes Problem im Code geben?
Ich mache alle Pins digital und setze den UART-Pin als Eingang mit diesem Code
__builtin_write_OSCCONL(OSCCON & 0xbf);
AD1PCFGL = 0xFFFF;
TRISBbits.TRISB15 = 0;
UART_INIT(9600);
__builtin_write_OSCCONL(OSCCON | 0x40);
Schließlich verwende ich die Funktionen wie folgt
UART_INIT(9600);
while(1)
{
send('H');
send('e');
send('l');
send('l');
send('o');
send(' ');
send('W');
send('o');
send('r');
send('l');
send('d');
send('\n');
}
Ein Diagramm würde helfen, zu vermitteln, was Sie tun. Ich denke, das ist, was Sie implementiert haben:
"ein Gerät" (USB-Gerät) <-> USB <-> PIC24FJ64BG002 (USB-Host) <-> UART <-> Arduino
Werfen wir einen Blick auf die Uhroptionen für diesen Teil:
Schauen wir uns auch die USB-spezifischen Uhrensachen genauer an:
CONFIG2 enthält Ihr oszillatorbezogenes Zeug:
_CONFIG2(
POSCMOD_HS &
I2C1SEL_PRI &
IOL1WAY_OFF &
OSCIOFNC_ON &
FCKSM_CSDCMD &
FNOSC_PRIPLL &
PLL96MHZ_ON &
PLLDIV_DIV2 &
IESO_OFF
)
Fassen wir zusammen, was wir wissen:
Auch aus dem Datenblatt:
Also, was ist unser Fazit? Ich würde sagen, dass die Situation wie in Abbildung 8.2 gezeigt ist, wenn nicht irgendwo anderer Code mit den Bits herumspielt - HSPLL läuft mit 32 MHz (96 MHz USB-PLL-Ausgang, geteilt durch drei, dann geteilt durch eins).
Und weil wir das wissen
die Antwort sollte 16 MHz sein.
Nun zu Ihrer Baudratenformel:
baud = (FCY/(16*baud))-1;
(Es ist eine schlechte Praxis, denselben Variablennamen auf beiden Seiten der Gleichung zu haben: Die linke Seite sollte in BRG oder etwas Ähnliches umbenannt werden - es ist der Baudratengeneratorwert, nicht die Baudrate selbst.)
Wenn Sie das Referenzhandbuch der PIC24-Familie für UART nachschlagen, finden Sie die für Sie vorberechneten Werte:
Standardmäßig ist BRGH null, also sollte Ihr Baudratengenerator auf 103 dezimal eingestellt sein, es sei denn, der Code mischt sich damit ein. (Ihre Formel ist für BRGH - 0 und stimmt mit einer Taktrate von 16 MHz mit dieser Tabelle überein.)
Ich würde eine Vermutung wagen und sagen, dass Ihre UART-Probleme, wenn sie bestehen bleiben, nicht mit der Uhr zusammenhängen ...
Im PIC24-Kern ist FCY die Hälfte der Oszillatorfrequenz. Mit externem 8-MHz-Quarz multipliziert mit 4 (PLL), geteilt durch 2 (PLLDIV) und dann noch einmal durch 2 geteilt (erster Satz) ergibt 8 MHz. Der Oszillator ist auch am REFO-Pin verfügbar, Sie können ihn aktivieren und die Frequenz direkt mit einem Zähler, Oszilloskop oder einem Logikanalysator messen.
Andere Antworten haben die Konfigurationseinstellungen ausführlich erklärt, mein Fokus liegt auf dem Code, den Sie für verwenden UART Communication
. Microchip bietet periphere Bibliotheksfunktionen, die Sie direkt in Ihrem Programm verwenden können, anstatt Werte in Register zu schreiben. Gehen Sie zu, c\Program Files\Microchip\(your compiler)\docs
dort finden Sie viele Dokumentationen oder suchen Sie nach PIC18/PIC24/PIC32 peripheral library
. Ich habe nicht in PIC24 gearbeitet, aber die Funktionen sind für alle MCU-Serien wie PIC18
PIC24
PIC32
. Zum Beispiel für UART:
OpenUART(): to initialize UART channel.
putsUART(): to send string to your UART
getsUART(): to receive string from UART
putcUART(): to send a char.
getcUART(): to receive a char
Sie können diese Funktionen direkt nutzen und sparen Zeit.!
Demo-Code:
/*
*
*/
int main()
{
/*
*
*/
OpenUART1( UART_EN | UART_NO_PAR_8BIT | UART_1STOPBIT, UART_RX_ENABLE | UART_TX_ENABLE, (FPB/16/BAUDRATE)-1 );
while(1)
{
putsUART1("Hello World");
}
}
plib.h
Wenn Sie sich nicht sicher sind, ob Ihre Uhr perfekt funktioniert, schalten Sie einfach einen Pin mit __delay_us(x) um und sehen Sie, ob die Ausgangswellenform auf dem Oszilloskop richtig ist.
und in Bezug auf die Baudrate hat die Gleichung einen einzigen Fehler (Compiler-Dummheit), versuchen Sie Folgendes: baud = (FCY/(16.0*baud))-1 . Wenn Sie ".0" zu 16 hinzufügen, erzwingen Sie eine Float-Division , da der Compiler manchmal Optimierungen vornimmt und das Ergebnis nicht korrekt ist, wenn Integer verwendet wird. Ich hatte vorher genau das gleiche Problem und das hat es gelöst.
Ich hoffe, das hilft
Dinge zum Ausprobieren:
Der Code sollte so aussehen, etwas anders angeordnet:
void UART_INIT()
{
__builtin_write_OSCCONL(OSCCON & 0xbf);
RPOR7bits.RP15R = 3; // connect uart1 tx to RP15
//AD1PCFGL = 0xFFFF; //try the code with and without this line
__builtin_write_OSCCONL(OSCCON | 0x40);
U1BRG = 103; //set baud value for 9600 (verify)
IEC0bits.U1TXIE = 0; //just in case
IEC0bits.U1RXIE = 0;
U1MODE = 0x8000; //turn on module
U1STA = 0x0400; // enable TX
IFS0bits.U1TXIF = 0;
IFS0bits.U1RXIF = 0;
}
void send(char c)
{
while(U1STAbits.UTXBF);
U1TXREG = c;
}
void uart_print(const char * str){
while (*str)
send(*str++);
}
void main(){
//initialize clock and other stuff here
UART_INIT();
//add a delay of 20ms here, just in case
while(1)
uart_print("Hello world\n");
}
brhans
Markovian8261
brhans
Markovian8261