PicManía by RedRaven
 

Búsqueda personalizada

El Rincón del C30
Ideas, Técnicas y Rutinas

 

     El lenguaje C es el que uso por defecto para el 90% de mis programas. Aquí os muestro algunos ejemplos de cómo hacer cosas con este idioma. Todos ejemplos que se muestran en esta sección se han realizado usando el C30 (v3.0.2) de Microchip para PIC24H y dsPIC.
Índice General:
 
  Lo Hiperbásico:
 
  • WINK Por donde todo programador que se precie debe empezar.
  • WINK2 Igual que el anterior pero con los Led's uno a uno.
  • USART Añadiendo el mas famoso canal de comunicaciones.
  • WINK3 En esta ocasión usando la interrupción del Timer1
  • ADC & LEDS Un Vúmetro con el potenciómetro y los Leds de la Explorer 16
 
 
  Bailando con Gráficos: La Librería Gráfica de Microchip.
 
  • Test1 Un botón que incrementa una variable.
  • Test2 KEYPAD que genera mensajes en las pantalla.
 
 
 


 

Nota1: El Micro usado es el dsPIC33FJ256GP710 sobre la tarjeta de desarrollo Explorer-16
 

 

 


WINK Por donde todo programador que se precie debe empezar.
 

   Este ha sido mi primer programa para un dsPIC. Es un extracto del ejemplo que el mismo C30 trae consigo al instalarlo. Sólo le he añadido la rutina de delay para conseguir el espaciado necesario de los parpadeos del Led. Esta rutina delay (delay.h y delay.c) también la he sacado de otros ejemplos que acompañan al compilador, de todas formas os la pongo completa para que no tengáis que buscar nada de nada.

 
     
 

/**********************************************************************
* © 2007 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_wink.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* Wink Led Port A
*
* C30 Optimization Level: -O1
*
**********************************************************************/

#include "p33FJ256GP710.h"
#include "delay.h"

_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
_FWDT(FWDTEN_OFF);

int main(void){

  //The settings below set up the oscillator and PLL for 16 MIPS
  PLLFBD = 0x00A0;
  CLKDIV = 0x0048;

  /* set LEDs (D3-D10/RA0-RA7) drive state low */
  LATA = 0xFF00;
  /* set LED pins (D3-D10/RA0-RA7) as outputs */
  TRISA = 0xFF00;

  /* Infinite Loop */
  while(1){

    // All PORTA to ON
    LATA = 0xFFFF;
    // Wait 0.5 seconds
    Delay(Delay_5mS_Cnt * 100);
    // All PORTA to OFF
    LATA = 0xFF00;
    // Wait 0.5 seconds
    Delay(Delay_5mS_Cnt * 100);
  };
}
 

 
     
 
 
 
  delay.c  
  /*********************************************************************
*
* Simple Delay Routines
*
*********************************************************************
* FileName: delay.c
* Dependencies: delay.h
* Processor: dsPIC33F
* Complier: MPLAB C30 v2.01.00 or higher
*
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the “Company”) for its dsPIC30F Microcontroller is intended
* and supplied to you, the Company’s customer, for use solely and
* exclusively on Microchip's dsPIC30F Microcontroller products.
* The software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Richard Fischer 7/14/05 Initial release for LCD support
* Priyabrata Sinha 1/27/06 Ported to non-prototype devices
*
********************************************************************/

#include "delay.h"

unsigned int temp_count;

void Delay(unsigned int delay_count){

  temp_count = delay_count +1;
  asm volatile("outer: dec _temp_count");
  asm volatile("cp0 _temp_count");
  asm volatile("bra z, done");
  asm volatile("do #3200, inner" );
  asm volatile("nop");
  asm volatile("inner: nop");
  asm volatile("bra outer");
  asm volatile("done:");
}


void Delay_Us(unsigned int delayUs_count){

  temp_count = delayUs_count +1;
  asm volatile("outer1: dec _temp_count");
  asm volatile("cp0 _temp_count");
  asm volatile("bra z, done1");
  asm volatile("do #1500, inner1" );
  asm volatile("nop");
  asm volatile("inner1: nop");
  asm volatile("bra outer1");
  asm volatile("done1:");
}
 
 
     
 
 
 
  delay.h  
  //#define Fcy 14754600
#define Fcy 16000000

void Delay( unsigned int delay_count );
void Delay_Us( unsigned int delayUs_count );

#define Delay200uS_count (Fcy * 0.0002) / 1080
#define Delay_1mS_Cnt (Fcy * 0.001) / 2950
#define Delay_2mS_Cnt (Fcy * 0.002) / 2950
#define Delay_5mS_Cnt (Fcy * 0.005) / 2950
#define Delay_15mS_Cnt (Fcy * 0.015) / 2950
#define Delay_1S_Cnt (Fcy * 1) / 2950
 
 
     


WINK2 Igual que el anterior pero con los Led's uno a uno
 

   En el anterior ejemplo activábamos y desactivábamos todo el PORTA completo, hacíamos parpadear todos los Led's conectados en la Explorer-16 a dicho puerto. En este nuevo programa lo hacemos pero uno a uno, comenzando por el PORTA.0 y acabando en el PORTA.7
 

   El único truco que hemos utilizado es inicializar una variable a 1 e ir desplazando ese 1 hacia la izquierda antes de sacar el resultado por el PORTA.

 
     
  /**********************************************************************
* © 2007 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_wink2.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* Wink Led Each Port A
*
* C30 Optimization Level: -O1
*
**********************************************************************/

#include "p33FJ256GP710.h"
#include "delay.h"

_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
_FWDT(FWDTEN_OFF);

int main(void){

  unsigned int fA;

  //The settings below set up the oscillator and PLL for 16 MIPS
  PLLFBD = 0x00A0;
  CLKDIV = 0x0048;

  /* set LEDs (D3-D10/RA0-RA7) drive state low */
  LATA = 0xFF00;
  /* set LED pins (D3-D10/RA0-RA7) as outputs */
  TRISA = 0xFF00;

  fA=0x0001;

  /* Infinite Loop */
  while(1){

    // Each PORTA to ON
    LATA = 0xFF00 +(fA);
    fA = (fA << 1);
    if(fA==0x0100){
      fA = 0x0001;
    }
    // Wait 0.5 seconds
    Delay(Delay_5mS_Cnt * 10);
    // All PORTA to OFF
    LATA = 0xFF00;
    // Wait 0.5 seconds
    Delay(Delay_5mS_Cnt * 10);
  };
}
 
     


USART Añadiendo el mas famoso canal de comunicaciones.
 
   Otro pasito adelante. Esta vez le toca a la USART leyendo y escribiendo por el canal serie.
 
   Aquí tenéis un programita que primero se presenta a si mismo, como todo dsPIC de buena familia debe hacer, y después se pone a la escucha del canal serie (por la USART2 que es la que el hardware de la Explorer-16 tiene el MAX232 conectado) y devuelve por ese mismo canal lo que reciba, hace el eco.
 
     
  /**********************************************************************
* © 2007 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_usart.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* Wink Led Port A
*
* C30 Optimization Level: -O1
*
*********************************************************************
* The Processor starts with the Internal oscillator without PLL enabled
* and then the Clock is switched to PLL Mode.
*********************************************************************/
#include <p33FJ256GP710.h>
#include <delay.h>

_FOSCSEL(FNOSC_FRC); // Internal FRC oscillator
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE); // Clock Switching is enabled and Fail Safe Clock Monitor is disabled
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystanl

char mytext[] ="dsPIC33FJ256GP710 en línea¡\r\nHello TODOPIC (World)\r\n>\0";

void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void){
  // Lo que recibo vía UART2 lo pongo en el PORTA ...
  LATA = U2RXREG;
  // ... y lo devuelvo como Echo filtrando el 0x0D para añadir 0x0A
  U2TXREG = U2RXREG;
  if(U2RXREG==0x0D){
    U2TXREG = 0x0A;
  }
  IFS1bits.U2RXIF = 0;
}

void __attribute__((interrupt, no_auto_psv)) _U2TXInterrupt(void){
  IFS1bits.U2TXIF = 0;
}

void InitClock(){
  PLLFBD = 38; // M = 40
  CLKDIVbits.PLLPOST = 0; // N1 = 2
  CLKDIVbits.PLLPRE = 0; // N2 = 2
  OSCTUN = 0;
  RCONbits.SWDTEN = 0;
  // Clock switch to incorporate PLL
  __builtin_write_OSCCONH(0x01); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
  __builtin_write_OSCCONL(0x01); // Start clock switching while (oscconbits.cOSC != 0b001); Wait for Clock switch to occur
  while(OSCCONbits.LOCK != 1) {};
}

void InitUART2(){
  // This is an EXAMPLE, so brutal typing goes into explaining all bit sets
  // The HPC16 board has a DB9 connector wired to UART2, so we will
  // be configuring this port only
  // configure U2MODE
  U2MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
  //U2MODEbits.notimplemented; // Bit14
  U2MODEbits.USIDL = 0; // Bit13 Continue in Idle
  U2MODEbits.IREN = 0; // Bit12 No IR translation
  U2MODEbits.RTSMD = 0; // Bit11 Simplex Mode
  //U2MODEbits.notimplemented; // Bit10
  U2MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
  U2MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here)
  U2MODEbits.LPBACK = 0; // Bit6 No Loop Back
  U2MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
  U2MODEbits.URXINV = 0; // Bit4 IdleState = 1 (for dsPIC)
  U2MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
  U2MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
  U2MODEbits.STSEL = 0; // Bit0 One Stop Bit
  // Load a value into Baud Rate Generator. Example is for 9600.
  // See section 19.3.1 of datasheet.
  // U2BRG = (Fcy/(16*BaudRate))-1
  // U2BRG = (37M/(16*9600))-1
  // U2BRG = 240
  U2BRG = 240; // 40Mhz osc, 9600 Baud
  // Load all values in for U1STA SFR
  U2STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
  U2STAbits.UTXINV = 0; //Bit14 N/A, IRDA config
  U2STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
  //U2STAbits.notimplemented = 0; //Bit12
  U2STAbits.UTXBRK = 0; //Bit11 Disabled
  U2STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
  U2STAbits.UTXBF = 0; //Bit9 *Read Only Bit*
  U2STAbits.TRMT = 0; //Bit8 *Read Only bit*
  U2STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
  U2STAbits.ADDEN = 0; //Bit5 Address Detect Disabled
  U2STAbits.RIDLE = 0; //Bit4 *Read Only Bit*
  U2STAbits.PERR = 0; //Bit3 *Read Only Bit*
  U2STAbits.FERR = 0; //Bit2 *Read Only Bit*
  U2STAbits.OERR = 0; //Bit1 *Read Only Bit*
  U2STAbits.URXDA = 0; //Bit0 *Read Only Bit*
  IPC7 = 0x4400; //Mid Range Interrupt Priority level, no urgent reason
  IFS1bits.U2TXIF = 0; //Clear the Transmit Interrupt Flag
  IEC1bits.U2TXIE = 1; //Enable Transmit Interrupts
  IFS1bits.U2RXIF = 0; //Clear the Recieve Interrupt Flag
  IEC1bits.U2RXIE = 1; //Enable Recieve Interrupts
  U2MODEbits.UARTEN = 1; //And turn the peripheral on
  U2STAbits.UTXEN = 1;
}

void InitPorts() {
  AD1PCFGHbits.PCFG23 = 1; // This is important. RA7 is muxxed with AN23,
  // So we need to config the pin as DIGITAL
  TRISA = 0x0080; // only 0th bit needs be output. A7 is input
}

void putUART2( char c){
  while ( U2STAbits.UTXBF); // wait while Tx buffer full
  U2TXREG = c;
}

void putsUART2( char *s){
  unsigned int i=0;
  while(s[i]) // loop until *s == ‘\0’, end of string
  putUART2(s[i++]); // send the character and point to the next one
}


int main(void){

  InitClock(); // This is the PLL settings
  InitUART2(); // Initialize UART2 for 9600,8,N,1 TX/RX
  InitPorts(); // LEDs outputs

  Delay(Delay_5mS_Cnt * 100);
  putsUART2(mytext);

  while(1) { // The ever versatile Infinite Loop! Do Nothing
  }
}
 
 
     
 

 


WINK3 Haciendo uso de la Interrupción del Timer1
 

   En este nuevo ejemplo vamos ha hacer parpadear nuestro Led pero haciendo uso de la interrupción por desbordamiento del Timer1. Configuramos el Timer1 y vamos acumulando desbordamientos hasta llegar a 500, en ese momento reiniciamos la cuenta y conmutamos (toggle) el estado del Led.

 
  main_wink_int_timer1.c  
   
/**********************************************************************
* © 2007 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_wink_int_timer1.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* Wink Led Port A
*
* C30 Optimization Level: -O1
*
*********************************************************************
* The Processor starts with the Internal oscillator without PLL enabled
* and then the Clock is switched to PLL Mode.
*********************************************************************/
#include <p33FJ256GP710.h>

_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT); // Clock Switching Enabled and Fail Safe Clock Monitor is disabled
                                                // OSC2 Pin Function: OSC2 is Clock Output
                                                // Primary Oscillator Mode: XT Crystal
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software

unsigned int Count;

/* ISR ROUTINE FOR THE TIMER1 INTERRUPT */

void __attribute__((interrupt,no_auto_psv)) _T1Interrupt( void ){

   IFS0bits.T1IF = 0;
   T1CONbits.TON = 0;
   Count++;
   if(Count == 500){
      Count = 0;
      LATAbits.LATA1 = ~LATAbits.LATA1;
   }
   TMR1 = 0;
   T1CONbits.TON = 1; // reset Timer 1 interrupt flag
}

void InitClock(void){

   PLLFBD = 38; // M = 40
   CLKDIVbits.PLLPOST = 0; // N1 = 2
   CLKDIVbits.PLLPRE = 0; // N2 = 2
   OSCTUN = 0;
   RCONbits.SWDTEN = 0;
   // Clock switch to incorporate PLL
   __builtin_write_OSCCONH(0x01); // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
   __builtin_write_OSCCONL(0x01); // Start clock switching while (oscconbits.cOSC != 0b001); Wait for Clock switch to occur
   while(OSCCONbits.LOCK != 1) {};
}

void Init_Timer1(void){

   T1CON         = 0; // Timer reset
   IFS0bits.T1IF = 0; // Reset Timer1 interrupt flag
   IPC0bits.T1IP = 6; // Timer1 Interrupt priority level=4
   IEC0bits.T1IE = 1; // Enable Timer1 interrupt
   TMR1= 0x0000;
   PR1 = 0xFFFF;      // Timer1 period register = ?????
   T1CONbits.TON = 1; // Enable Timer1 and start the counter
}

int main(void){

   RCONbits.SWDTEN=0; // Disable Watch Dog Timer
   InitClock(); // This is the PLL settings
   /*Initialize the Ports All PORTA Output*/
   TRISA = 0x0000;
   LATA = 0x0000;
   PORTA = 0x0000;
   /*Initialize Timer 1 for Period Interrupts*/
   Init_Timer1();

   while(1){
   };
}

 
 
     


ADC & LEDS Un Vúmetro con el potenciómetro y los Leds de la Explorer 16
 

   Otro primer paso más. Ahora le toca al conversor AD del dsPIC. En este ejemplo utilizamos el Potenciómetro conectado a RA5 (el cursor) y sus extremos entre Vdd y Vss.

   Vamos a realizar de forma continua la conversión y vamos a implementar una especie de VUmeter con los 8 leds del PORTA. Con el POT el extremo de Vss apagaremos todos los Leds y en el extremo contrario, a Vdd, los encenderemos todos, con los distintos puntos intermedios encendiendo tantos leds como le toquen.

   En este ejemplo configuramos la conversión AD, activamos la Interrupción de dicha conversión y no utilizamos el DMA. O sea lo mas simple posible, que ya habrá tiempo para complicarse la vida.
 

     
  /
/**********************************************************************
* © 2007 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_adc_volts_for_leds.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* Wink Led Port A
*
* C30 Optimization Level: -O1
*
**********************************************************************/

#include "p33FJ256GP710.h"
#include "delay.h"

_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
_FWDT(FWDTEN_OFF);


volatile unsigned int volts_value=0;
volatile unsigned int flag_volts_value=0;


void init_clock(void){

    //The settings below set up the oscillator and PLL for 16 MIPS
    PLLFBD = 0x00A0;
    CLKDIV = 0x0048;
}

void init_leds(void){

    unsigned int i;

    LATA = 0xFF00;
    TRISA = 0xFF00;

    for(i=0; i<3; i++){
        LATA = 0xFFFF;
        Delay(Delay_5mS_Cnt * 20);
        LATA = 0xFF00;
        Delay(Delay_5mS_Cnt * 20);
    }

}

void init_ADC( void ){

    /* set port configuration here */
    AD1PCFGLbits.PCFG5 = 0; // ensure AN5/RB5 is analog (Analog Pot)
    /* set channel scanning here, auto sampling and convert, with default read-format mode */
    AD1CON1 = 0x00E4;
    /* select 12-bit, 1 channel ADC operation */
    AD1CON1bits.AD12B = 1;
    /* No channel scan for CH0+, Use MUX A, SMPI = 1 per interrupt, Vref = AVdd/AVss */
    AD1CON2 = 0x0000;
    /* Set Samples and bit conversion time */
    AD1CON3 = 0x032F;
    /* set channel scanning here for AN5 */
    AD1CSSL = 0x0000;
    /* channel select AN5 */
    AD1CHS0 = 0x0005;
    /* reset ADC interrupt flag */
    IFS0bits.AD1IF = 0;
    /* enable ADC interrupts, disable this interrupt if the DMA is enabled */
    IEC0bits.AD1IE = 1;
    /* turn on ADC module */
    AD1CON1bits.ADON = 1;
}

void __attribute__((interrupt,no_auto_psv)) _ADC1Interrupt(void){

    if(flag_volts_value==0){
        volts_value = ADC1BUF0; // Save off the RP5 Potentiometer data
        flag_volts_value=1; // set flag to update Leds
    }
    IFS0bits.AD1IF = 0; // reset ADC interrupt flag
}


void volts_value_to_leds(void){


    unsigned int scala,leds;

    scala = (unsigned int) volts_value * 0x0007 / 0x0C00;
    leds = scala;

    LATA = 0xFF00;
    if(leds>0) LATA += 0b00000001;
    if(leds>1) LATA += 0b00000010;
    if(leds>2) LATA += 0b00000100;
    if(leds>3) LATA += 0b00001000;
    if(leds>4) LATA += 0b00010000;
    if(leds>5) LATA += 0b00100000;
    if(leds>6) LATA += 0b01000000;
    if(leds>7) LATA += 0b10000000;
}


int main(void){


    RCONbits.SWDTEN=0; // Disable Watch Dog Timer

    init_clock();
    init_leds();
    init_ADC();


    /* Infinite Loop */
    while(1){
        if(flag_volts_value==1){
            flag_volts_value=0;
            volts_value_to_leds();
        }
    };
}
 
 
     


LCD "Hello World" El LCD mínimo.
 

   Bueno, continuamos con nuestras pruebas. Ahora el mas simple "Hello Word" en el LCD. Para ello necesitamos los módulos lcd.c y sus prototipos en lcd.h que adjunto mas abajo.
 

  main_lcd_hello_world.c  
 
/**********************************************************************
* © 2007 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_lcd_hello_world.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* Present "Hello World" message
*
* C30 Optimization Level: -O1
*
**********************************************************************/

#include "p33FJ256GP710.h"
#include "lcd.h"

_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
_FWDT(FWDTEN_OFF);

int main(void){

  char mytext1[] = " dsPIC33F - LCD ";
  char mytext2[] = " Hello World ";

  char *pText1=&mytext1[0];
  char *pText2=&mytext2[0];

  //The settings below set up the oscillator and PLL for 16 MIPS
  PLLFBD = 0x00A0;
  CLKDIV = 0x0048;
  // Initialize LCD Display
  Init_LCD();
  // Hellow World message
  home_clr();
  puts_lcd(pText1,sizeof(mytext1)-1);
  line_2();
  puts_lcd(pText2,sizeof(mytext2)-1);
  // Infinite Loop
  while(1){};
}

 
 
     
 
 
  lcd.c  
 
/**********************************************************************
* © 2006 Microchip Technology Inc.
*
* FileName: lcd.c
* Dependencies: p33FJ256GP710.h
* lcd.h
* delay.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* SOFTWARE LICENSE AGREEMENT:
* Microchip Technology Inc. (“Microchip”) licenses this software to you
* solely for use with Microchip dsPIC® digital signal controller
* products. The software is owned by Microchip and is protected under
* applicable copyright laws. All rights reserved.
*
* SOFTWARE IS PROVIDED “AS IS.” MICROCHIP EXPRESSLY DISCLAIMS ANY
* WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP
* BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
* DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
* ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
*
* REVISION HISTORY:
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Author Date Comments on this revision
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Richard Fischer 07/14/05 Explorer 16 board LCD support
* Priyabrata Sinha 01/27/06 Ported to non-prototype devices
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ADDITIONAL NOTES:
*
**********************************************************************/

#include "p33FJ256GP710.h"
#include "lcd.h"
#include "delay.h"


/*
For Explorer 16 board, here are the data and control signal definitions
RS -> RB15
E -> RD4
RW -> RD5
DATA -> RE0 - RE7
*/

// Control signal data pins
#define RW LATDbits.LATD5 // LCD R/W signal
#define RS LATBbits.LATB15 // LCD RS signal
#define E LATDbits.LATD4 // LCD E signal

// Control signal pin direction
#define RW_TRIS TRISDbits.TRISD5
#define RS_TRIS TRISBbits.TRISB15
#define E_TRIS TRISDbits.TRISD4

// Data signals and pin direction
#define DATA LATE // Port for LCD data
#define DATAPORT PORTE
#define TRISDATA TRISE // I/O setup for data Port



/****************************************************************************/
/***** LCD SUBROUTINE *****/

void Init_LCD( void ) // initialize LCD display
{
  // 15mS delay after Vdd reaches nnVdc before proceeding with LCD initialization
  // not always required and is based on system Vdd rise rate
  Delay(Delay_15mS_Cnt); // 15ms delay

  /* set initial states for the data and control pins */
  LATE &= 0xFF00;
  RW = 0; // R/W state set low
  RS = 0; // RS state set low
  E = 0; // E state set low

  /* set data and control pins to outputs */
  TRISE &= 0xFF00;
  RW_TRIS = 0; // RW pin set as output
  RS_TRIS = 0; // RS pin set as output
  E_TRIS = 0; // E pin set as output

  /* 1st LCD initialization sequence */
  DATA &= 0xFF00;
  DATA |= 0x0038;
  E = 1;
  Nop();
  Nop();
  Nop();
  E = 0; // toggle E signal
  Delay(Delay_5mS_Cnt); // 5ms delay

  /* 2nd LCD initialization sequence */
  DATA &= 0xFF00;
  DATA |= 0x0038;
  E = 1;
  Nop();
  Nop();
  Nop();
  E = 0; // toggle E signal
  Delay_Us( Delay200uS_count ); // 200uS delay

  /* 3rd LCD initialization sequence */
  DATA &= 0xFF00;
  DATA |= 0x0038;
  E = 1;
  Nop();
  Nop();
  Nop();
  E = 0; // toggle E signal
  Delay_Us( Delay200uS_count ); // 200uS delay

  lcd_cmd( 0x38 ); // function set
  lcd_cmd( 0x0C ); // Display on/off control, cursor blink off (0x0C)
  lcd_cmd( 0x06 ); // entry mode set (0x06)
}


void lcd_cmd( char cmd ) // subroutiune for lcd commands
{
  // TRISD &= 0xFF00; // ensure RD0 - RD7 are outputs
  DATA &= 0xFF00; // prepare RD0 - RD7
  DATA |= cmd; // command byte to lcd
  RW = 0; // ensure RW is 0
  RS = 0;
  E = 1; // toggle E line
  Nop();
  Nop();
  Nop();
  E = 0;
  Delay(Delay_5mS_Cnt); // 5ms delay
}


void lcd_data( char data ) // subroutine for lcd data
{
  // TRISD &= 0xFF00; // ensure RD0 - RD7 are outputs
  RW = 0; // ensure RW is 0
  RS = 1; // assert register select to 1
  DATA &= 0xFF00; // prepare RD0 - RD7
  DATA |= data; // data byte to lcd
  E = 1;
  Nop();
  Nop();
  Nop();
  E = 0; // toggle E signal
  RS = 0; // negate register select to 0
  Delay_Us( Delay200uS_count ); // 200uS delay
  Delay_Us( Delay200uS_count ); // 200uS delay
}

void puts_lcd( unsigned char *data, unsigned int count )
{
  while ( count )
  {
    lcd_data( *data++ );
    count --;
  }
}
 
 
     
 
 
  lcd.h  
  /
/**********************************************************************
* © 2006 Microchip Technology Inc.
*
* FileName: lcd.h
* Dependencies: none
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* SOFTWARE LICENSE AGREEMENT:
* Microchip Technology Inc. (“Microchip”) licenses this software to you
* solely for use with Microchip dsPIC® digital signal controller
* products. The software is owned by Microchip and is protected under
* applicable copyright laws. All rights reserved.
*
* SOFTWARE IS PROVIDED “AS IS.” MICROCHIP EXPRESSLY DISCLAIMS ANY
* WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP
* BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
* DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
* ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
*
* REVISION HISTORY:
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Author Date Comments on this revision
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Richard Fischer 07/14/05 Explorer 16 board LCD function support
* Priyabrata Sinha 01/27/06 Ported to non-prototype devices
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ADDITIONAL NOTES:
*
**********************************************************************/


/****** LCD FUNCTION PROTOYPES ******/

void Init_LCD( void ); // initialize display
void lcd_cmd( char cmd ); // write command to lcd
void lcd_data( char data ); // write data to lcd
void puts_lcd ( unsigned char *data, unsigned int count );

/***** LCD COMMAND FUCNTION PROTOTYPES *****/
#define cursor_right() lcd_cmd( 0x14 )
#define cursor_left() lcd_cmd( 0x10 )
#define display_shift() lcd_cmd( 0x1C )
#define home_clr() lcd_cmd( 0x01 )
#define home_it() lcd_cmd( 0x02 )
#define line_2() lcd_cmd( 0xC0 ) // (0xC0)
 
 
     
 



LCD-USART De la USART al LCD.
 

   Y como consecuencia lógica e irrefrenable he montado una combinación de dos de los ejemplos anteriores: La USART y el LCD. Este ejemplo "oye" la USART y lo que recibe lo coloca en el PORTA, lo devuelve por la misma USART como eco y lo coloca en el LCD en la segunda línea a partir del carácter prompt ">". Si se completa totalmente esa segunda línea del LCD la limpia y comienza de nuevo desde el segundo carácter de la segunda linea del LCD.
 

  main_lcd_usart.c  
 
/**********************************************************************
* © 2008 PicManía By RedRaven
* http://picmania.garcia-cuervo.net
*
* FileName: main_lcd_usart.c
* Dependencies: p33FJ256GP710.h
* Processor: dsPIC33F
* Compiler: MPLAB® C30 v2.01 or higher
*
* When recive USART present in LCD
*
* C30 Optimization Level: -O1
*
**********************************************************************/

#include "p33FJ256GP710.h"
#include "lcd.h"

_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);

_FWDT(FWDTEN_OFF);

unsigned int flag_RECUSART;
unsigned char CHAR_RECUSART;

void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void){

  CHAR_RECUSART = U2RXREG;
  flag_RECUSART =1;
  IFS1bits.U2RXIF = 0;
}
void __attribute__((interrupt, no_auto_psv)) _U2TXInterrupt(void){

  IFS1bits.U2TXIF = 0;
}

void InitClock(void) {
  PLLFBD = 38; // M = 40
  CLKDIVbits.PLLPOST = 0; // N1 = 2
  CLKDIVbits.PLLPRE = 0; // N2 = 2
  OSCTUN = 0;
  RCONbits.SWDTEN = 0;
  // Clock switch to incorporate PLL
  __builtin_write_OSCCONH(0x01);
  __builtin_write_OSCCONL(0x01);
  while(OSCCONbits.LOCK != 1) {};
}

void InitUART2(void){

  U2MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
  //U2MODEbits.notimplemented; // Bit14
  U2MODEbits.USIDL = 0; // Bit13 Continue in Idle
  U2MODEbits.IREN = 0; // Bit12 No IR translation
  U2MODEbits.RTSMD = 0; // Bit11 Simplex Mode
  //U2MODEbits.notimplemented; // Bit10
  U2MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
  U2MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here)
  U2MODEbits.LPBACK = 0; // Bit6 No Loop Back
  U2MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
  U2MODEbits.URXINV = 0; // Bit4 IdleState = 1 (for dsPIC)
  U2MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
  U2MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
  U2MODEbits.STSEL = 0; // Bit0 One Stop Bit
  U2BRG = 240; // 40Mhz osc, 9600 Baud
  // Load all values in for U1STA SFR
  U2STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
  U2STAbits.UTXINV = 0; //Bit14 N/A, IRDA config
  U2STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
  //U2STAbits.notimplemented = 0; //Bit12
  U2STAbits.UTXBRK = 0; //Bit11 Disabled
  U2STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
  U2STAbits.UTXBF = 0; //Bit9 *Read Only Bit*
  U2STAbits.TRMT = 0; //Bit8 *Read Only bit*
  U2STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
  U2STAbits.ADDEN = 0; //Bit5 Address Detect Disabled
  U2STAbits.RIDLE = 0; //Bit4 *Read Only Bit*
  U2STAbits.PERR = 0; //Bit3 *Read Only Bit*
  U2STAbits.FERR = 0; //Bit2 *Read Only Bit*
  U2STAbits.OERR = 0; //Bit1 *Read Only Bit*
  U2STAbits.URXDA = 0; //Bit0 *Read Only Bit*
  IPC7 = 0x4400; //Mid Range Interrupt Priority level, no urgent reason
  IFS1bits.U2TXIF = 0; //Clear the Transmit Interrupt Flag
  IEC1bits.U2TXIE = 1; //Enable Transmit Interrupts
  IFS1bits.U2RXIF = 0; //Clear the Recieve Interrupt Flag
  IEC1bits.U2RXIE = 1; //Enable Recieve Interrupts
  U2MODEbits.UARTEN = 1; //And turn the peripheral on
  U2STAbits.UTXEN = 1;
}

void putUART2(char c){

  while ( U2STAbits.UTXBF); // wait while Tx buffer full
  U2TXREG = c;
}

void putsUART2(char *s){

  unsigned int i=0;
  while(s[i]) // loop until *s == ‘\0’, end of string
  putUART2(s[i++]); // send the character and point to the next one
}

int main(void){

  char mytext1[] = "dsPIC33F-PCtoLCD";
  char mytext2[] = "> ";
  char *pText1=&mytext1[0];
  char *pText2=&mytext2[0];
  unsigned int nCHARS=0;


  TRISA = 0x0000; // All to output
  InitClock(); // This is the PLL settings
  InitUART2(); // Initialize UART2 for 9600,8,N,1 TX/RX
  Init_LCD(); // Initialize LCD
  // Send to serial
  putsUART2(mytext1);
  putsUART2("\r\n");
  // Hellow World message
  home_clr();
  puts_lcd(pText1,sizeof(mytext1)-1);
  line_2();
  puts_lcd(pText2,sizeof(mytext2)-1);
  line_2();
  cursor_right();
  // Infinite Loop
  flag_RECUSART = 0;
  while(1){
    if(flag_RECUSART==1){
      flag_RECUSART=0;
      LATA = CHAR_RECUSART; // Lo que recibo vía UART2 lo pongo en el PORTA ...
      putUART2(CHAR_RECUSART); // ... lo devuelvo como eco ...
      lcd_data(CHAR_RECUSART); // ... y lo pongo en el LCD
      if(++nCHARS==15){
        line_2();
        puts_lcd(pText2,sizeof(mytext2)-1);
        line_2();
        cursor_right();
        nCHARS=0;
      }
    }
  };
}
 
 
     


 

  


 

 



Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias.
 
Visitas
Totales : 24291 Hoy: 1 Activas: 1 Vistas: 24291

Esta página fue modificada el 07-08-2010 22:41:25

           
 DmSoft WAMP Escribir Unreal