57
2010 Alejandro www.micros-designs.com.ar 10/04/2010 MPLAB C30 y PIC24

ABC de La Mecatronica - STEREN

Embed Size (px)

Citation preview

  • 2010

    Alejandro

    www.micros-designs.com.ar

    10/04/2010

    MPLAB C30 y PIC24

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Tabla de contenido PIC24 Y C30 ............................................................................................ 3

    Programacin. ...................................................................................... 5

    Introduccin: ........................................................................................ 6

    Memoria de datos. ............................................................................... 9

    Creando el primer Proyecto. ..................................................................... 11

    El Cdigo Fuente ................................................................................... 13

    La funcin principal. ........................................................................... 14

    Operacin de cambio de clock. ................................................................. 17

    Ejemplo en C30: ................................................................................ 18

    Algunos aspectos de C30: ........................................................................ 19

    Atributos de variables. ......................................................................... 20

    Atributos a funciones: .......................................................................... 20

    Interrupciones. ..................................................................................... 21

    Registros de control y estado de las interrupciones: ...................................... 22

    Manejo de las interrupciones: ................................................................ 23

    Mdulos temporizadores. ......................................................................... 25

    Modos de operacin. ........................................................................... 26

    Configuracion timer 32-bits. .................................................................. 28

    Operacin de lectura y escritura. ............................................................ 28

    Ejemplo modo temporizacin, interrupcin cada 500ms a 40 MIPS. .................... 29

    Seleccin de pines de los perifricos. .......................................................... 32

    UART. ............................................................................................... 34

    Baud rate. ........................................................................................ 35

    Configuracin de la USART. ................................................................... 35

    Uso del printf en C30. .......................................................................... 42

    Notificacin de cambio de estado de pines. ................................................... 43

    Control LCD. Modo 4-bits o 3-pines ms registro de desplazamiento ...................... 46

    Modificacin de funciones de bajo nivel de la librera stdio.h para re-direccionar

    salida de datos de printf. ...................................................................... 47

    ANEXO A. ........................................................................................... 49

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    PIC24 Y C30

    Aqu se presenta una introduccin para comenzar a trabajar con los microcontroladores

    PIC24 y MPLAB C30.

    Para comenzar necesitamos tener instalado:

    MPLAB IDE, entorno de programacin.

    MPLAB C30, C Compiler (Versin estudiantil)

    En estos ejemplos voy a trabajar principalmente con el PIC24HJ128GP505 y adems

    mostrar algunos ejemplos con el PIC24FJ128GA010. El primero, en un primer momento,

    lo he elegido sencillamente por dos razones, disponibilidad y porque tiene package DIP que

    nos facilita enormemente la construccin de una placa para trabajar con l. Y para ello he

    construido una mini placa de desarrollo para estos microcontroladores DIP28.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Caractersticas:

    Prototipo para todos los 28-pines, DIP PIC24, dsPIC30F y dsPIC33F

    Reguladores para 3.3V o 5V de operacin sobre la placa

    Comunicacin UART

    Conector para PICkit 2 In-circuit Debugger/Programmer Header para acceder a todos los pines I/O del microcontrolador

    Por aqu esta el pdf con el esquemtico y el PCB para su construccin.

    Para trabajar con el segundo he realizado una placa adaptadora para usar la Multiboard del

    amigo Felixls:

    Si alguien se anima se comunica por mail para el pdf de la placa.

    Algunas caractersticas de estos PIC:

    PIC24HJ128GP502:

    El CPU puede operar hasta 40 MIPS

    Oscilador interno de 8Mhz

    PLL interno

    Memoria de programa de 128kB

    Memoria RAM 8kB

    Direccionamiento lineal de memoria de programa de hasta 4MB

    Direccionamiento lineal de la memoria de datos de hasta 64kB.

    Stack por software

    Hardware para multiplicacin 16x16, divisin 32x16 y 16x16.

    8 canales DMA (Acceso a memoria directo)

    2 UART 2 SPI 1 I2C

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Mdulo AD. 10-bit 1.1 Msps o 12-bit a 500ksps.

    4 Mdulos Comparacin/Captura/PWM. 16-bits PWM.

    Timers, 5 x 16-bit 2 x 32-bit.

    RTC (Reloj de tiempo real)

    PPS (Periferal Pin Select).

    Etc.

    PIC24FJ128GA010:

    El CPU puede operar hasta 16 MIPS

    Oscilador interno de 8Mhz

    PLL interno

    Memoria de programa de 128kB

    Memoria RAM 8kB

    Direccionamiento lineal de memoria de programa de hasta 4MB

    Direccionamiento lineal de la memoria de datos de hasta 64kB.

    Stack por software

    Hardware para multiplicacin 16x16, divisin 32x16 y 16x16.

    2 UART 2 SPI 2 I2C

    Puerto paralelo Master-Slave. Direccionamiento 16-bits, Datos 8-bits o 16-bits.

    Mdulo AD. 10-bit a 500ksps.

    5 Mdulos Comparacin/Captura/PWM. 16-bits PWM.

    Timers, 5 x 16-bit 2 x 32-bit.

    RTC (Reloj de tiempo real)

    Mdulo CRC configurable.

    5 interrupciones externas.

    Pines configurables como a colector abierto (Salidas)

    Etc.

    Sencillamente espectacular!!!

    Algo que me llama la atencin es el DMA, leyendo el datasheet ya nos damos una idea de

    que se trata:

    Acceso directo a memoria (DMA) es un mecanismo muy eficiente de copia de datos entre

    perifricos SFRs (por ejemplo, registro de recepcin UART, buffer de entrada Captura 1), y

    buffer o variables almacenadas en la memoria RAM, con una intervencin mnima del CPU.

    El controlador DMA puede copiar automticamente bloques enteros de datos sin necesidad

    de software para leer o escribir en lo SFRs cada vez que se produce una interrupcin del

    perifrico. El controlador DMA usa un bus dedicado para la transferencia de datos y por lo

    tanto, no utiliza ciclos de ejecucin del cdigo del CPU.

    Programacin. Para programarlos hay diversas herramientas, entre las cuales encontramos las de Microchip

    (PICKit2, PicKit3, ICD2, ICD3, ect) , GTP-USB [plus], etc. En mi caso he construido el

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    PICKit2 Clone, que junto a Felixls hemos diseado uno compatible con estos

    microcontroladores que trabajan a 3.3V. Por aqu tienen una de las versiones disponibles por

    el momento.

    Introduccin:

    Microchip ofrece 2 familias de microcontroladores de 16 bits, la familia PIC24F de bajo

    costo y performance media (Muy rentable, mximo 16 MIPS) y la familia PIC24H de alta

    performance (Mximo 40 MIPS). Entre las familias hay muchos atributos en comn, entre

    ellos son la compatibilidad de pinout, compatibilidad de perifricos, misma herramienta de

    desarrollo, entre otras.

    Principales caractersticas:

    Memoria de programa flash de 4 a 256 Kbytes. Memoria RAM de 0.5 a 16Kbytes. DMA, 8 canales con 2Kbytes de RAM.

    Package de 14 a 100 pines. Peripheral Pin Select (PPS), seleccin de pines para perifricos de forma flexible. Arquitectura diseada para las exigencias de control en tiempo real. Osciladores integrados de alta velocidad y baja potencia con PLL.

    USB-OTG en productos de 28 a 100 pin. (Soporta USB HOST). UART, soporta LIN, IrDa, RS-232, RS485 con 4 niveles de buffer FIFO o DMA. SPI, 8 niveles de Buffer FIFO o DMA. I2C, modo multi-master, slave de 7/10 bits de direccionamiento. Bus CAN, con 8 buffers de transmisin y 32 de recepcin. CRC, programable.

    Temporizadores de 16-bits que se pueden colocar en cascada para formar de 32-bits. Reloj de Tiempo Real con Calendario.

    A/D de 10/12-bits.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Unidad de medida de tiempo de carga (CTMU), una fuente de corriente constante acoplada al ADC que provee la habilidad de medir capacidades o tiempos con una

    resolucin de ns. til para realizar teclados sensibles al tacto.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    La CPU de los PIC24 posee una arquitectura Harvard modificada con avanzado set de

    instrucciones con palabras de 24-bits de ancho. La memoria de programa tiene 4M-24bits

    como espacio de direcciones, pero solo se implementa un porcentaje que depender del

    dispositivo.

    Las instrucciones se ejecutan en un solo ciclo de programa salvo algunas excepciones como

    las instrucciones que cambian el flujo del programa, instrucciones de tabla e instrucciones de

    acceso a PSV que pueden ocupar ms.

    Estos microcontroladores poseen 16 registros W de 16 bits, en donde una palabra puede ser

    un dato o una direccin. El ltimo registro W (W15) opera como puntero de software de la

    memoria de programa para llamadas a subrutinas y pedidos de interrupcin

    Una propiedad que agrega es la capacidad de que los ltimos 32KB de la memoria de datos

    pueden ser mapeados en la memoria de programa cmo 16Kword, quedando definida el rea

    por el registro Program Space Visibility Page (PSVPAG). De esta manera los datos

    mapeados en la memoria de programa son accedidos como si fueran de la memoria de datos

    y no necesitan de instrucciones especiales para su acceso (por ejemplo, TBLRD, TBLWT).

    Espacio de memoria DMA (Solo para los PIC24H), para transferencia de datos desde

    perifricos. El controlador DMA usa un bus dedicado para la transferencia de datos y por lo

    tanto, no utiliza ciclos de ejecucin del cdigo del CPU.

    Posee un bloque de multiplicacin 17x17 que puede realizar operaciones signadas, sin signo

    o mixtas de 16-bits x 16bits o 8-bits x 8-bits en un solo ciclo de programa. Adems tambin

    hay un bloque de divisin de 32-bits o 16-bits dividido 16-bits signado o no signado, que

    requiere 19 ciclos de programa.

    Memoria de programa.

    Como dijimos anteriormente estos dispositivos tienen 4M-24bits como espacio de

    direcciones de memoria de programa. Este espacio es direccionable/accedido por 24 bits

    derivados de tres mtodos, el contador de programa (PC, 23 bits, se limita de 0x000000 a

    0x7FFFFF), la tabla de operacin (TBLRD, TBLWT) o desde el re-mapeo del espacio de

    memoria.

    sta es dividida en 2 sectores, en el espacio de programa de usuario y en el espacio de

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    configuraciones. El espacio de programa de usuario (0x000000 a 0x7FFFFF) a la vez est

    divido en sectores:

    Vector de reset. (0x000000 a 0x000003) Tabla de vectores de interrupciones. (0x000006 a 0x0000FE) Tabla alterna de vectores de interrupciones. (0x000106 a 0x0001FE) Memoria de programa. (0x000200 a 0x., depender del dispositivo, mximo 0x7FFFFF)

    Memoria de datos.

    Como estos dispositivos son de arquitectura Hardvard tienen buses independientes para la

    memoria de datos y para la memoria de programa, lo que permite el acceso simultaneo. La

    memoria de datos de los PIC24 tiene 16 bits de ancho y su direccionamiento es lineal. El

    espacio de datos es accedido por dos unidades generadoras de direcciones (Address

    Generation Units o AUGs) para operaciones de lectura y escritura.

    Un bloque de direccionamiento efectivo (Effective Address o EA) es responsable del

    direccionamiento de la memoria de datos. En la mitad baja del espacio de memoria

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    (EA=0) se implementa la memoria RAM (0000h a 7FFFh), mientras que la mitad alta

    es reservado para el rea de visualizacin de la memoria de programa (PSV).

    Espacio SFR

    Los primeros 2 Kbytes del espacio de memoria es ocupado por los registros de funciones

    especiales, estos son usados para el control de operacin del CPU y de los perifricos del

    mismo. Memoria RAM DMA.

    Los PIC24H disponen de un espacio de memoria con doble puerto que puede ser accedido

    simultneamente por el CPU o por el mdulo DMA. Su capacidad depende del dispositivo.

    Este espacio de memoria es utilizado por el controlador DMA para transferir datos desde

    perifricos que lo soporten, sin utilizar ciclos adicionales del CPU.

    Adems este espacio de memoria puede usarse para propsitos generales si no se utiliza la

    funcin DMA en el proyecto.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Creando el primer Proyecto. Creamos un nuevo proyecto:

    Seleccionamos dispositivo:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Creamos y guardamos archivo fuente del proyecto con extensin c, incluyndolo al mismo:

    Insertamos el linker Script (*.GLD) del dispositivo utilizado.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Este archivo informa al enlazador acerca de posiciones predefinidas en la memoria (de

    acuerdo a la hoja de datos del dispositivo), as como proporciona informacin esencial

    espacio de memoria, tales como: cantidad total de memoria Flash disponibles, la cantidad

    total de memoria RAM disponible, y sus rangos de direcciones. Se encuentra en

    \Microchip\MPLAB C30\support\PIC24H\gld.

    Con esto, creo que ya estamos listos para programar algo en C30

    El Cdigo Fuente

    En primer lugar incluimos el archivo *.h del dispositivo utilizado, este contiene definidos los

    registros funciones especiales y bits de los mismos.

    #include

    Ahora sigue la configuracin de fuses, en este caso depende del dispositivo utilizado y para

    saber que funciones y como configurarlas, debemos ir a la seccin de caractersticas

    especiales en el datashhet.

    Para este dispositivo tenemos:

    o Bits de configuracin para proteccin de Flash y RAM:

    _FBS(x)

    _FGS(x)

    o Bits de configuracin para seleccin de oscilador.

    _FOSCSEL(x)

    _FOSC(x)

    o Bits de configuracin para seleccin de Watchdog.

    _FWDT(x)

    o Configuraciones generales como Power-on Reset, pin I2C, JTAG, ect.

    _FPOR(x)

    _FICD(x)

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Para saber la sintaxis hay que darle una miradita al *.h del dispositivo, al final estn los

    define de los mismos.

    Por ejemplo:

    _FOSCSEL(FNOSC_PRIPLL); // Oscilador primario + PLL

    _FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock y

    Fail-Safe Clock des-habilitados, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    La funcin principal.

    main(void){

    }

    Funcin que debe estar si o si, pues es la primera que se ejecuta al iniciar es sistema, en

    donde configuraremos los perifricos y llevaremos control de nuestra aplicacin.-

    Configuracin del PLL y determinacin de MIPS de trabajo.

    El oscilador primario y el oscilador interno (FRC), puede utilizar el PLL interno para

    obtener mayores velocidades de operacin, adems proporciona una significativa

    flexibilidad en la seleccin de la velocidad de funcionamiento del dispositivo.

    La salida del oscilador primario o FRC, el cual denominamos 'Fin', se divide por un factor

    de pre-escale (N1), de 2, 3, ... o 33 antes de ingresar al PLL de tal manera que est entre el

    intervalo de 0,8 MHz a 8 MHz. El factor de pre-escaler N1 se selecciona mediante los bits PLLPRE del registro CLKDIV.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    El divisor de realimentacin del PLL, es seleccionado mediante los bits PLLDIV del

    registro PLLFBD, que proporciona un factor M (2513), por el que se multiplica la entrada al PLL. Este factor debe ser elegido de modo que la frecuencia resultante de salida

    est en la gama de 100 MHz a 200 MHz.

    La salida del PLL se divide por un factor post-escaler N2. Este factor se selecciona mediante el los bits PLLPOST del registro CLKDIV. N2 puede ser 2, 4 u 8, y debern seleccionarse de forma que la frecuencia de salida PLL (FOSC) est en el rango de

    12,5 MHz a 80 MHz, lo que genera una velocidad de funcionamiento del dispositivo de

    6.25-40 MIPS.

    Fosc=Fin*(M/(N1*N2))

    Tenemos que Fcy=Fosc/2, pero adems con los bits DOZE del registro CLKDIV

    podemos aplicar un pos-escaler entre 2,4,8,16,32,64 o 128.

    Por ejemplo con un cristal de 4MHz, N1 = 2, M = 80; N2 = 2; Fcy = Fosc/2 obtenemos 40

    MIPS.

    PLLFBD = 0x0000;

    CLKDIV = 0x004E;

    Bueno, hasta aqu ya hemos definido algunos detalles de como va a trabajar nuestro

    microcontrolador, ahora hagamos un ejemplo sencillo de hacer titilar los led ubicados en

    RB12-RB15.

    La librera para agregar demoras a nuestro programa libpic30.h, pero tiene un bug, no se

    puede usar a 40MIPs Para utilizar demoras se debe incluir la librera, definir la

    frecuencia FCY y disponemos de la funcin __delay32(Numero de ciclos) con la cual

    podemos hacer demoras mayores a 12 ciclos. Luego tenemos definidos 2 macros:

    #if !defined(FCY)

    extern void __delay_ms(unsigned long);

    extern void __delay_us(unsigned long);

    #else

    #define __delay_ms(d) \

    { __delay32( (unsigned long) (d)*(FCY)/1000); }

    #define __delay_us(d) \

    { __delay32( (unsigned long) (d)*(FCY)/1000000); }

    #endif

    El problema a 40MIPs surge en la definicin del macro, pues d*FCY se va de rango de los

    32 bits cuando d es mayor a 107 aprox. y genera una demora incorrecta, para solucionarlo

    hay que cambiar a unsigned long long para trabajar con 64-bits. Tambin podemos agregar

    una demora de segundos.

    #define _delay_ms(d) __delay32( (unsigned long long) (d)*(FCY)/1000)

    #define _delay_us(d) __delay32( (unsigned long long) (d)*(FCY)/1000000)

    #define _delay_s(d) __delay32( (unsigned long) (d)*(FCY))

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Ejemplo:

    /* ********* Primer Proyecto en C30 *************

    \Autor: Suky

    \Fecha: 11/01/10

    */

    #include

    #define FCY 40000000UL

    #include

    _FOSCSEL(IESO_OFF & FNOSC_PRIPLL); // Oscilador primario + PLL

    _FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock y

    Fail-Safe Clock des-habilitados, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    main(int argc, char * argv[]){

    // Cristal de 4MHz y PLL trabajando a 40 MIPS.

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    while(_LOCK==0);

    AD1PCFGL=0xFFFF; // todos los pines digitales.-

    TRISB=0x0FFF; // Configuramos RB2-RB15 como salidas.-

    while(1){

    LATB=0xF000;

    __delay_ms(500);

    //__delay_s(1);

    LATB=0x0000;

    __delay_ms(500);

    //__delay_s(1);

    }

    }

    Utilizando el PIC24FJ128GA010:

    #include

    _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx2

    & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR128 & WDTPS_PS32768);

    _CONFIG2( FNOSC_PRI & FCKSM_CSDCMD & POSCMOD_HS );

    #define FCY 10000000UL

    #include

    int main (int argc, char * argv[]){

    TRISF=0xFFF3;

    LATFbits.LATF2=0;

    LATFbits.LATF3=0;

    while(1){

    LATFbits.LATF2=0;

    __delay_ms(500);

    LATFbits.LATF2=1;

    __delay_ms(500);

    }

    }

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Operacin de cambio de clock.

    En esta arquitectura se puede cambiar entre 4 fuentes de reloj (Primario, LP, FRC y LPRC)

    por medio de software cuando se desee. El primario tiene 3 sub modos de operacin (XT,

    HS y EC) que son configurados mediante los bits de configuracin, sea que en tiempo de

    operacin no se puede cambiar de modo, pero si se puede cambiar desde o hacia la fuente

    primaria.

    Para habilitar el cambio de clock, el bit de configuracin FCKSM1 del registro de

    configuracin debe ser programado como 0.

    Los bits COSC (OSCCON) reflejan la seleccin de la fuente de clock de los bits

    de configuracin FNOSC, y los bits de control NOSC (OSCCON) controlan la

    seleccin de clock cuando el cambio est habilitado. El bit de control OSWEN

    (OSCCON) inicia el cambio y muestra la finalizacin, pero si el cambio no esta

    habilitado, este bit siempre se sostiene a 0.

    Secuencia de cambio de oscilador.

    El cambio de clock requiere la siguiente secuencia:

    1. Si se desea, para determinar la fuente de clock actual se debe leer los bits COSC

    (OSCCON).

    2. Realizar la secuencia de desbloqueo para permitir la escritura del byte alto del registro

    OSCCON.

    3. Escribir el valor apropiado a los bits de control NOSC (OSCCON) para la nueva

    fuente de clock.

    4. Realizar la secuencia de desbloqueo para permitir la escritura del byte bajo del registro

    OSCCON.

    5. Setear el bit OSWEN (OSCON) para iniciar el cambio de oscilador.

    Una vez que esta secuencia ha sido completada, el hardware responder de la siguiente

    manera:

    1. Se compara los bits COSC con los bits NOSC, si son iguales el bit OSWEN es borrado

    automticamente y el cambio de clock es abortado.

    2. Si el cambio de clock es valido, los bits LOCK y CF del registro OSCCON son

    borrados.

    3. El nuevo oscilador es encendido por el hardware y se espera el tiempo adecuado. Si

    usar PLL, se espera hasta que el PLL se enganche. (LOCK=1)

    4. El hardware espera 10 ciclos de clock de la nueva fuente y recin realiza el cambio.

    5. Se borra el bit OSWEN para indicar la finalizacin de la transicin, y los bits COSC se

    actualizan con los de NOSC.

    6. La fuente antigua de clock es apagada.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Ejemplo en C30:

    Pasando de oscilador principal XT de 4MHz sin PLL (2 MIPS) a oscilador principal XT con

    PLL (40 MIPS).

    /* ********* Cambiando clock *************

    \Autor: Suky

    \Fecha: 07/01/10

    */

    #include

    _FOSCSEL(IESO_OFF & FNOSC_PRI); // Oscilador primario

    _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock

    habilitado, Fail-Safe Clock des-habilitado, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    void Delay_us(unsigned int time){

    while(time!=0){

    asm volatile("repeat #34");

    asm volatile("nop");

    time--;

    }

    }

    void Delay_ms(unsigned int time){

    while (time!=0){ Delay_us(1000); time--;}

    }

    main(void){

    // Configuramos PLL para trabajar a 40 MIPS con Cristal de 4MHz.-

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    // Cambiamos clock para incroporar PLL.-

    __builtin_write_OSCCONH(0b011); // Indicamos cambio a clock

    primario con PLL.-

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    __builtin_write_OSCCONL(0x01); // Iniciamos cambio.-

    while(OSCCONbits.OSWEN == 1) {}; // Esperamos a que se termine el

    cambio de clock.

    AD1PCFGL=0xFFFF; // todos los pines digitales.-

    TRISB=0x0FFF; // Configuramos RB2-RB15 como salidas.-

    while(1){

    LATB=0xF000;

    Delay_ms(1000);

    LATB=0x0000;

    Delay_ms(1000);

    }

    }

    Otra caracterstica interesante que tienen estos microcontroladores es el Fail-Safe Clock

    Monitor, el cual si est habilitado permite que el dispositivo contine operando ante la falla

    de un oscilador. Al estar habilitado el oscilador interno LPRC esta funcionando durante

    todo el tiempo excepto en modo Sleep, y cuando el oscilador principal falla se genera un

    traps (Interrupcin por falla del sistema) y el sistema cambia el clock al oscilador LPRC. El

    software del usuario ser el encargado de intentar reiniciar el oscilador que ha fallado.

    Algunos aspectos de C30: Tipos de variables:

    Variables enteras:

    Variables flotantes:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Atributos de variables.

    En C30 para fijar atributos especiales a las variables se utiliza la palabra __attribute__ la

    cual es seguida por los atributos dentro de parntesis dobles. Los atributos pueden ser:

    address aligned deprecated far mode near noload packed persistent reverse section sfr space transparent_union unordered unused weak

    Ejemplos:

    Comparando con C18 podemos ver la diferente forma de sintaxis:

    C18:

    near int Data;

    far int Data;

    rom int Buffer[6]={0x01,0x0A,0x07,0xC1,0x26,0xAA};

    #pragma udata data=0x400

    volatile unsigned int Buffer[100];

    C30

    __attribute__((near)) int Data

    __attribute__((far)) int Data

    __attribute__ ((section(.romdata), space(prog))) int

    Buffer[6]={0x01,0x0A,0x07,0xC1,0x26,0xAA};

    volatile unsigned int __attribute__((address(0x400))) Buffer[100];

    Atributos a funciones:

    Tambin se utiliza la palabra clave __attribute__ para dar una propiedad a una funcin, los

    soportados son:

    address (addr) alias ("target") const deprecated far

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    format (archetype, string-index, first-to-check) format_arg (string-index) interrupt [ ( [ save(list) ] [, irq(irqid) ] [, altirq(altirqid)] [,preprologue(asm) ] ) ] near no_instrument_function noload noreturn section ("section-name") shadow unused weak

    Ejemplos:

    // La function se ubica en la direccin 0x100.-

    void Funcion(int a, char b) __attribute__ ((address(0x100))) {

    ...

    }

    // La funcin es ubicada en la seccin libtext pero es definida en otro

    archivo fuente.-

    extern void Funcion(void) __attribute__ ((section (".libtext")));

    // Asigna a la function como tratamiento de interrupcin.-

    void __attribute__((__interrupt__)) isr0(void);

    // Se indica que se guarden las variables automticamente al ejecutarse la

    interrupcin.-

    void __attribute__((__interrupt__(__save__(var1,var2)))) isr0(void);

    // Se indica que se use el salvado de contexto rpido .-

    void __attribute__((__interrupt__, __shadow__)) isr0(void);

    Para ms informacin leer C30 User guide.

    Interrupciones.

    La arquitectura de los PIC24 proporciona 118 fuentes de interrupcin las cuales poseen un

    vector propio para cada una de ellas, a diferencia de la familia 16F que tiene solo un vector,

    y la familia 18F la cual posee 2 vectores para baja y alta prioridad. En este caso no solo

    existen 2 niveles de prioridad, sino 8 que pueden asignarse a cada evento. Adems de las

    interrupciones tenemos 8 TRAPs, que son eventos prioritarios (Sin niveles de prioridad) de

    falla del sistema.

    Los vectores estn agrupados en dos tablas, la principal (IVT-Interrupt Vector Table) y

    alternativa (AIVT-Alternate Interrupt Vector Table) la cual es para soporte de debbug.

    La IVT reside en la memoria del programa comenzando en la direccin 0x000004, la cual

    contiene 126 vectores, 8 Traps y 118 fuentes de interrupcin. Cada vector de interrupcin

    tiene asociado 24-bits para indicar la direccin de arranque de la rutina de servicio de

    interrupcin individual asociada (ISR).

    Las prioridades estn definidas por su prioridad natural, sea est asociada a su posicin en

    la tabla de vectores. Las de ms baja direccin tienen una prioridad natural ms alta.

    La AIVT est localizada inmediatamente despus la de IVT como se muestra en la siguiente

    figura y los vectores estn organizados de la misma manera. El acceso esta controlado por el

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    bit ALTIVT (INTCON2 ), el cual si est en alto todas las interrupciones y

    excepciones son procesadas en ste.

    Registros de control y estado de las interrupciones:

    Para estas funciones se utilizan 30 registros:

    INTCON1 INTCON2 IFSx IECx IPCx INTTREG INTCON1 AND INTCON2

    Contienen los flags para control de estado de los traps, seleccin de vector de interrupciones

    AIVT, etc.

    IFSx

    Estos registros tienen todos los flags de las peticiones de interrupcin. Cada fuente de

    interrupcin tiene su bit de estado, que es seteado por el perifrico respectivo y es borrado

    mediante software.

    IECx

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Estos registros tienen los bit habilitadores/des-habilitadores de cada fuente de interrupcin.

    IPCx

    Estos registros asignan a cada fuente de interrupcin un nivel de prioridad entre 8

    disponibles.

    INTTREG

    Este registro contiene el numero del vector de interrupcin asociado y el nuevo nivel de

    prioridad de interrupcin del CPU (VECNUM y IRL). El nuevo nivel de

    prioridad de interrupcin es la prioridad de la interrupcin pendiente.

    STATUS/CONTROL REGISTERS

    Aunque no son especficamente parte del hardware de control de interrupcin, los registros

    de control del CPU contienen bit que controlan la funcionalidad de las interrupciones.

    El registro SR contiene los bits IPL que indican el actual nivel de prioridad de

    del CPU. El CPU tiene 16 niveles de prioridad (0-15), y una fuente de interrupcin o

    una Traps debe tener mayor prioridad para que pueda generar una excepcin en el

    proceso.

    El registro CORCOn contiene el bit IPL3, que junto a IPL indican el nivel

    actual de prioridad del CPU. Este bit es solo de lectura para que los eventos traps

    (Niveles de prioridad de 8 a 15) no puedan ser enmascarados por el software del

    usuario.

    Manejo de las interrupciones:

    Inicializacin.

    1. Setear el bit NSTDIS si no se desea interrupciones anidadas.

    2. Seleccionar el nivel de prioridad para las fuentes de interrupcin escribiendo el bit de

    control en el regsitro IPCx apropiado. El nivel de prioridad depende de la aplicacin

    especficamente y el tipo de fuente de interrupcin. Si no se desea niveles de prioridad

    mltiples, los bits de control de los registros IPCx para todas las fuentes de interrupcin

    habilitadas pueden ser programadas al mismo valor distinto de cero.

    3. Borrar la bandera de interrupcin asociada en el registro IFSx.

    4. Habilitar la fuente de interrupcin seteando el bit de control asociado en el registro

    apropiado IECx.

    Nota: Interrupcin anidada se refiere a la posibilidad de que una interrupcin de baja

    prioridad pueda ser interrumpida por otra de mayor prioridad. Si no esta habilitada, se espera

    a que termine el tratamiento de una para atender a la siguiente.

    Rutina de servicio de interrupcin en C30.

    Las rutinas de interrupcin (ISR) son como cualquier otra funcin que utilizan variables

    locales o globales pero que no tienen parmetros de entrada, no retornan valores y no pueden

    ser llamadas como otras funciones. Las ISR solo sirven para invocarse a travs de una

    interrupcin por hardware o traps. Para dar por terminada la ISR se utiliza la instruccin (en

    assembler, oculta para el usuario de C30) RETFIE la cual devuelve el valor salvado a PC, y

    restablece el nivel anterior de prioridad del CPU.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Una recomendacin es no llamar a otras funciones dentro de la ISR por problemas de

    latencia.

    Para declarar una funcin como una ISR, se le debe asignar el atributo interrupt, siendo la

    sintaxis la siguiente:

    __attribute__((interrupt [( [ save(ListaVariables)] [, irq(irqid)] [,

    altirq(altirqid)] [, preprologue(asm)])]))

    void __attribute__((__interrupt__)) _StackError(void){

    }

    void __attribute__((__interrupt__)) _AltStackError(void){

    }

    El parmetro opcional save se utiliza para guardar y restablecer una o ms variables al entrar

    y salir de la ISR.

    void __attribute__((__interrupt__(__save__(var1,var2))))isr0(void);

    El parmetro opcional IRQ permite colocar un vector de interrupcin (IVT) a una

    interrupcin especfica, y el opcional ALTIRQ permite colocar una interrupcin a un vector

    alterno (AIVT). Cada parmetro requiere un nmero de identificacin. (Ms informacin,

    C30 user guide, pag. 96)

    void __attribute__((__interrupt__(__irq__(52)))) MyIRQ(void);

    void __attribute__((__interrupt__(__altirq__(52)))) MyAltIRQ(void);

    El parmetro opcional preprologue permite insertar declaraciones en assembler antes del

    cdigo generado por el compilador para la inicializacin de la ISR.

    Void __attribute__((__interrupt__(__preprologue__("inc _semaphore"))))

    isr0(void);

    Des-habilitacin de interrupciones.

    Cada fuente de interrupcin tiene su bit de control para habilitarla o des-habilitarla, pero si

    desea deshabilitar todas las interrupciones se puede establecer el nivel de prioridad del CPU

    mayor al de las interrupciones (mximo nivel 7).

    SET_AND_SAVE_CPU_IPL(current_cpu_ipl, 7); // Des-habilita interrupciones.-

    RESTORE_CPU_IPL(current_cpu_ipl); // Habilita interrupciones.-

    Tambin es posible usar la instruccin DISI que deshabilita las interrupciones (Niveles de

    prioridad 1 a 6) durante un determinado nmero de instrucciones (Mximo 0x3FFF). Esta

    instruccin trabaja en conjunto con el registro DISICNT. Si el registro es distinto de cero,

    las interrupciones con nivel de prioridad entre 1 a 6 son deshabilitadas, y este registro se

    decrementa por cada ciclo. Cuando este registro llega a 0 las interrupciones son re-

    habilitadas.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    __asm__ volatile ("disi #30"); // Deshabilita interrupcin durante 30

    ciclos.

    __asm__ volatile ("disi #0x1E"); // Deshabilita interrupcin durante 30

    ciclos.

    Mdulos temporizadores.

    Estos microcontroladores disponen de timers de 16-bits que pueden dividirse en tres tipo de

    acuerdo a sus funcionalidades:

    Timer tipo A (Timer1)

    Timer tipo B (Timer2, 4, 6 y 8 )

    Timer tipo C (Timer3, 5, 7 y 9)

    Los timers de tipo A, a diferencia de los dems, pueden operar desde un oscilador de baja

    potencia de 32kHz y poseen el modo de contador asincrnico desde fuente de clock externa.

    En cambio los timers de tipo B y C pueden combinarse para formar timer de 32-bits.

    Adems los timers de tipo C pueden activar la conversin AD.

    Cada modulo timers es un contador/temporizador de 16-bits que tienen los siguientes

    registros de control leibles/escribibles:

    TMRx: Registro de 16-bits que lleva la cuenta del timer. PRx: Registro de 16-bits que fija periodo al timer. TxCON: Registro de control del timer. Tambin cada modulo tiene asociado sus bits para el control de interrupcin, para

    habilitacin (TxIE), para control de estado (TxIF) y para fijar prioridad (TxIP).

    Esquema Timer tipo A:

    Esquema Timer tipo B:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Esquema Timer tipo C:

    Modos de operacin.

    Los timers pueden trabajar de los siguientes modos:

    Modo temporizador Modo temporizador controlado por pin externo (Gated timer) Modo contador asincrnico (nicamente Timers tipo A) Modo contador sincrnico.

    En los modos temporizador y Gated se utiliza como clock el ciclo de instruccin interna

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    (Fcy), en cambio, en los modos contador sincronico y asincrnico se utiliza el clock externo

    derivado del pin TxCK. Para control del modo de operacin se utilizan los siguientes bits:

    TCS (TxCON): Bit que determina fuente de clock. TSYC (TxCOM): Bit para determinar si el clock externo se sincroniza con el ciclo de instrucciones (nicamente timers tipo A).

    TGATE (TxCON): Bit que determina modo Gate.

    El clock de entrada (FCY o pin TxCK) de todos los timers poseen la opcin de ser

    preescalado entre 1:1, 1:8, 1:64 o 1:256, esta configuracin de preescaler se realiza mediante

    los bits TCKPS del registro TxCON. La cuenta de los preescaler es borrada cuando se

    efectua una escritura sobre los registros TMRx y TxCON, cuando se deshabilita del timers

    (TON=0) y al ocurrir un reset.

    Los modos temporizacin, contador asincrnico y sincrnico son bien conocidos en las

    familias 16F y 18F, por lo que solo voy a enfocarme en el modo Gate:

    Cuando se selecciona el modo Gate, el timer puede ser usado para la medir la duracin de

    una seal externa. En este modo el timer se incrementa al recibir un flanco ascendente en el

    pin TxCK y continua incrementndose a razn del clock interno (FCY) mientras este se

    mantenga en nivel alto (1). Cuando se recibe un flanco descendente en el pin TxCK se

    detiene la cuenta y se genera una interrupcin.

    Para seleccionar este modo hay que setear el bit TGATE y borrar el bit TCS. Adems se

    debe configurar el pin TxCK como entrada.

    main(void){

    T1CONbits.TCS = 0; // Seleccin de clock interno.

    T1CONbits.TGATE = 1;// Habilitacin modo Gate

    T1CONbits.TCKPS = 0b00; // Preescaler 1:1

    TMR1 = 0x00; // Inicializacin

    PR1 = 9; // Fijamos periodo

    IPC0bits.T1IP = 0x01;// Nivel de prioridad 1 para interrupcin

    IFS0bits.T1IF = 0; // Borramos flag.

    IEC0bits.T1IE = 1; // Habilitamos interrupcin.

    T1CONbits.TON = 1; // Encendemos timer.

    while(1){}

    }

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    void __attribute__((__interrupt__, __shadow__)) _T1Interrupt(void){

    static unsigned int Cuenta;

    Cuenta=TMR1;

    IFS0bits.T1IF = 0; // Borramos flag.

    }

    Configuracion timer 32-bits.

    Mediante la combinacin de los timers de tipo B y C logramos un timers de 32-bits, en

    donde el timer tipo C es la palabra ms significativa (msw) y el timer tipo B de menor

    significancia (lsw).

    Cuando los timers estn configurados para trabajar a 32-bits nicamente los bits del registro

    de control (TxCON) del timer tipo B son utilizados, a excepcin del bit TSIDL los dems

    bits del timer tipo C son ignorados. Pero para el control de la interrupcin, se utilizan los bits

    de control (TxIE, TxIF y TxIP) del timer tipo C.

    Operacin de lectura y escritura.

    Para operaciones de lectura y escritura se utiliza un registro adicional llamado TMRyHLD

    asignado al timer tipo C (nicamente en operacin a 32-bits). Cuando se realiza una lectura,

    primero se debe leer el valor del timer tipo B (TMRx), para que el valor de TMRy (Timer

    tipo C) sea transferido a TMRyHLD para la posterior lectura. En cambio al realizar una

    escritura primero se debe establecer el valor de TMRyHLD para luego realizar la carga

    sobre el valor TMRx, lo cual genera que el valor pre-cargado a TMRyHLD sea transferido a

    TMRy.

    Ejemplo:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    main(void){

    T2CONbits.T32 = 1; // modo de 32-bits

    T2CONbits.TCS = 0; // Clock interno

    T2CONbits.TGATE = 1; // Mode Gate Habilitado, pin T2CK.-

    T2CONbits.TCKPS = 0b00 // Preescaler 1:1

    TMR3HLD = 0x00; // Borramos Timer3 (msw)

    TMR2 = 0x00; // Borramos timer2 (lsw)

    PR3 = 0x0002; // Fijamos periodo (msw)

    PR2 = 0x0000; // Fijamos periodo (lsw)

    IPC2bits.T3IP = 0x01; // Fijamos nivel de prioridad

    IFS0bits.T3IF = 0; // Borramos flag.

    IEC0bits.T3IE = 1; // Habilitamos interrupcin.

    T2CONbits.TON = 1; // Encendemos timer de 32-bits.

    }

    void __attribute__((__interrupt__, __shadow__)) _T3Interrupt(void){

    static unsigned long Cuenta;

    Cuenta=TMR2;

    Cuenta+= TMR3HLD*0x10000;

    IFS0bits.T3IF = 0; //Borramos flag.

    }

    Ejemplo modo temporizacin, interrupcin cada 500ms a 40 MIPS.

    /* ********* timers en C30 *************

    \Autor: Suky

    \Fecha: 07/01/10

    */

    #include

    _FOSCSEL(IESO_OFF & FNOSC_PRIPLL); // Oscilador primario + PLL

    _FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock y

    Fail-Safe Clock des-habilitados, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    void __attribute__((__interrupt__, __shadow__)) _T3Interrupt(void){

    LATBbits.LATB15=~LATBbits.LATB15; // Cambiamos de estado pin

    B15.-

    IFS0bits.T3IF = 0; //Borramos flag.

    }

    main(void){

    // Cristal de 4MHz y PLL trabajando a 40 MIPS.

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    AD1PCFGL=0xFFFF; // todos los pines digitales.-

    TRISB=0x0FFF; // Configuramos RB2-RB15 como salidas.-

    LATB=0xF000; // Todos los leds apagados.-

    T2CONbits.T32 = 1; // modo de 32-bits

    T2CONbits.TCS = 0; // Clock interno

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    T2CONbits.TGATE = 0; // Mode Gate deshabilitado.

    T2CONbits.TCKPS = 0b00; // Preescaler 1:1

    /* ** Debemos contar 20.000.000 ciclos y generar la interrupcin

    ** */

    PR3 = 0x0131; // Fijamos periodo (msw)

    PR2 = 0x2D00; // Fijamos periodo (lsw)

    IPC2bits.T3IP = 0x01; // Fijamos nivel de prioridad

    IFS0bits.T3IF = 0; // Borramos flag.

    IEC0bits.T3IE = 1; // Habilitamos interrupcin.

    TMR3HLD = 0x00; // Borramos Timer3 (msw)

    TMR2 = 0x00; // Borramos timer2 (lsw)

    T2CONbits.TON = 1; // Encendemos timer de 32-bits.

    while(1){}

    }

    Tambin podemos utilizar las funciones de las libreras que incluyen C30 para el manejo de

    perifricos. Documentacin sobre ella encontramos en \Microchip\MPLAB C30\docs\periph_lib . Para el control de de timers tenemos:

    Funciones: CloseTimerx CloseTimerxy ConfigIntTimerx ConfigIntTimerxy OpenTimerx OpenTimerxy ReadTimerx ReadTimerxy WriteTimerx WriteTimerxy

    Los parmetros disponibles para cada funcin estn bien detallados en la ayuda.

    /* ********* timers en C30 *************

    \Autor: Suky

    \Fecha: 07/12/09

    */

    #include

    /* ***************************************************************** */

    _FOSCSEL(IESO_OFF & FNOSC_PRIPLL); // Oscilador primario + PLL

    _FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock y

    Fail-Safe Clock des-habilitados, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    /* ***************************************************************** */

    #include

    /* ***************************************************************** */

    void __attribute__((__interrupt__, __shadow__)) _T3Interrupt(void){

    LATBbits.LATB15=~LATBbits.LATB15; // Cambiamos de estado pin

    B15.-

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    _T3IF = 0; //Borramos flag.

    }

    /* ***************************************************************** */

    main((int argc, char * argv[]){

    // Cristal de 4MHz y PLL trabajando a 40 MIPS.

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    while(_LOCK==0);

    AD1PCFGL=0xFFFF; // todos los pines digitales.-

    TRISB=0x0FFF; // Configuramos RB2-RB15 como salidas.-

    LATB=0xF000; // Todos los leds apagados.-

    OpenTimer23(T2_ON & T2_IDLE_STOP & T2_GATE_OFF & T2_PS_1_1 &

    T2_SOURCE_INT,0x01312D00);

    ConfigIntTimer23(T3_INT_PRIOR_1 & T3_INT_ON);

    WriteTimer23(0x00);

    while(1){}

    }

    #include

    _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx2

    & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR128 & WDTPS_PS32768);

    _CONFIG2( FNOSC_PRI & FCKSM_CSDCMD & POSCMOD_HS );

    #include

    /* ***************************************************************** */

    void __attribute__((__interrupt__, __shadow__)) _T3Interrupt(void){

    LATDbits.LATD8=~LATDbits.LATD8; // Cambiamos de estado pin F2.-

    _T3IF = 0; //Borramos flag.

    }

    int main (int argc, char * argv[]){

    TRISD=0xF0FF;

    OpenTimer23(T23_ON & T2_IDLE_STOP & T2_GATE_OFF & T2_PS_1_1 &

    T2_SOURCE_INT,0x004C4B40);

    ConfigIntTimer23(T3_INT_PRIOR_1 & T3_INT_ON);

    WriteTimer23(0x00);

    while(1){

    }

    }

    Que desperdicio hacer titilar un led con tremenda maquina pero es el precio de ir

    adquiriendo conocimientos de forma ordenada y no estamparnos contra la pared y no saber

    para donde correr.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Seleccin de pines de los perifricos.

    Esta caracterstica que implementa esta familia de microcontroladores esta enfocado a hacer

    mucho ms flexible la utilizacin de ellos, ms aun en microcontroladores de pocos pines.

    La seleccin de pines de los perifricos permite a los usuarios determinar que pines usar en

    una amplia gama de pines I/O. Al aumentar las opciones de patillas disponibles en un

    dispositivo en particular, podemos adaptar mejor el microcontrolador a la aplicacin, en

    lugar de adecuar la aplicacin al dispositivo.

    Los pines disponibles para seleccin dependen del microcontrolador particularmente. Estos

    pines incluyen la designacin RPn (Remappable peripheral y n indica el nmero)

    Los perifricos que pueden utilizar la seleccin de pines son nicamente digitales, estos

    incluyen las comunicaciones seriales (UART y SPI), entrada a clock externo de timers, pin

    para captura o comparacin y pines de interrupcin externa. Hay perifricos digitales que no

    pueden utilizar la multiplexin de pines por necesitar un hardware especial, como es el caso

    de la comunicacin I2C.

    Control de la seleccin de pines.

    La seleccin de pines se divide en pines que tienen la funcin de entrada y pines de salida.

    Para el mapeo de pines con la funcin de entrada se utiliza el registro RPINRx, que contiene

    un campo de 5-bits para seleccionar el pin RPx asociado al perifrico.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    En cambio la seleccin de pines con la funcin de entrada es inversa, con la utilizacin del

    registro RPORx se asigna un perifrico a un pin determinado. Adems tiene la opcin

    NULL (00000) que permite dejar desconectado el pin. (Sin seleccin)

    Durante la operacin normal del dispositivo, la operacin de escritura de los registros

    RPINRx y RPORX son deshabilitadas. Para desbloquear esta proteccin es necesario actuar

    sobre el bit IOLOCK (OSCCON), para ello es necesario realizar una secuencia de

    comandos.

    Escribir 0x46 en OSCCON Escribir 0x57 en OSCCON Borrar o setear bit IOLOCK en una sola operacin. Ejemplo de asignacin de pines:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    // Habilitamos escritura sobre registros RPINRx y RPORX.

    __builtin_write_OSCCONL(OSCCON & ~(0x40));

    RPINR18bits.U1RXR = 9; //Asignamos pin recepcin UART1 a RP9.-

    RPOR4bits. RP8R = 0b00011; // Asignamos RP8 al pin de transmisin UART1.

    // Bloqueamos escritura sobre registros RPINRx y RPORX.

    __builtin_write_OSCCONL(OSCCON |0x40);

    UART.

    El mdulo USART es utilizado para comunicacin serial con dispositivos perifricos o

    computadoras, utilizando protocolos tales copmo RS232, RS485, LIN o IrDA. Soporta

    control de flujo por hardware con los pines UxCTS y UxRTS, adems incluye

    decodificacin y codificacin IrDA.

    Las caractersticas de este mdulo son:

    Full-Duplex, 8 o 9 bits de datos. Para datos de 8 bits se puede asignar paridad par, impar o ninguna. 1 o 2 bits STOP. Auto-Baud Rate. Opcin de control de flujo mediante hardware, pines UxCTS y UxRTS. Generador de baud Rate con preescaler de 16-bits. Rango de Baud Rate de 10 Mbps a 38 bps a 40 MIPS. Buffer de 4 posiciones FIFO. Deteccin de error de paridad, error de cuadro y error de sobre-escritura. Soporte para modo de 9-bits con deteccin de direccin. Modo Loopback, devuelve inmediatamente el carcter recibido. Interrupcin por transmisin y recepcin. Codificador y decodificador IrDA. Soporte para bus LIN. Registros de control.

    Los registros utilizados para el control del mdulo UART son:

    UxMODE: o Habilita o deshabilita modulo UART.

    o Habilita o deshabilita codificacin y decodificacin IrDA.

    o Habilita o deshabilita pines UzRTS y UxCTS.

    o Configura el modo de operacin designado al pin UxRTS.

    o Configura la polaridad del pin UxRx.

    o Selecciona tipo de baud rate.

    o Selecciona nmero de datos, paridad y bit de Stop.

    UxSTA: o Selecciona el modo de interrupcin de transmisin.

    o Selecciona modo de interrupcin de recepcin.

    o Habilita o deshabilita transmisin.

    o Controles para modo de deteccin de direccionamiento.

    o Indicadores varios de estado de buffer de transmisin y recepcin, y errores.

    UxRXREG:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    o Guarda el dato recibido.

    UxTXREG: o Para cargar datos a transmitir.

    UxBRG: o Para determinar Baud Rate.

    Baud rate.

    Para determinar el baud rate tenemos 2 opciones, baud rate de alta velocidad BRGH=1 o de

    baja velocidad. Las ecuaciones asociadas son: (UxBRG de 16-bits)

    Configuracin de la USART.

    La USART usa el formato estndar NRZ, con un bit de Start, 8 o 9 bits de datos y 1 o 2 bits

    de Stop. Adems tenemos la posibilidad de configurar paridad como par, impar o ninguna.

    Esto lo configuramos mediante los bits PDSEL y STSEL. (UxMODE)

    El mdulo USART es habilitado mediante el seteo del bit UARTEN (UxMODE) y el bit

    UTXEN (UxSTA). Una vez habilitado, los pines UxTX y UxRX son configurados como

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    salida y entrada respectivamente, sustituyendo los valores seteados al TRIS correspondiente.

    Para deshabilitar el mdulo se debe borrar el bit UARTEN (UxMODE), al deshabilitarlo los

    pines se comportan con I/O adoptando la configuracin del TRIS. Adems se borra el buffer,

    el baud rate se restablece y tambin todos los bits de estados y errores son reseteados.

    Transmisin.

    El modo de funcionamiento es ms o menos similar a las otras familias, difiere en que hay 3

    modos de seleccin de la interrupcin:

    UTXISEL=00, el bit UxTXIF es seteado cuando un carcter es transferido desde el Buffer al registro UxTSR, esto implica que una posicin esta libre en el buffer.

    UTXISEL=01, el bit UxTXIF es seteado cuando el ultimo carcter es transferido desde el registro UxTSR, esto implica que todas las operaciones de transmisin han sido

    completadas.

    UTXISEL=10, el bit UxTXIF es seteado cuando el carcter es transferido al registro UxTSR y el buffer de transmisin est vacio.

    Pasos a seguir para la transmisin. 1. Inicializar Baud Rate cargando el valor apropiado a UxBRG.

    2. Setear el numero de bits de datos, numero de bits de Stop y seleccionar paridad.

    3. Si se trabajar con interrupciones seleccionar entre los 3 modos de operacin, habilitar

    mediante bit UxTIE y seleccionar nivel de prioridad (UxTXIP).

    4. Habilitar modulo UART setenado bit UARTEN.

    5. Habilitar transmisin setenado el bit UTXEN.

    6. El bit UxTXIF debe ser borrado por software en la rutina de servicio de interrupcin.

    7. Cargar el dato en el registro UxTXREG. Si se ha seleccionado transmisin de 9-bits se

    debe cargar un Word y sino un byte. Se pueden cargar datos hasta que el bit UxSTA sea

    seteado a uno indicando buffer lleno.

    Recepcin.

    Al igual que el bloque de transmisin, no hay nada de nuevo en el bloque de recepcin, el

    principio de funcionamiento se mantiene. Las interrupciones pueden configurarse de los

    siguientes modos:

    URXISEL=00 o 01. La interrupcin es generada cada vez que un dato es transferido desde el registro UxRSR al buffer de recepcin. Puede haber uno o ms

    caracteres en el buffer.

    URXISEL=10. La interrupcin es generada cuando un dato es transferido desde el registro UxRSR al buffer, y como resultado, el buffer tiene 3 de 4 caracteres.

    URXISEL=11. La interrupcin es generada cuando un dato es transferido desde el registro UxRSR al buffer, y como resultado, el buffer tiene 4 caracteres.

    Estos modos pueden ser cambiando durante la operacin. Tenemos los bits URXDA y

    UxRXIF que indican el estado del registro UxRXREG, y el bit RIDLE (UxSTA) que

    muestra el estado del registro UxRSR. Cuando el registro UxRSR esta vacio, el bit RIDLE

    est en 1.

    Pasos a seguir en la recepcin. 1. Inicializar Baud Rate.

    2. Configurar el nmero de bits de datos, Stop y determinar paridad.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    3. Si se utilizar interrupcin determinar el modo mediante los bits URXISEL, habilitar la

    interrupcin mendiante el bit UxRXIE, y establecer prioridad (UxRXIP).

    4. Habilitar modulo UART seteando bit UARTEN.

    5. Si la interrupcin no est habilitada, se debe recibir por poleo mediante el bit URXDA.

    Si se usa interrupcin, el bit UxRXIF debe ser borrado por software.

    6. Leer dato desde buffer, si se ha seleccionado trabajar con 9-bits se recibe un Word, sino

    un byte.

    Hay varias otras operaciones que se pueden realizar que dependern de la aplicacin a

    desarrollar, como transmisin a 9-bits, detectar automticamente direccin, modo Loopback,

    auto-Baud Rate, operacin con control de flujo mediante hardware, soporte infrarrojo,

    soporte LIN, ect. cuya informacin esta bien detallada en el datasheet del dispositivo.

    Ejemplo:

    Configuramos UART1 en 9600:8:N:1 para enviar un texto de inicializacin y luego por

    medio de interrupcin capturar dato enviado por PC y luego reenviar el mismo dato.

    Tambien debemos asignar los pines del periferico, en este caso Rx a RP9 y Tx a RP8.

    Configurando bits a bits:

    /* ********* UART en C30 *************

    \Autor: Suky

    \Fecha: 09/01/10

    */

    #include

    /* **

    **************************************************************************

    ********* ** */

    _FOSCSEL(IESO_OFF & FNOSC_PRI); // Oscilador primario

    _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock

    habilitad, Fail-Safe Clock des-habilitado, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    /* **

    **************************************************************************

    ********* ** */

    #include

    char DataUART;

    char KbhitUART;

    /* **

    **************************************************************************

    ********* ** */

    // Definciones para calculo de Baud Rate.-

    #define FCY 40000000 // MHz

    #define BAUDRATE 9600

    #define BRGHigh 1

    #if BRGHigh

    #define BRGVAL ((FCY/BAUDRATE)/4)-1

    #else

    #define BRGVAL ((FCY/BAUDRATE)/16)-1

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    #endif

    /* **

    **************************************************************************

    ********* ** */

    void __attribute__((__interrupt__, __shadow__)) _U1RXInterrupt(void){

    DataUART=getcUART1();

    KbhitUART=1;

    _U1RXIF=0; // Borramos flag.

    }

    /* **

    **************************************************************************

    ********* ** */

    main(void){

    const char Texto[]= "Probando comunicacin serial...\r\nPIC24HJ128GP502 xD

    ...\r\n";

    // Configuramos PLL para trabajar a 40 MIPS con Cristal de 4MHz.-

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    // Cambiamos clock para incorporar PLL.-

    __builtin_write_OSCCONH(0b011); // Indicamos cambio a clock

    primario con PLL.-

    __builtin_write_OSCCONL(0x01); // Iniciamos cambio.-

    while(OSCCONbits.OSWEN == 1) {}; // Esperamos a que se termine el

    cambio de clock.

    // Habilitamos escritura sobre registros RPINRx y RPORX.

    __builtin_write_OSCCONL(OSCCON & ~(0x40));

    RPINR18bits.U1RXR = 9; //Asignamos pin recepcin UART1 a RP9.-

    RPOR4bits. RP8R = 0b00011; // Asignamos RP8 al pin de transmisin

    UART1.

    // Bloqueamos escritura sobre registros RPINRx y RPORX.

    __builtin_write_OSCCONL(OSCCON |0x40);

    U1MODEbits.USIDL=1; // Al pasar al modo Sleep, apagar modulo.

    U1MODEbits.IREN=0; // Codificacion/decodificacion IrDA

    deshabilitado.

    U1MODEbits.RTSMD=1; // RTS en modo simple.

    U1MODEbits.UEN=0b00; // Tx/Rx habilitado, CTS/RTS deshabilitados.

    U1MODEbits.WAKE=0; // Wake-up deshabilitado.

    U1MODEbits.LPBACK=0; // Modo LoopBack deshabilitado.

    U1MODEbits.ABAUD=0; // Auto-Baud rate deshabilitado.

    U1MODEbits.URXINV=0; // Modo normal de pin RX, en reposo = 1.

    U1MODEbits.BRGH=BRGHigh; // Mode seleccionado en define.-

    U1MODEbits.PDSEL=0b00; // 8 bits- sin paridad.

    U1MODEbits.STSEL=0; // 1 bit de Stop.

    U1STAbits.UTXISEL1=1; // Interrupcion por transimision no usada.

    U1STAbits.UTXISEL0=1; // Interrupcion por transimision no usada.

    U1STAbits.UTXINV=0; // Pin Tx en reposo igual a 1.

    U1STAbits.UTXBRK=0; // Break deshabilitado.

    U1STAbits.URXISEL=0b00; // Interrumpir cuando se recibe un

    caracter.

    U1STAbits.ADDEN=0; // Auto-Address deshabilitado.

    U1STAbits.OERR=0; // Borramos bits de error por overflow.

    U1BRG =BRGVAL; // Baud Rate determinado en defines.

    IPC2bits.U1RXIP=0b01; // Fijamos nivel de prioridad.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    IFS0bits.U1RXIF=0; // Borramos flag.

    IEC0bits.U1RXIE=1; // habilitamos interrupcion por recepcin.

    U1MODEbits.UARTEN=1;// Encendemos modulo.

    U1STAbits.UTXEN=1; // Transmision habilitada.

    KbhitUART=0;

    putsUART1(Texto);

    while(1){

    if(KbhitUART==1){

    KbhitUART=0;

    putcUART1(DataUART);

    }

    }

    }

    Para el control de UART C30 dispone de la librera uart.h la cual tiene las siguientes

    funciones:

    BusyUARTx CloseUARTx ConfigIntUARTx DataRdyUARTx getsUARTx OpenUARTx [dsPIC30F] OpenUARTx [dsPIC33F/PIC24H] putsUARTx ReadUARTx o getcUARTx WriteUARTx o putcUARTx

    /* ********* UART en C30 *************

    \Autor: Suky

    \Fecha: 09/01/10

    */

    #include

    /* **

    **************************************************************************

    ********* ** */

    _FOSCSEL(IESO_OFF & FNOSC_PRI); // Oscilador primario

    _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock

    habilitad, Fail-Safe Clock des-habilitado, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    /* **

    **************************************************************************

    ********* ** */

    #include

    char DataUART;

    char KbhitUART;

    /* **

    **************************************************************************

    ********* ** */

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    // Definciones para calculo de Baud Rate.-

    #define FCY 40000000 // MHz

    #define BAUDRATE 9600

    #define BRGHigh 1

    #if BRGHigh

    #define BRGVAL ((FCY/BAUDRATE)/4)-1

    #else

    #define BRGVAL ((FCY/BAUDRATE)/16)-1

    #endif

    /* **

    **************************************************************************

    ********* ** */

    void __attribute__((__interrupt__, __shadow__)) _U1RXInterrupt(void){

    DataUART=getcUART1();

    KbhitUART=1;

    _U1RXIF=0; // Borramos flag.

    }

    /* **

    **************************************************************************

    ********* ** */

    main(void){

    const char Texto[]= "Probando comunicacin serial...\r\nPIC24HJ128GP502 xD

    ...\r\n";

    // Configuramos PLL para trabajar a 40 MIPS con Cristal de 4MHz.-

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    // Cambiamos clock para incorporar PLL.-

    __builtin_write_OSCCONH(0b011); // Indicamos cambio a clock

    primario con PLL.-

    __builtin_write_OSCCONL(0x01); // Iniciamos cambio.-

    while(OSCCONbits.OSWEN == 1) {}; // Esperamos a que se termine el

    cambio de clock.

    // Habilitamos escritura sobre registros RPINRx y RPORX.

    __builtin_write_OSCCONL(OSCCON & ~(0x40));

    RPINR18bits.U1RXR = 9; //Asignamos pin recepcin UART1 a RP9.-

    RPOR4bits. RP8R = 0b00011; // Asignamos RP8 al pin de transmisin

    UART1.

    // Bloqueamos escritura sobre registros RPINRx y RPORX.

    __builtin_write_OSCCONL(OSCCON |0x40);

    /* ** Utilizando las funciones definidas en C30 ** */

    OpenUART1(UART_EN & UART_IDLE_STOP & UART_IrDA_DISABLE &

    UART_MODE_SIMPLEX &

    UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK &

    UART_UXRX_IDLE_ONE &

    UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_BRGH_FOUR

    & UART_1STOPBIT,

    UART_INT_TX & UART_IrDA_POL_INV_ZERO &

    UART_SYNC_BREAK_DISABLED &

    UART_TX_ENABLE & UART_INT_RX_CHAR &

    UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR,

    BRGVAL);

    SetPriorityIntU1RX(1);

    EnableIntU1RX;

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    KbhitUART=0;

    putsUART1(Texto);

    while(1){

    if(KbhitUART==1){

    KbhitUART=0;

    putcUART1(DataUART);

    }

    }

    }

    #include

    _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx2

    & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR128 & WDTPS_PS32768);

    _CONFIG2( FNOSC_PRI & FCKSM_CSDCMD & POSCMOD_HS );

    #include

    char DataUART;

    char KbhitUART;

    /* ** ************************************************************** ** */

    // Definciones para calculo de Baud Rate.-

    #define FCY 10000000 // MHz

    #define BAUDRATE 9600

    #define BRGHigh 1

    #if BRGHigh

    #define BRGVAL ((FCY/BAUDRATE)/4)-1

    #else

    #define BRGVAL ((FCY/BAUDRATE)/16)-1

    #endif

    //__attribute__ ((__section__ (".text"), __space__(prog)))

    const char Texto[]= "Probando comunicacin serial...\r\nPIC24FJ128GA010

    xD ...\r\n";

    /* ** ************************************************************* ** */

    void __attribute__((__interrupt__, __shadow__)) _U2RXInterrupt(void){

    DataUART=getcUART2();

    KbhitUART=1;

    _U2RXIF=0; // Borramos flag.

    }

    /* ** ************************************************************** ** */

    int main (int argc, char * argv[]){

    /* ** Utilizando las funciones definidas en C30 ** */

    OpenUART2(UART_EN & UART_IDLE_STOP & UART_IrDA_DISABLE &

    UART_MODE_SIMPLEX &

    UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK &

    UART_UXRX_IDLE_ONE &

    UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_BRGH_FOUR &

    UART_1STOPBIT,

    0xFFFF & UART_IrDA_POL_INV_ZERO &

    UART_SYNC_BREAK_DISABLED &

    UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS

    & UART_RX_OVERRUN_CLEAR,

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    BRGVAL);

    ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR1 & UART_TX_INT_DIS &

    UART_TX_INT_PR0 );

    /*U2MODEbits.USIDL=1; // Al pasar al modo Sleep, apagar modulo.

    U2MODEbits.IREN=0; // Codificacion/decodificacion IrDA

    deshabilitado.

    U2MODEbits.RTSMD=1; // RTS en modo simple.

    U2MODEbits.UEN=0b00; // Tx/Rx habilitado, CTS/RTS deshabilitados.

    U2MODEbits.WAKE=0; // Wake-up deshabilitado.

    U2MODEbits.LPBACK=0; // Modo LoopBack deshabilitado.

    U2MODEbits.ABAUD=0; // Auto-Baud rate deshabilitado.

    U2MODEbits.RXINV=0; // Modo normal de pin RX, en reposo = 1.

    U2MODEbits.BRGH=BRGHigh; // Mode seleccionado en define.-

    U2MODEbits.PDSEL=0b00; // 8 bits- sin paridad.

    U2MODEbits.STSEL=0; // 1 bit de Stop.

    U2STAbits.UTXISEL1=1; // Interrupcion por transimision no usada.

    U2STAbits.UTXISEL0=1; // Interrupcion por transimision no usada.

    U2STAbits.UTXINV=0; // Pin Tx en reposo igual a 1.

    U2STAbits.UTXBRK=0; // Break deshabilitado.

    U2STAbits.URXISEL=0b00; // Interrumpir cuando se recibe un caracter.

    U2STAbits.ADDEN=0; // Auto-Address deshabilitado.

    U2STAbits.OERR=0; // Borramos bits de error por overflow.

    U2BRG =BRGVAL; // Baud Rate determinado en defines.

    IPC7bits.U2RXIP=0b01; // Fijamos nivel de prioridad.

    IFS1bits.U2RXIF=0; // Borramos flag.

    IEC1bits.U2RXIE=1; // habilitamos interrupcion por recepcin.

    U2MODEbits.UARTEN=1;// Encendemos modulo.

    U2STAbits.UTXEN=1; // Transmision habilitada.*/

    KbhitUART=0;

    putsUART2(Texto);

    while(1){

    if(KbhitUART==1){

    KbhitUART=0;

    putcUART2(DataUART);

    }

    }

    }

    Uso del printf en C30.

    Para utilizar printf en nuestros proyectos se debe agregar la librera stdio.h, pero adems se

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    debe inicializar el Heap Size, yendo a Project/Buil Options/Project, y en la solapa

    MPLAB LINK30 llenar el campo, yo he colocado 256.

    Notificacin de cambio de estado de pines.

    Los PIC24 disponen de la habilidad de generar una interrupcin en respuesta de cambio de

    estado en los pines seleccionados para ello. El nmero de pines disponibles para tal

    actividad depende del microcontrolador elegido.

    Se dispone de 4 registros para el control de la operacin, los registros CNEN1, CNEN2,

    CNPU1 y CNPU2. Los primeros dos registros contienen los bits CNxIE (Donde x indica el

    numero de pin) que son utilizados para asociar la interrupcin con el pin. En los registros

    CNPU1 y CNPU2 encontramos los bits CNxPUE utilizados para habilitar las resistencias

    pull-up internas a cada pin, de manera de ahorrarnos esta al utilizar por ejemplo teclados

    matriciales.

    Configuracin:

    1. Colocar los pines como entrada digital setenado los bits correspondientes en el TRISx.

    2. Habilitar la interrupcin para los pines seleccionados seteando los bits correspondientes

    en CNEN1 y CNEN2.

    3. Si se desea habilitar las resistencias pull-up internas setear los bits correspondientes en

    CNPU1 y CNPU2.

    4. Fijar prioridad de interrupcin usando los bits CNIP.

    5. Habilitar interrupcin seteando bit CNIE.

    Cuando la interrupcin ocurre, se debe leer el registro PORT asociado al pin necesario para

    detectar la condicin de desigualdad y preparar la lgica para detectar un prximo cambio.

    Interrupcin externa

    Tambin disponemos interrupcin por defeccin de flanco ascendente o descendente de un

    pin. El nmero de pines disponibles es como mximo 5 pero depende del dispositivo. Para

    seleccin del flanco de activacin de evento tenemos los bits INTxEP del registro

    INTCON2, adems de los bits INTxIP para configurar prioridad de interrupcin y

    INTxIE para habilitar dicha interrupcin. Los pines para trabajar con esta propiedad deben

    elegirse mediante la seleccin de pines de perifricos (PPS) excepto INT0 que en este caso

    es fijo en RB7.

    Funciones disponible en C30 para trabajar con notificacin de cambio de estado e

    interrupcin externa:

    CloseINTx ConfigINTx ConfigCNPullups ConfigIntCN

    Nota: Revisando las funciones vemos que para control de cambio solo se tiene en cuenta

    desde 0 hasta 23, pero este PIC tiene 24, 27, 29 y 30 As que nos utilizables, hay que

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    utilizar configuracin mediante bits.

    Ejemplo, leyendo un teclado matricial:

    /* ********* NC en C30 *************

    \Autor: Suky

    \Fecha: 12/01/10

    */

    #include

    /* ** ************************************************************** ** */

    _FOSCSEL(IESO_OFF & FNOSC_PRI); // Oscilador primario

    _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock

    habilitad, Fail-Safe Clock des-habilitado, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    /* ** ************************************************************* ** */

    #define FCY 40000000UL // Necesaria para delays y UART.

    #include

    #include

    #include

    /* ** ************************************************************** ** */

    // Definciones para calculo de Baud Rate.-

    #define BAUDRATE 9600

    #define BRGHigh 1

    #if BRGHigh

    #define BRGVAL ((FCY/BAUDRATE)/4)-1

    #else

    #define BRGVAL ((FCY/BAUDRATE)/16)-1

    #endif

    #define Col0 PORTBbits.RB12

    #define Col1 PORTBbits.RB13

    #define Col2 PORTBbits.RB14

    #define Col3 PORTBbits.RB15

    #define Fil0 LATBbits.LATB1

    #define Fil1 LATBbits.LATB0

    #define Fil2 LATAbits.LATA1

    #define Fil3 LATAbits.LATA0

    /* ** ************************************************************** ** */

    const char Teclas[17]={'1','2','3','A',

    '4','5','6','B',

    '7','8','9','C',

    '*','0','#','D'};

    char Tecla,KbhitTecla;

    /* ** ************************************************************** ** */

    void __attribute__((__interrupt__, __shadow__)) _CNInterrupt(void){

    volatile char i,j=0;

    __delay_ms(30);

    Fil0=1;Fil1=1;Fil2=1;Fil3=1;

    for(i=0;i

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    j++;

    if(!Col1) break;

    j++;

    if(!Col2) break;

    j++;

    if(!Col3) break;

    j++;

    }

    Fil0=0;Fil1=0;Fil2=0;Fil3=0;

    while((!Col0)|(!Col1)|(!Col2)|(!Col3));

    __delay_ms(30);

    if(j

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    _CNIP=1; // Prioridad en 1.

    _CNIE=1; // Habilitamos interrupcin.

    KbhitTecla=0;

    while(1){

    if(KbhitTecla){

    KbhitTecla=0;

    printf("Tecla:-> %c\r\n",Tecla);

    }

    }

    }

    Control LCD. Modo 4-bits o 3-pines ms registro de desplazamiento

    En este caso solo posteo una librera para manejo LCD compatible con Hitachi 44780 y que

    modificaciones hacer para usar printf para escribir en el LCD. La librera dispone de la

    posibilidad de trabajar en modo de 4-bits con R/W siempre y cuando se seleccionen pines

    tolerables a 5V para dispositivos de 3.3V o sin R/W. Tambin implementa el manejo del

    LCD mediante 3 pines y un registro de desplazamiento (4094, 74164, ect) todos estos modos

    se selecciona con 2 definiciones (USE_RW y USE_3PINES).

    Tiene implementada las siguientes funciones:

    Open_LCD(Tipo) o Tipo = LINEA_5X7,LINEA_5X10 o LINEAS_5X7

    BusyLCD(); WriteCmdLCD(cmd) putcLCD(data) .Con reconocimiento de caracteres especiales \f,\n putsLCD(*data) GotoxyLCD(x,y) Ejemplo:

    Modo 4 bits con R/W:

    Modo 3 pines y registro de desplazamiento:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Modificacin de funciones de bajo nivel de la librera stdio.h para re-direccionar salida de datos de printf.

    Podemos utilizar la funcin printf para formatear datos y enviar por puerto UART, SPI,

    CAN, I2C (Caso especial) y LCD entre otros ejemplos. Una forma fcil que encontr fue la

    siguiente:

    Agregar una variable externa a la funcin write.c (\Microchip\MPLAB C30\src\pic30) __OUT_PER que seleccionar que perifrico utilizar para la salida de datos. Esta variable la

    definimos en nuestro archivo principal y all controlaremos su valor.

    En el archivo write.c solo hacemos un switch para seleccionar los perifricos de salida de

    datos manteniendo la original sin hacer cambios mayores:

    extern int __OUT_PER;

    switch(__OUT_PER){

    case 0: // UART

    while ((ustatus->TRMT) ==0);

    *txreg = *(char*)buffer++;

    break;

    case 1: // LCD

    WriteDataLCD(*(char*)buffer++);

    break;

    case 2: // SPI

    break;

    case 3: // CAN

    break;

    }

    Tambin debemos agregar la definicin de la funcin externa utilizada, por ejemplo para el

    caso del LCD:

    extern void WriteDataLCD(char data);

    Y no debemos olvidarnos de agregar el archivo write.c al proyecto para que sea re-

    compilado y efectivizar los cambios. (Se adjunta write.c)

    Quedando la librera con la modificacin para usar printf en el envo de datos al LCD:

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    Ejemplo para un PIC24F: Ver que se cambia las funciones que realizan la configuracin

    de fuses. Se configura para oscilador HS sin PLL, por ejemplo 20 MHZ, 10MIPS.

    #include

    /* ** ***************************************************************** */

    _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx2

    & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR128 & WDTPS_PS32768);

    _CONFIG2( FNOSC_PRI & FCKSM_CSDCMD & POSCMOD_HS );

    /* ** ************************************************************** ** */

    //#define FCY 10000000UL

    #include "LCD_C30.h"

    #include

    #define LCD_rev 1.0

    int __OUT_PER=1;

    /* ** ************************************************************** ** */

    main(void){

    OpenLCD(LINEAS_5X7);

    printf("Probando LCD\n%C30 v:%1.1f",LCD_rev);

    while(1){}

    }

    Ejemplo para un PIC24H:

    /* ********* LCD en C30 *************

    \Autor: Suky

    \Fecha: 14/01/10

    */

    #include

    /* ** ************************************************************** ** */

    _FOSCSEL(IESO_OFF & FNOSC_PRI); // Oscilador primario

    _FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Conmutacin de Clock

    habilitad, Fail-Safe Clock des-habilitado, OSC2 Clout, Cristal XT.

    _FWDT(FWDTEN_OFF);// Watchdog des-habilitado.

    _FPOR(FPWRT_PWR2);// Power-on Reset 2ms.

    /* ** ************************************************************ ** */

    #include "LCD_C30.h"

    #include

    #define LCD_rev 1.0

    int __OUT_PER=1;

    /* ** ************************************************************** ** */

    main(void){

    // Configuramos PLL para trabajar a 40 MIPS con Cristal de 4MHz.-

    PLLFBD = 0x004E; // M=80.

    CLKDIV = 0x0000; //N1=2, N2=2.

    // Cambiamos clock para incorporar PLL.-

    __builtin_write_OSCCONH(0b011); // Indicamos cambio a clock

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    primario con PLL.-

    __builtin_write_OSCCONL(0x01); // Iniciamos cambio.-

    while(OSCCONbits.OSWEN == 1) {}; // Esperamos a que se termine el

    cambio de clock.

    AD1PCFGL=0xFFFF; // todos los pines digitales.-

    OpenLCD(LINEAS_5X7);

    printf("Probando LCD\n%Ucontrol v:%1.1f",LCD_rev);

    while(1){

    }

    }

    Libreras en anexo A.

    ANEXO A.

    Libreras para control de LCD:

    /*******************************************************************

    \file LCD_30.h

    \version: 1.0

    \author Suky.

    \web www.infopic.comlu.com

    \mail [email protected]

    \date 18/01/10

    *******************************************************************/

    #if defined(__dsPIC30F__)

    #include

    #elif defined(__dsPIC33F__)

    #include

    #elif defined(__PIC24H__)

    #include

    #elif defined(__PIC24F__)

    #include

    #endif

    #ifndef _LCDPIC24_H

    #define _LCDPIC24_H

    #warning "Se ha definido valor de FCY para realizacin de demoras!!!"

    #define FCY 10000000UL

    //#define FCY 2000000UL

    #include

    /* ** El siguiente modo no utiliza el PIN RW** */

    #define USE_3PINES // Se utiliza registro de desplazamiento

    para DATA[0..3] y RS.

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    /* ** Para no utilizar el PIN RW comentar la siguiente definicin ** */

    //#define USE_RW

    #ifndef USE_3PINES

    /* ** Pines tolerables a 5V para usar RW ** */

    #define DATA_PIN_7 LATBbits.LATB11

    #define DATA_PIN_6 LATBbits.LATB10

    #define DATA_PIN_5 LATBbits.LATB9

    #define DATA_PIN_4 LATBbits.LATB8

    #define READ_PIN_7 PORTBbits.RB11

    #define READ_PIN_6 PORTBbits.RB10

    #define READ_PIN_5 PORTBbits.RB9

    #define READ_PIN_4 PORTBbits.RB8

    #define TRIS_DATA_PIN_7 TRISBbits.TRISB11

    #define TRIS_DATA_PIN_6 TRISBbits.TRISB10

    #define TRIS_DATA_PIN_5 TRISBbits.TRISB9

    #define TRIS_DATA_PIN_4 TRISBbits.TRISB8

    #define E_PIN LATBbits.LATB2

    #define RS_PIN LATBbits.LATB0

    #ifdef USE_RW

    #define RW_PIN LATBbits.LATB1

    #endif

    #define TRIS_E TRISBbits.TRISB2

    #define TRIS_RS TRISBbits.TRISB0

    #ifdef USE_RW

    #define TRIS_RW TRISBbits.TRISB1

    #endif

    #else

    #define DATA_PIN LATBbits.LATB15

    #define CLOCK_PIN LATBbits.LATB14

    #define E_PIN LATBbits.LATB13

    #define TRIS_DATA TRISBbits.TRISB15

    #define TRIS_CLOCK TRISBbits.TRISB14

    #define TRIS_E TRISBbits.TRISB13

    #endif

    /* Definiciones generales */

    // Encendido display.

    #define D_ON 0x0C

    #define D_OFF 0x08

    #define CURSOR_ON 0x0E

    #define BLINK_ON 0x0F

    #define C_ON_BLINK 0x0D

    // Control.

    #define D_CLEAR 0x01

    #define SET_INIT 0x02

    /*;--- Modos de Entrada

    ; Incrementa Direccion, Display fijo 0x06

    ; Decrementa Direccion, Display fijo 0x04

    ; Incrementa Direccion, Cursor fijo 0x07

    ; Decrementa Direccion, Cursor fijo 0x05

    ;--- Corriemiento Cursor

    ; Cursor a la Izquierda 0x10

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    ; Cursor a la Derecha 0x14

    ; Display a la Izquierda 0x18

    ; Display a la Derecha 0x1C

    ;--- Fijar Sistema

    ; Bus 8 bits, 1 lnea, 5x7 0x30

    ; Bus 8 bits, 1 linea, 5x10 0x34

    ; Bus 8 bits, 2 lneas, 5x7 0x38

    ; Bus 4 bits, 1 lnea, 5x7 0x20

    ; Bus 4 bits, 1 linea, 5x10 0x24

    ; Bus 4 bits, 2 lneas, 5x7 0x28*/

    /* Definiciones para OpenLCD */

    #define LINEA_5X7 0b00000000 /* 5x7 characters, single line */

    #define LINEA_5X10 0b00000100 /* 5x10 characters */

    #define LINEAS_5X7 0b00001000 /* 5x7 characters, multiple line */

    /* Funciones */

    void OpenLCD(unsigned char LcdType) __attribute__ ((section

    (".libperi")));

    unsigned char BusyLCD(void) __attribute__ ((section (".libperi")));

    void WriteCmdLCD(unsigned char cmd) __attribute__ ((section

    (".libperi")));

    void WriteDataLCD(char data) __attribute__ ((section (".libperi")));

    #define putcLCD WriteDataLCD

    void putsLCD(char *buffer) __attribute__ ((section (".libperi")));

    void GotoxyLCD(unsigned char x,unsigned char y) __attribute__ ((section

    (".libperi")));

    #endif

    /*******************************************************************

    \file LCD_30.c

    \version: 1.0

    \author Suky.

    \web www.infopic.comlu.com

    \mail [email protected]

    \date 18/01/10

    ********************************************************************/

    #include "LCD_C30.h"

    unsigned char BusyLCD(void){

    #ifdef USE_RW

    DATA_PIN_7 = 0;

    DATA_PIN_6 = 0;

    DATA_PIN_5 = 0;

    DATA_PIN_4 = 0;

    TRIS_DATA_PIN_7 = 1;

    TRIS_DATA_PIN_6 = 1;

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    TRIS_DATA_PIN_5 = 1;

    TRIS_DATA_PIN_4 = 1;

    RW_PIN = 1;

    RS_PIN = 0;

    E_PIN=1;

    __delay_us(2);

    if(READ_PIN_7==1){

    E_PIN = 0;

    __delay_us(2);

    E_PIN = 1;

    __delay_us(2);

    E_PIN = 0;

    RW_PIN = 0;

    return 1;

    }else{

    E_PIN = 0;

    __delay_us(2);

    E_PIN = 1;

    __delay_us(2);

    E_PIN = 0;

    RW_PIN = 0;

    return 0;

    }

    #else

    __delay_ms(1);

    return 0;

    #endif

    }

    void WriteCmdLCD(unsigned char cmd){

    #ifdef USE_3PINES

    unsigned char i;

    unsigned char cmd_temp;

    #endif

    while(BusyLCD());

    #ifndef USE_3PINES

    #ifdef USE_RW

    RW_PIN = 0;

    #endif

    RS_PIN = 0;

    TRIS_DATA_PIN_7 = 0;

    TRIS_DATA_PIN_6 = 0;

    TRIS_DATA_PIN_5 = 0;

    TRIS_DATA_PIN_4 = 0;

    DATA_PIN_7 = (unsigned int)((cmd & 0x80)>>7);

    DATA_PIN_6 = (unsigned int)((cmd & 0x40)>>6);

    DATA_PIN_5 = (unsigned int)((cmd & 0x20)>>5);

    DATA_PIN_4 = (unsigned int)((cmd & 0x10)>>4);

    #else

    cmd_temp=(cmd>>4); // Rs es bit 4

    for(i=0;i>7);

    cmd_temp

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    __delay_us(1);

    CLOCK_PIN=0;

    }

    #endif

    Nop();

    E_PIN = 1;

    __delay_us(2);

    E_PIN = 0;

    #ifndef USE_3PINES

    DATA_PIN_7 = (unsigned int)((cmd & 0x08)>>3);

    DATA_PIN_6 = (unsigned int)((cmd & 0x04)>>2);

    DATA_PIN_5 = (unsigned int)((cmd & 0x02)>>1);

    DATA_PIN_4 = (unsigned int)(cmd & 0x01);

    #else

    cmd_temp=(cmd&0x0F); // Rs es bit 4

    for(i=0;i>7);

    cmd_temp

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    E_PIN = 0;

    TRIS_DATA = 0;

    TRIS_CLOCK = 0;

    TRIS_E = 0;

    for(i=0;i7);

    temp

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    while(BusyLCD());

    switch(data){

    case '\f':

    WriteCmdLCD(0x01);

    break;

    case '\n':

    GotoxyLCD(1,2);

    break;

    default:

    #ifndef USE_3PINES

    #ifdef USE_RW

    RW_PIN = 0;

    #endif

    RS_PIN = 1;

    TRIS_DATA_PIN_7 = 0;

    TRIS_DATA_PIN_6 = 0;

    TRIS_DATA_PIN_5 = 0;

    TRIS_DATA_PIN_4 = 0;

    DATA_PIN_7 = (unsigned int)((data & 0x80)>>7);

    DATA_PIN_6 = (unsigned int)((data & 0x40)>>6);

    DATA_PIN_5 = (unsigned int)((data & 0x20)>>5);

    DATA_PIN_4 = (unsigned int)((data & 0x10)>>4);

    #else

    data_temp=(data>>4); // Rs es bit 4

    data_temp|=0x10;

    for(i=0;i>7);

    data_temp3);

    DATA_PIN_6 = (unsigned int)((data & 0x04)>>2);

    DATA_PIN_5 = (unsigned int)((data & 0x02)>>1);

    DATA_PIN_4 = (unsigned int)(data & 0x01);

    #else

    data_temp=(data&0x0F); // Rs es bit 4

    data_temp|=0x10;

    for(i=0;i>7);

    data_temp

  • Autor: Suky Mail: [email protected] Web: www.micros-designs.com.ar

    __delay_u