domingo, 5 de abril de 2020

Comunicación SPI para PIC24FJXXGA004 en XC16

En este ejemplo haré referencia a la hoja de datos para la familia PIC24FJXXGA004, así que deben tenerla a la mano. 'XX' hace referencia al tamaño de la memoria de programa. En este caso particular usaré un PIC24FJ32GA004 (32Kb). Lo primero que hay que saber es que esta familia de PIC's tiene pines remapeables (Peripheral Pin Select). Para usar los pines asociados al SPI, UART, PWM, interrupciones externas, etc, se deben mapear a los pines del puerto virtual RP. Para trabajar con SPI requerimos 3 pines: SCK1,  SDO1 y SDI1. Para poder realizar el mapeo, existen dos grupos de registros que hay que configurar. Uno es el grupo de 24 registros de mapeo entrada: del RPINR0 al RPINR23 (pags. 111-117). El otro es el grupo de 13 registros mapeo de salida: del RPOR0 al RPOR12  (pags 118-124). La forma de mapear entradas es muy distinta a la de mapear salidas. Para mapear un pin de entrada debe elegirse el registro asignado al periférico que nos interesa mapear. Para esto podemos consultar la Tabla 10-2 de la página 108. Ahí podremos ver que la entrada SDI1 se configura con el registro RPINR20. Lo que debemos hacer ahora es escribir en RPINR20.SDI1R el numero de RPx a dónde queremos poner a SDI1. En este ejemplo lo pondremos en RP2 (RB0) de la siguiente manera:

RPINR20bits.SDI1R = 2; // SDI -> RP2/RB2

Para mapear las salidas debe elegirse primero el RPx, RP0 y RP1 para SCK1 y SDO1 respectivamente en este ejemplo. El registro necesario será por lo tanto RPOR0 (pag. 118). Este registro tiene los campos RP0R y RP1R asociados a RP0 y RP1. Para elegir las funciones de estos pines debe consultarse la Tabla 10-3 de la pagina 109. Se podrá ver que el código para SKC1OUT es 8 y para SDO1 es 7.  Configuramos los dos pines de la siguiente manera:

 RPOR0bits.RP0R = 8;  // SCK -> RP0/RB0 
RPOR0bits.RP1R = 7;  // SDO -> RP1/RB1

El circuito simulado en Proteus es el siguiente:
(Click para agrandar)
El código completo:

/*
* File: main.c
* Author: Rodolfo E. Escobar U.
* Device: PIC24FJ32GA002
* Created on 4 de abril de 2020, 08:09 PM
*/
// --- FUSES ---
// CONFIG2
#pragma config POSCMOD = XT // Primary Oscillator Select (XT Oscillator mode selected)
#pragma config OSCIOFNC = OFF // Primary Oscillator Output Function (OSC2/CLKO/RC15 functions as CLKO (FOSC/2))
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor (Clock switching and Fail-Safe Clock Monitor are disabled)
#pragma config FNOSC = PRIPLL // Oscillator Select (Primary Oscillator with PLL module (HSPLL, ECPLL))
#pragma config IESO = ON // Internal External Switch Over Mode (IESO mode (Two-Speed Start-up) enabled)
// CONFIG1
#pragma config WDTPS = PS32768 // Watchdog Timer Postscaler (1:32,768)
#pragma config FWPSA = PR128 // WDT Prescaler (Prescaler ratio of 1:128)
#pragma config WINDIS = ON // Watchdog Timer Window (Standard Watchdog Timer enabled,(Windowed-mode is disabled))
#pragma config FWDTEN = OFF // Watchdog Timer Enable (Watchdog Timer is disabled)
#pragma config ICS = PGx2 // Comm Channel Select (Emulator/debugger uses EMUC2/EMUD2)
#pragma config GWRP = OFF // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = ON // JTAG Port Enable (JTAG port is enabled)
// ---
#include <p24FJ32GA002.h>
#include "xc.h"
#define FCY 32000000UL
#include "libpic30.h"
unsigned short writeSPI1( unsigned short data )
{
SPI1BUF = data; // Escribir al buffer
while(!SPI1STATbits.SPIRBF);// Esperar a que se complete tranferecnia
return SPI1BUF; // Leer buffer
}
int main(void) {
// --- Setup ---
TRISBbits.TRISB0 = 0;
TRISBbits.TRISB1 = 0;
TRISBbits.TRISB2 = 1;
TRISBbits.TRISB3 = 0;
TRISBbits.TRISB4 = 0;
// Mapeo de pines para SPI (ver pag. 107)
RPOR0bits.RP0R = 8; // SCK -> RP0/RB0
RPOR0bits.RP1R = 7; // SDO -> RP1/RB1
RPINR20bits.SDI1R = 2; // SDI -> RP2/RB2
// Configurción SPI (ver pag. 141)
SPI1BUF = 0x00;
SPI1CON1bits.MSTEN = 1; // Activar modo Maestro
SPI1CON1bits.SMP = 0; // Bit de fase de entrada (muestra a la mitad)
SPI1STATbits.SPIROV = 0;// Bandera de overflow bajada
SPI1STATbits.SPIEN = 1; // Activar modulo SPI1
// -------------
LATBbits.LATB0 = 1; // SS desactivado
//while(1){
__delay_ms(500);
LATBbits.LATB3 = 1;
LATBbits.LATB0 = 0; // SS activado
writeSPI1(88);
LATBbits.LATB0 = 1; // SS desactivado
__delay_ms(500);
LATBbits.LATB3 = 0;
LATBbits.LATB0 = 0; // SS activado
writeSPI1(23);
LATBbits.LATB0 = 1; // SS desactivado
//}
while(1){}
return 0;
}
view raw main.c hosted with ❤ by GitHub

No hay comentarios: