LusoRobótica - Robótica em Português

Sistemas específicos => PIC => Tópico iniciado por: Sérgio_Sena em 06 de Março de 2011, 00:35

Título: [PIC24] Rotinas de inicialização e Configuração
Enviado por: Sérgio_Sena em 06 de Março de 2011, 00:35
Sei que, por vezes, a iniciação num processador novo ou numa série mais avançada, pode acarretar algumas dores de cabeça ou "medo".

Arranjei um tempinho para copy-paste de um micro-programa de configuração inicial de um PIC24, facilmente adaptavel a qualquer micro desta série.
Está escrito em MPLAB C.

Um aviso: não foram usadas quaisquer bibliotecas para configuração das entranhas do PIC.
A configuração é feita registo a registo, "manualmente". Desta forma podem aprender o que realmente se está a fazer ao PIC.

Espero que seja de utilidade!



Código: [Seleccione]
#include <p24HJ64GP202.h>
#define FCY 5529600UL //frequencia para os DELAYs (cristal usado de 11.0592MHz)


/***********************************************************************************************
PIC24 Configuration Fuses
***********************************************************************************************/

_FOSCSEL(FNOSC_PRI & IESO_OFF); // Primary oscillator (XT, HS, EC)
_FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_HS); //(Clock switching and clock monitor both Disabled) & (Single configuration for remappable I/O Disabled) & (OSC2 is clock O/P) & (HS oscillator)

_FWDT(FWDTEN_OFF); // Watchdog Timer Disabled
// (LPRC can be disabled by clearing SWDTEN bit in RCON register

_FPOR(ALTI2C_OFF & FPWRT_PWR64); //(I2C mapped to SDA1/SCL1) & (Power-on Reset Value 64ms)

_FICD(JTAGEN_OFF & ICS_PGD1); //(JTAG is disabled) & (ICD communication channel)

//_FUID0() //User Unit ID Byte 0
//_FUID1() //User Unit ID Byte 1
//_FUID2() //User Unit ID Byte 2
//_FUID3() //User Unit ID Byte 3











//declaraçoes das interrupçoes
//void __attribute__((__interrupt__)) _INT0Interrupt(void); /*Declare external interrupt ISRs*/
//void __attribute__((__interrupt__)) _INT1Interrupt(void);
//void __attribute__((__interrupt__)) _INT2Interrupt(void);
//void __attribute__((__interrupt__)) _INT3Interrupt(void);
//void __attribute__((__interrupt__)) _INT4Interrupt(void);
void __attribute__((__interrupt__)) _U1RXInterrupt(void);
void __attribute__((__interrupt__)) _U1TXInterrupt(void);
void __attribute__((__interrupt__)) _T2Interrupt(void); //declaracao de interrupcao de TMR2








/***********************************************************************************************
TMR2 interrupt routine
***********************************************************************************************/

void __attribute__((__interrupt__)) _T2Interrupt(void)
{
IFS0bits.T2IF = 0; //limpa a flag de interrupcao de TMR2 = 0;

LATBbits.LATB6 ^= 1; //DEBUG, faz oscilacao no pino RB6

if (bTimeoutOn) //se houver autorizacao para contagem do TIMEOUT, fa-la
wTimeout--;

}



/***********************************************************************************************
USART1-RX interrupt routine
***********************************************************************************************/

void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
BYTE byData;
BOOL dummy;

if (IFS0bits.U1RXIF) //verifica se é a interrupçao certa
{
IFS0bits.U1RXIF = 0; //limpa a interrupcao de USART-RX

dummy = U1STAbits.FERR; //limpa registo de erros
dummy = U1STAbits.PERR;

byData = U1RXREG; //tira do SFR de chegada
}
}


/***********************************************************************************************
USART1-TX interrupt routine
***********************************************************************************************/

void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
if (IFS0bits.U1TXIF) //verifica se é a interrupçao certa
{
IFS0bits.U1TXIF = 0; //limpa a interrupcao de USART-TX

U1TXREG = texBufArray[0]; //envia Byte
}
}










/***********************************************************************************************
microController Init routine
***********************************************************************************************/

void init_uC(void)
{
//configuraçao do OSCILADOR
OSCCONbits.CLKLOCK = 1; //Clock switching is disabled, system clock source is locked
OSCCONbits.IOLOCK = 0; //Peripheral Pin Select is not locked. Writes to Peripheral Pin Select registers are allowed
OSCCONbits.LPOSCEN = 0; //Disable secondary oscillator
OSCCONbits.OSWEN = 0; //Oscillator Switch Enable bit -> Oscillator switch is complete
CLKDIVbits.ROI = 0; //Recover on Interrupt bit - Interrupts have no effect on the DOZEN bit
CLKDIVbits.PLLPOST = 0; //PLL VCO Output Divider -> Output divided by 2
// CLKDIVbits.DOZE = 8; //Processor Clock Reduction Select bits (8=default)
CLKDIVbits.DOZEN = 0; //Processor clock and peripheral clock ratio forced to 1:1
// CLKDIVbits.PLLPOST = 4; //PLL VCO Output Divider Select bits 4=default
CLKDIVbits.PLLPRE = 0; //Clock Divisor Register - 00000 = Input divided by 2 (default)
// PLLFBD = 30; //PLL Feedback Divisor bits (000110000 = 50 (default))
// OSCTUNbits.TUN = 0; //FRC Oscillator Tuning bits - 000000 = Center frequency (7.37 MHz nominal)

// RCONbits.SWDTEN=0; // disable watchdog timer

/* AD1CON1 = 0x0000; //Analogue is OFF
AD1CON2 = 0x0000;
AD1CON3 = 0x0000;
AD1CON4 = 0x0000;
AD1CHS123 = 0x0000;
AD1CHS0 = 0x0000;
AD1CSSL = 0x0000; */
AD1PCFGL = 0xFFFF; // Analogue/Digital :: all digital

RPINR0 = 0xFFFF; //External Interrupt 1 (INTR1)
RPINR1 = 0xFFFF; //External Interrupt 2 (INTR2) ::
RPINR3 = 0xFFFF; //Timer3 External Clock (T3CK) & Timer2 External Clock (T2CK)
RPINR4 = 0xFFFF; //Timer5 External Clock (T3CK) & Timer4 External Clock (T2CK)
RPINR7 = 0xFFFF; //Input Capture 2 (IC2) & Input Capture 1 (IC1)
RPINR10 = 0xFFFF; //Input Capture 8 (IC8) & Input Capture 7 (IC7)
RPINR11 = 0xFFFF; //Output Capture A (OCFA)
RPINR18 = 0xFF0B; //UART1 Clear to Send (U1CTS) & UART1 Receive (U1RX) :: ... & PLCTXOUT (USART1)
RPINR19 = 0xFF0C; //UART2 Clear to Send (U1CTS) & UART2 Receive (U1RX) :: ... & GPRS (invertido no WISMO)
RPINR20 = 0xFFFF; //SPI1 Clock Input (SCK1IN) & SPI1 Data Input (SDI1)
RPINR21 = 0xFFFF; //SPI1 Slave Select Input (SS1IN)
RPINR22 = 0xFFFF; //SPI2 Clock Input (SCK2) & SPI2 Data Input (SDI2)
RPINR23 = 0xFFFF; //SPI2 Slave Select Input (SS2)
// RPINR26 = 0xFFFF; //ECAN1 Receive (C1RX) PIC24HJxxGP8xx ONLY

RPOR0 = 0xFFFF; //RP1 Output Pin & RP0 Output Pin
RPOR1 = 0xFFFF; //RP3 Output Pin & RP2 Output Pin
RPOR2 = 0xFFFF; //RP5 Output Pin & RP4 Output Pin
RPOR3 = 0xFF00; //RP7 Output Pin & RP6 Output Pin, RP6=IO0
RPOR4 = 0xFFFF; //RP9 Output Pin & RP8 Output Pin
RPOR5 = 0xFF03; //RP11 Output Pin & RP10 Output Pin :: ... & PLCRXIN (USART1)
RPOR6 = 0x05FF; //RP13 Output Pin & RP12 Output Pin :: TXOPTO (USART2) & ...  (invertido no WISMO)
RPOR7 = 0xFFFF; //RP15 Output Pin & RP14 Output Pin
// RPOR8 = 0xFFFF; //RP17 Output Pin & RP16 Output Pin 44pins only
// RPOR9 = 0xFFFF; //RP19 Output Pin & RP18 Output Pin
// RPOR10 = 0xFFFF; //RP21 Output Pin & RP20 Output Pin
// RPOR11 = 0xFFFF; //RP23 Output Pin & RP22 Output Pin
// RPOR12 = 0xFFFF; //RP25 Output Pin & RP24 Output Pin

TRISA = 0b0000000000001100; // RA2=OSC1 & RA3=OSC2
TRISB = 0b0101010000000000; // RB10=RXOPTO & RB13=PLCRXIN & RB14=SYSMON & RB2=EXT_RESET
// ODCA = 0x00; //Open-Drain Outputs
// ODCB = 0x00;
// LATB = 0xFF; //
// LATA = 0xFF;


// CNPU1 = 0x0000; //Input Change Notification Pull-up Enable Register :: DISABLED
// CNPU2 = 0x0000;
// CNEN1 = 0x0000; //Input Change Notification Interrupt Enable Register :: DISABLED
// CNEN2 = 0x0000;
CNPU1bits.CN13PUE = 1; //activa pull-up RB13



// OC1CON = 0; //OCxCON: Output Compare x Control Register
// OC2CON = 0;


// U1MODE = 0b1000000000000000; //15=UART1 ON, 13=continue operation, 4=U1RX IDLE STATE is 1, Low Speed,2-0=8N1
// U1STA = 0b0000000000000000; //14=U1TX IDLE STATE is 1
// U2MODE = 0b1000000000000000; //15=UART1 ON, 13=continue operation, 4=U1RX IDLE STATE is 1, Low Speed,2-0=8N1
// U2STA = 0b0000000000000000; //14=U1TX IDLE STATE is 1



//configuraçao da USART-1
U1MODEbits.UARTEN = 1; //UARTx is enabled; all UARTx pins are controlled by UARTx as defined by UEN<1:0>
U1MODEbits.USIDL = 0; //Continue module operation in Idle mode
U1MODEbits.IREN = 0; //IrDA encoder and decoder disabled
U1MODEbits.RTSMD = 0; //UxRTS pin in Flow Control mode
U1MODEbits.UEN = 0; //UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/BCLK pins controlled by port latches
U1MODEbits.WAKE = 0; //No wake-up enabled
U1MODEbits.LPBACK = 0; //Loopback mode is disabled
U1MODEbits.ABAUD = 0; //Baud rate measurement disabled or completed
U1MODEbits.URXINV = 0; //UxRX Idle state is ‘1’
U1MODEbits.BRGH = 0; //1 = BRG generates 4 clocks per bit period (4x baud clock, High-Speed mode) - 0 = BRG generates 16 clocks per bit period (16x baud clock, Standard mode)
U1MODEbits.PDSEL = 0; //8-bit data, no parity
U1MODEbits.STSEL = 0; //One Stop bit
// U1STAbits.UTXISEL = 0; //Interrupt when a character is transferred to the Transmit Shift Register (this implies there is at least one character open in the transmit buffer)
U1STAbits.UTXISEL0 = 0; //Interrupt when a character is transferred to the Transmit Shift Register (this implies there is at least one character open in the transmit buffer)
U1STAbits.UTXISEL1 = 0; //Interrupt when a character is transferred to the Transmit Shift Register (this implies there is at least one character open in the transmit buffer)
U1STAbits.UTXINV = 0; //UxTX Idle state is ‘1’
U1STAbits.UTXBRK = 0; //Sync Break transmission disabled or completed
U1STAbits.UTXEN = 1; //Transmit enabled, UxTX pin controlled by UARTx
U1STAbits.URXISEL = 0; //Interrupt is set when any character is received and transferred from the UxRSR to the receive buffer. Receive buffer has one or more characters
U1STAbits.ADDEN = 0; //Address Detect mode disabled
U1BRG = 8; //UxBRG = ((FCY / Desired Baud Rate) / 16) - 1 (38k4bps com o cristal 11.0592MHz)

//configuracao das interrupcoes USART
IFS0bits.U1TXIF = 0; //limpa a interrupcao de USART-TX
IEC0bits.U1TXIE = 1; //permite que a USART1-TX dispare interrupcoes
IFS0bits.U1RXIF = 0; //limpa a interrupcao de USART-RX
IEC0bits.U1RXIE = 1; //permite que a USART1-RX dispare interrupcoes LIGA apenas depois das CONFIGURAÇÕES
// IEC1bits.U2TXIE = 0; //permite que a USART2-TX dispare interrupcoes
// IEC1bits.U2RXIE = 0; //permite que a USART2-RX dispare interrupcoes
// IEC4bits.U1EIE = 0; //... UART1 Error Interrupt Enable bit
// IEC4bits.U2EIE = 0; //... UART2 Error Interrupt Enable bit
// IPC2bits.U1RXIP = 4; //UART1 Receiver Interrupt Priority (default=4)
// IPC3bits.U1TXIP = 4; //UART1 Transmitter Interrupt Priority (default=4)
// IPC7bits.U2RXIP = 4; //UART2 Receiver Interrupt Priority (default=4)
// IPC7bits.U2TXIP = 4; //UART2 Transmitter Interrupt Priority (default=4)
// IPC16bits.U1EIP = 4; //UART1 Error Interrupt Priority bits (default=4)
// IPC16bits.U2EIP = 4; //UART2 Error Interrupt Priority bits (default=4)



//configuracao do TMR2
T2CONbits.TCS = 0; //configura para modo TIMER
T2CONbits.TGATE = 0; //configura para modo TIMER
T2CONbits.TCKPS = 3; //Timerx Input Clock Prescale Select bits - 11 = 1:256 prescale value
T2CONbits.T32 = 0; //32-bit Timerx Mode Select bit - TMRx and TMRy form separate 16-bit timer
T2CONbits.TCS = 0; //Timerx Clock Source Select bit - 0 = Internal clock (FOSC/2)
T2CONbits.TON = 1; //liga TMR2
// PR2 = 10800; //perfaz 500ms, com as configurações acima
// PR2 = 26; //perfaz ~1.2ms, com as configurações acima
PR2 = 216; //perfaz 10ms, com as configurações acima

//interrupcoes para o TMR2
IFS0bits.T2IF = 0; //limpa a flag de interrupcao de TMR2
IEC0bits.T2IE = 1; //liga interrupcao TMR2

}






/***********************************************************************************************
MAIN routine
***********************************************************************************************/

int main(void)
{
init_uC(); //faz configuracoes iniciais do PIC


while(1)
{

LATBbits.LATB5 ^= 1; //DEBUG, faz oscilacao no pino RB5


}


return 0; //stack underflow, RESET
}


Título: Re: [PIC24] Rotinas de inicialização e Configuração
Enviado por: metRo_ em 06 de Março de 2011, 00:38
De certeza que será muito útil a muitos utilizadores, obrigado :)
Título: Re: [PIC24] Rotinas de inicialização e Configuração
Enviado por: iyahdub em 04 de Dezembro de 2012, 07:26
Venho aqui invocar a vossa experiencia com os pic.
Aqui, usate um cristal de 11.0592Mhz, com prescaler de dois  correcto ?! Ou e a questao de dividir por dois, como nos pic 32 ?!
Desculpa , mas ainda ando a pesca com os 24
Ja agora, tenho outra duvida...
Como so agora passei dos 16F para cima, e que me deparei com as diferentes frequencias possiveis nestes chips.
Sei que se pode mudar para o osc segundario a meiio, mas ainda nao percebi bem a dos 96 MHz PLL. para aloem de servir o stack de USB... Tem mais alguma funcao que nos possa facilitar a vida de alguma maneira que eu nao tenha captado ainda ?
Obrigado em avanco !!

PS : Entretanto encontrei isto, Acho que comeco a compreender melhor !!
Título: Re: [PIC24] Rotinas de inicialização e Configuração
Enviado por: beirao em 05 de Dezembro de 2012, 12:55
Nunca mexi em PIC24, de certeza que dará jeito para quem começar a mexer!!

Novamente, asena em grande!! Obrigado! ;)
Título: Re: [PIC24] Rotinas de inicialização e Configuração
Enviado por: avalente em 07 de Dezembro de 2012, 10:17
Caro A. Sena,

Só um conselho, se me permite...
Nas rotinas de serviço à interrupção (ISR) só limpo a flag no fim de modo a evitar que outra interrupção seja servida dentro da própia ISR.
por exemplo:
Código: [Seleccione]
void __attribute__((__interrupt__)) _T2Interrupt(void)
{
// IFS0bits.T2IF = 0; //limpa a flag de interrupcao de TMR2 = 0;   <------ Não colocava aqui ...

LATBbits.LATB6 ^= 1; //DEBUG, faz oscilacao no pino RB6

if (bTimeoutOn) //se houver autorizacao para contagem do TIMEOUT, fa-la
wTimeout--;

       IFS0bits.T2IF = 0; //limpa a flag de interrupcao de TMR2 = 0;   <------  .... mas sim aqui
}

Um abraço,
António Valente