Mostrando entradas con la etiqueta MPLAB X. Mostrar todas las entradas
Mostrando entradas con la etiqueta MPLAB X. Mostrar todas las entradas

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:

lunes, 18 de marzo de 2019

LCD en MPLAB X / XC8

Había comentado en una entrada pasada que las nuevas versiones de XC8 dejaron de usar Peripheral Library y en esa misma entrada explico el truco que pueden hacer para utilizarla. Sin embargo, los usuarios de PIC's modernos deben saber lo cómodo que es usar ahora MCC. Pero también habrán notado que no hay un generador de código para el manejo de LCD's.  Así que he hecho un fork en GitHub de una librería hecha por Manolis Agkopian a la que hecho una mínima modificación para poder usarla en el PIC18F45K50. Pueden acceder a los códigos aquí. Esta librería me parece genial porque te permite usar el puerto que quieras, a diferencia de la mayoría que he visto que te limitan a un puerto fijo (que debes modificar si quieres usar otro). Lo único que deben hacer es agregar los archivos lcd.h y lcd.c a los headers de su proyecto. Como aún hay muchos usuarios del PIC18F4550 voy a poner aquí un ejemplo con él.  Usaré una tarjeta Miuva a 48 MHz: 

martes, 12 de marzo de 2019

Máquina de Estados Finitos en C [PIC18F45K50]

Para esta implementación en software de una máquina de estados finitos (FSM: Finite State Machine) haremos uso de punteros a funciones [click en el enlace para ver un video-tutorial]. Usaremos también  el compilador XC8 en MPLAB X y un PIC18F45K50 con las mismas configuraciones que en la entrada anterior.

En una gran cantidad de problemas a resolver mediante un sistema embebido es necesario llevar a cabo un proceso estrictamente secuencial. En estos casos es muy útil y elegante estructurar nuestros programas como una máquina de estados. Quizá muchos de ustedes estén tentados a usar una estructura case para elegir un segmento de código cuando se cumple una condición. Si el numero de estados es pequeño, quizá se una opción fácil. Desafortunadamente el uso de case's es muy ineficiente cuando la máquina de estados y su tabla de transiciones es muy compleja. La implementación que se mostrará en esta entrada parecerá un tanto rebuscada pero tiene la ventaja de tener buen despeño a la hora de escalarla a numero grande de estados.

El diagrama de estados de la FSM de este ejemplo es el siguiente:
Diagrama hecho en LaTeX con TIKz
Las entradas 0/1 representan los estados de un switch conectado a RB0. Los estados se harán visibles enviando el numero correspondiente al Puerto D [esta acción será definida en la función asociada a cada estado]. Obsérvese que está máquina describe a un contador ascendente o descendente según la entrada. Se agregará un retardo de un segundo para poder visualizar las transiciones.

Movámonos al programa. Primero, debemos definir un tipo enumerado para codificar nuestro conjunto de estados:

//-- Definición de tipo de estados
typedef enum {
    Estado_0,      // Estado inicial
    Estado_1,
    Estado_2,
    Estado_3,
    Estado_4,      
    No_de_Edos
} ESTADOS;

Creamos con esto una variable enumerada global que usaremos para almacenar el estado actual de la máquina:

//-- Variable global de estado
ESTADOS Estado_Actual = Estado_0;

El siguiente paso es definir una estructura que nos permitirá construir un objeto para nuestra FSM:

//-- Estructura de Maquina de Estados (FSM))
typedef struct {
    ESTADOS Estado; // Estado miembro del conjunto enumerado ESTADOS
    void (*func)(int); // Acciones asociadas al estado         
} FSM;

Con lo anterior podemos ahora crear una instancia que sera nuestra FSM:

//-- Prototipos de funciones de estado
void Codigo_EDO_0(int);
void Codigo_EDO_1(int);
void Codigo_EDO_2(int);
void Codigo_EDO_3(int);
void Codigo_EDO_4(int);

//-- Creación de la estructura global de la FSM
FSM Maquina_de_Estados[] = {
    {Estado_0,Codigo_EDO_0},
    {Estado_1,Codigo_EDO_1},
    {Estado_2,Codigo_EDO_2},
    {Estado_3,Codigo_EDO_3},
    {Estado_4,Codigo_EDO_4},
};

Es importante que los prototipos de las funciones asociadas a cada estado aparezcan antes de la creación de la estructura (estas funciones serán definidas más adelante en el código). El segmento de código principal queda reducido elegantemente de la siguiente manera:

void main(void) {
    int sw = 0;
    setup();
   
    //-- FSM ---
    while(1){
        sw = PORTBbits.RB0;
        (*Maquina_de_Estados[Estado_Actual].func)(sw);
    }
    return;
}

Código completo:
Circuito utilizado:

viernes, 22 de febrero de 2019

Iniciando con el PIC18F45K50 / 25K50 en XC8

El PIC18F4550 es uno de los microcontroladores más populares entre estudiantes y hobbistas. Sin embargo ya es algo viejo (no tiene soporte para MCC , los K50 si). Poco a poco, se está migrando a su sustituto más nuevo: el PIC18F45K50. En México, fecha de 2019, aún no es muy fácil de conseguir en tiendas pero puede comprarse con envío gratis en Newark Mexico. Si nunca han usado MPLAB con XC8 aquí hay un tutorial bastante bueno (con PIC16, pero estén pendientes a mi canal porque subiré un curso para los K50). Vamos a realizar una práctica sencilla para comenzar a familiarizarnos con este MCU: Prender y apagar un led conectado a RB0 mediante un switch conectado a RD0 con un reloj a 48 MHz. Tengan a la mano la datasheet y vayamos por partes:

1. Configuración del reloj

El esquema de reloj es distinto al de su antecesor [pag. 29]. Usando un cristal de 16 MHz, este es el camino que debe estar habitado para conseguir los 48 MHz:
Click para agrandar
Los configuraciones necesarios son las siguientes:

#pragma config PLLSEL = PLL3X
#pragma config CFGPLLEN = OFF // ver Tabla 3-3 
#pragma config CPUDIV = NOCLKDIV
#pragma config FOSC = HSM     

#pragma config PCLKEN = ON  

 2. Configuración de puertos

Los pines RB0 y RD0 son usados por el módulo ADC por lo que deben desactivarse para ellos. En el caso del puerto B, esto puede hacerse al generar la cabecera de fuses con la linea:

#pragma config PBADEN = OFF

Para el caso de RDO deberá hacerse en el código principal escribiendo en el registro ANSELD [la tabla con todos los registros de función especial está en la página 84 de la datasheet] :
 3 Código completo en C

Como regla general siempre se debe leer en puerto y escribir  en latch:

jueves, 13 de septiembre de 2018

Librerías de periféricos en MPLAB X v5+ / XC8

Como ya se deben haber dado cuenta todos los que han intentado usar plib.h en las versiones más recientes de XC8, estas bibliotecas han sido descontinuadas en favor de MPLAB Code Configurator y el linker no da la opción de Link in peripheral library. Pero es posible seguir usándolas instalando versiones anteriores de XC8 que pueden ser descargadas desde el archivo de software de Microchip. El usuario de GitHub Burakenes recomienda instalar la versión 1.34 que ya viene con las librerías de periféricos pre-instaladas y da menos problemas que las versiones en dónde deben instalarse por separado. Una vez instalado XC8 v1.34 aún hará falta ir a las propiedades del proyecto linker y seleccionar la casilla de Link in peripheral library. Aquí muestro una captura de una prueba de xlcd.h modificada para la tarjeta de desarrollo Miuva:
 Pueden leer aquí un tutorial de modificacion de los pines para el LCD.

miércoles, 12 de septiembre de 2018

Instalar MPLAB X en Debian 9 (64 bits)

Primero deben activar el soporte multi-arquitectura agregando la arquitectura i386

 $ sudo dpkg --add-architecture i386 

Luego instalar librerias de compatibilidad para i386:

$ sudo apt-get update 
$ sudo apt-get upgrade
$ sudo apt-get install libc6:i386 libx11-6:i386 libxext6:i386 libstdc++6:i386 libexpat1:i386 

Finalmente se ejecuta el instalador descargado de aquí:

$ sudo ./MPLABX-v5.05-linux-installer.sh

Si la instalación se realiza correctamente podemos iniciar MPLAB X buscándolo en las aplicaciones:


NOTA: Deben tener ya instalado Java Runtime Enviroment en su sistema. Aquí hay una guía de instalación en español.