Ich habe einen 30-MHz-Quarzoszillator, um einen PIC24FJ128GC010-Controller zu takten. Ich programmiere in MPLAB X. Meine Idee ist es, einen Impuls auf einem der E / A-Pins zu erzeugen, die umschalten. Aber das kann ich leider nicht. Anfangs benutzte ich einen 8-MHz-Quarz. Ich habe die Konfigurationswort-Einstellungen sowie die Steuerregister-Anpassungen vorgenommen. Die Baudrate habe ich auch geändert.
Bitte schlagen Sie die Möglichkeiten in diesem Fall vor.
*****************************************************************************************
CONFIG WORDS
*****************************************************************************************
POSCMD = HS // Primary Oscillator Select (HS Oscillator Enabled)
OSCIOFCN = OFF // OSCO Pin Configuration (OSCO/CLKO/RC15 functions as CLKO (FOSC/2))//
FCKSM = CSDCMD // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Disabled)
FNOSC = PRI // Initial Oscillator Select (Primary Oscillator (XT, HS, EC))
IESO = OFF // Internal External Switchover (Disabled)
*****************************************************************************************
#include "timer.h"
unsigned millisCount = 0;
void __attribute__ ((interrupt, no_auto_psv)) _T2Interrupt(void)
{
IFS0bits.T2IF = 0;
millisCount++;
}
/*******************************************************************************
* Returns the number of milliseconds since the device was started as an
* unsigned long.
******************************************************************************/
unsigned long Millis()
{
return millisCount;
}
void ResetMillis(void)
{
millisCount = 0u;
}
void Delay(unsigned long delayTime)
{
volatile int delayStart = Millis();
while (Millis() - delayStart < delayTime);
}
****************************************************************************************
INITIALISATION CODE
****************************************************************************************
void Osc_Config(void)
{
OSCTUN = 0;
CLKDIV = 0;
OSCCON = 0;
OSCCONbits.COSC = 2;
OSCCONbits.NOSC = 2;
OSCCONbits.OSWEN = 1;
while(OSCCONbits.OSWEN);
}
void Timer2_Config(void)
{
T2CON = 0;
TMR2 = 0x0000; //Turn off Timer2
PR2 = 0xFFFF; //Period register at maximum
_T2IF = 0; //clear Timer2 interupt flag
_T2IE = 1; //Enable Time2 interupt
//T2CON
T2CONbits.T32 = 0; //Timer2 and T3 or T4 and T5 act as two 16-bit timers
T2CONbits.TCKPS = 0; //Timer Prescale 1:1
T2CONbits.TGATE = 0; //Gated time accumulation is disabled
T2CONbits.TSIDL = 0; //Continues module operation in Idle mode
T2CONbits.TCS = 0; //Internal clock (FOSC/2)
T2CONbits.TON = 1; //Starts Timer2
}
void Io_Config(void)
{
****//Start pulse pin**
PULSE_PIN = 0;
TRISBbits.TRISB2 = 0; //set as output pin**
//Stop pulse pin
TRISBbits.TRISB15 = 1; //set as input pin
TRISCbits.TRISC1 = 1; //set as input pin for current
TRISBbits.TRISB13 = 1; //set as input pin
//Trip point pin
TRISBbits.TRISB5 = 0; //set as output pin
// Configure start and stop pulse as digital
ANSBbits.ANSB2 = 0; //set as digital
ANSBbits.ANSB15 = 0; // set as digital
ANSCbits.ANSC1 = 1; // set to analog
ANSBbits.ANSB13 = 0; // set to digital
ANSBbits.ANSB12 = 0; //Set to Digital to check the frequency of the Oscillator
//reference clock output
ANSBbits.ANSB15 = 0; //seta s digital
TRISBbits.TRISB15 = 0; //SSet as output
} <-- NOTE: was missing trailing brace here.
void Adc_Config(void)
{
PMD1bits.ADC1MD = 0; //Clear PMD bit to allow ADC operation
//ADCON1
ADCON1bits.ADSIDL = 0;
ADCON1bits.ADSLP = 0;
ADCON1bits.FORM = 0;
ADCON1bits.PUMPEN = 0;
ADCON1bits.ADCAL = 0;
ADCON1bits.PWRLVL = 1;
//ADCON2
ADCON2bits.PVCFG = 0;
ADCON2bits.NVCFG0 = 0;
ADCON2bits.BUFORG = 1;
//ADCON3
ADCON3bits.ADRC = 0;
ADCON3bits.ADCS = 0;
ADCON3bits.SLEN0 = 1u; //FKo
ADCON1bits.ADON = 1;
while(ADSTATHbits.ADREADY == 0); // Wait for ready flag set.
//Make sure ADC sample lists and Accumulator feature are in known states
ACCONH = 0x0000; //Disable accumulation for the moment
ACRES = 0x00000000; //Clear previous accumulation count
ADL0CONLbits.SLSIZE = 1-1; //Sample list length for 1 channel
//Configure Sample List 0 settings
ADL0CONHbits.ASEN = 0;
ADL0CONHbits.SLINT = 1;
ADL0CONHbits.WM = 0;
ADL0CONHbits.CM = 0;
ADL0CONHbits.SAMC = 1;
ADL0CONLbits.SLTSRC = 0;
ADTBL0bits.ADCH = 8; // channel 0 selected
ADL0PTR = 0; // Point to start of sample list 0
#if (__TEST_FREQUENCY_SETUP__)
ADL0CONLbits.SAMP = 1;
Nop();Nop();
ADL0CONLbits.SAMP = 0;
while(!IFS0bits.AD1IF && !ADSTATLbits.SL0IF) { ; }
IFS0bits.AD1IF = 0u;
ADSTATLbits.SL0IF = 0u;
{
unsigned long res = ADRES0;
res = 15u;
}
#endif <-- NOTE: was missing.
} <-- NOTE: missing.
void Uart_Config(void)
{
RPOR1bits.RP2R = 3; //Assign UART1 transmit to RP3 Peripheral
RPOR1bits.RP3R = 4;
RPINR18bits.U1RXR = 0; //Assign UART1 RXD to RP0 Peripheral
RPINR18bits.U1CTSR = 1;
U1BRG = 50;//12;
U1STA = 0;
U1MODE = 0x8000;
U1STAbits.UTXEN = 1;
}
**#define UART_BUFFER_SIZE 128
void UARTInit(void)
{
//U1BRG = 312; //9600 baudrate @ 24MHz osc
U1BRG = 24; //19200 baudrate @ 10 MHz osc
U1MODE = 0;
U1MODEbits.BRGH = 1;
U1STA = 0;
U1STAbits.URXISEL = 0;
U1MODEbits.UARTEN = 1;
U1STAbits.UTXEN = 1;
IFS0bits.U1RXIF = 0;
}
void UARTPutChar(uint8_t ch)
{
while(U1STAbits.TRMT == 0);
Nop(); Nop();Nop(); Nop();
Nop(); Nop();Nop(); Nop();
U1TXREG = ch;
}
void UARTPutInt(int32_t data)
{
int j;
char string[UART_BUFFER_SIZE];
sprintf(string, "%ld", data);
j = 0;
while(string[j] != 0)
{
UARTPutChar(string[j]);
j++;
if(j >= UART_BUFFER_SIZE)
{
break;
}
}
}
void UARTPutString(char* string)
{
while(*string != 0)
{
UARTPutChar(*string);
string++;
}
}
void UARTPutDouble(double data)
{
int j;
char string[UART_BUFFER_SIZE];
sprintf(string, "%9.3f", data);
j = 0;
while(string[j] != 0)
{
UARTPutChar(string[j]);
j++;
if(j >= UART_BUFFER_SIZE)
{
break;
}
}
}
char UARTWaitChar(void)
{
while(IFS0bits.U1RXIF == 0);
IFS0bits.U1RXIF = 0;
return U1RXREG;
}
char UARTGetChar(void)
{
if(IFS0bits.U1RXIF == 0)
{
return 0;
}
U1STAbits.OERR = 0;
IFS0bits.U1RXIF = 0;
return U1RXREG;
}
*************************************************************************************
MAIN CODE
*************************************************************************************
// PIC24FJ128GC010 Configuration Bit Settings
#define STARTUP_DELAY (5) //Time spent waiting after device start up
#define ZERO_SET_TIME (5) //Time spent setting the zero level
#define COUNT 5
#define DELAY for(i=0;i<COUNT;i++)
int dispOffset = 0;
void SetDutyCycle(int nDC); //Set duty cycle for trip point
int PulseMeasure(void); //Single pulse measurement
int LevelMeasure(int, int); //Averaged return of multiple measurements
int adctemp;
void TestMeas(void); //Test routine to scan through PWM values
double StdDev(int, double, double, double);//Get sigma for measurements
int i;
/*******************************************************************************
* Main
******************************************************************************/
int main(void)
{
//Configure all of the devices
while (Millis() < STARTUP_DELAY); //Wait for settling...
//Wait for sensor to be plugged in
**while(LevelMeasure(CTMU_BUFFER_POWER, OVER_SAMPLE) < 0);**
#if (__TEST_FREQUENCY_SETUP__)
while(Millis() < 10) { ; }
ResetMillis();
LATBbits.LATB2 = 1;
while(Millis() < 10) { ; }
ResetMillis();
LATBbits.LATB2 = 0;
#endif
} <-- NOTE: missing brace.
int PulseMeasure(void)
{
volatile unsigned int Vread;
double Vtot = 0;
int j;
//ADL0CONLbits.SAMP = 1; //Sample
PULSE_PIN = 0;
CTMUCON2 = CTMUCON2 & 0xFCFF;
CTMUCON1bits.IDISSEN = 1; //discharge cap
Delay(20);
CTMUCON1bits.IDISSEN = 0; //Release cap from discharge
ADL0CONLbits.SLEN = 1;
ADL0CONLbits.SAMP = 1;
for(j=0;j<10;j++)
{
Nop();Nop();Nop();Nop();
Nop();Nop();Nop();Nop();
Delay(1);
CTMUCON2 = CTMUCON2 & 0xFCFF;
PULSE_PIN = 1;
PULSE_PIN = 0;
while(!CTMUCON2bits.EDG1STAT);
while(ADSTATHbits.ADBUSY);//{;}
Nop(); Nop();
IFS0bits.AD1IF = 0;
ADSTATLbits.SL0IF = 0;
ADL0CONLbits.SAMP = 0; //Conversion
while (!ADSTATLbits.SL0IF);
Vread = ADRES0;
IFS0bits.AD1IF = 0;
ADSTATLbits.SL0IF = 0;
ADL0CONLbits.SAMP = 1;
UARTPutString("#gy;1;");
UARTPutInt(Vread);
UARTPutString("\r\n");
}
return (Vread);
}
PULSE_PIN ist die Funktion für die Impulserzeugung. Entschuldigen Sie den langen Code und die Anzahl der Bearbeitungen. Aber ich verstehe wirklich nicht, warum das Programm auch auf 8MHz läuft und nicht auf 30MHz! Und ja; Es ist wirklich ein 30-MHz-Quarzoszillator.
BITTE HILF MIR!!! Ich bin neu in der Programmierung, aber ich muss mit diesem Code arbeiten, um ihn für weitere Arbeiten mit 30/2 = 16 MHz auszuführen.
Ich habe Ihren Code auf das absolute Minimum reduziert, das zum Testen des Systemtakt- und Timerbetriebs erforderlich ist, und ihn auf einem PIC24FJ64GA104 ausgeführt (dessen grundlegender Takt- und Timerbetrieb Ihrem PIC ähnelt). Alles funktionierte korrekt, auch bei Verwendung eines externen Oszillatormoduls anstelle eines Quarzes ( sollte in diesem Fall POSCMD
auf eingestellt werden ).EC
Ich habe ein paar Dinge geändert, die dazu führen könnten, dass Ihr Frequenztest nicht richtig funktioniert:-
Deaktiviert den Watchdog-Timer (er ist standardmäßig aktiviert, was dazu führt, dass die MCU wiederholt zurückgesetzt wird, wenn sie nicht regelmäßig zurückgesetzt wird).
Der Frequenztestcode wurde in eine while(1)
Schleife eingeschlossen, damit er kontinuierlich ausgeführt wird, anstatt main()
nach einer Iteration beendet zu werden.
Versuchen Sie meinen Code auf Ihrem PIC. Wenn es nicht funktioniert, liegt möglicherweise ein Hardwareproblem vor (Oszillator startet nicht, unzureichende Umgehung der Stromversorgung, falsche Verkabelung usw.).
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <xc.h> // automatically includes MCU selected in project
#pragma config POSCMOD = HS // Primary Oscillator Select (HS = crystal, EC = external clock input)
#pragma config OSCIOFNC = OFF // OSCO Pin Configuration (OSCO/CLKO/RC15 functions as CLKO (FOSC/2))
#pragma config FCKSM = CSDCMD // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Disabled)
#pragma config FNOSC = PRI // Initial Oscillator Select (Primary Oscillator (XT, HS, EC))
#pragma config IESO = OFF // Internal External Switchover (Disabled)
#pragma config FWDTEN = OFF // watchdog timer (off)
//******************************************************************************
#include "timer.h"
unsigned millisCount = 0;
void __attribute__ ((interrupt, no_auto_psv)) _T2Interrupt(void)
{
IFS0bits.T2IF = 0;
millisCount++;
}
/*******************************************************************************
* Returns the number of milliseconds since the device was started as an
* unsigned long.
******************************************************************************/
unsigned long Millis()
{
return millisCount;
}
void ResetMillis(void)
{
millisCount = 0u;
}
void Delay(unsigned long delayTime)
{
volatile int delayStart = Millis();
while (Millis() - delayStart < delayTime);
}
//******************************************************************************
// INITIALISATION CODE
//******************************************************************************
void Timer2_Config(void)
{
T2CON = 0;
TMR2 = 0x0000; //Turn off Timer2
PR2 = 0xFFFF; //Period register at maximum
_T2IF = 0; //clear Timer2 interupt flag
_T2IE = 1; //Enable Time2 interupt
//T2CON
T2CONbits.T32 = 0; //Timer2 and T3 or T4 and T5 act as two 16-bit timers
T2CONbits.TCKPS = 0; //Timer Prescale 1:1
T2CONbits.TGATE = 0; //Gated time accumulation is disabled
T2CONbits.TSIDL = 0; //Continues module operation in Idle mode
T2CONbits.TCS = 0; //Internal clock (FOSC/2)
T2CONbits.TON = 1; //Starts Timer2
}
#define PULSE_PIN LATBbits.LATB2
void Io_Config(void)
{
// pulse pin
PULSE_PIN = 0;
TRISBbits.TRISB2 = 0; //set as output
}
//******************************************************************************
//MAIN CODE
//******************************************************************************
#define STARTUP_DELAY (5) //Time spent waiting after device start up
int main(void)
{
//Configure all of the devices
Io_Config();
Timer2_Config();
while (Millis() < STARTUP_DELAY){}; //Wait for settling...
while (1)
{
while(Millis() < 10) { ; }
ResetMillis();
LATBbits.LATB2 = 1;
while(Millis() < 10) { ; }
ResetMillis();
LATBbits.LATB2 = 0;
}
return 0;
}
http://ww1.microchip.com/downloads/en/DeviceDoc/39726a.pdf (ziemlich umfangreiches Dokument) zeigt in Abschnitt 35.8, dass die maximale Frequenz für einen Quarzoszillator 25 MHz beträgt. Wenn Sie eine höhere Frequenz benötigen, benötigen Sie einen Quarz mit niedrigerer Frequenz und die interne PLL, um diese zu erzeugen.
Es kann auch eine externe Taktquelle von bis zu 32 MHz aufnehmen, aber das ist nicht dasselbe wie ein Quarz.
Bruce Abbott
Bob
Adam Lawrence
0x6d64
Bruce Abbott
Scott Seidmann