1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

16f1827 code in asm & hi-tech c

Discussion in 'Code Repository' started by ClydeCrashKop, Sep 17, 2013.

  1. ClydeCrashKop

    ClydeCrashKop Well-Known Member

    Joined:
    Apr 28, 2005
    Messages:
    1,032
    Likes:
    172
    Location:
    Florida
    Here are my first couple programs just to get it working while I read the data sheet. They both work on the 16F1827 with a 20mhz crystal. Use the other config1 line for internal clock.
    Feel free to add any programs / subroutines to this thread.

    Blinks 8 LEDs on PORTB in asm.
    Code (asm):
    ;Modified from Tutorial 1.5 - Nigel Goodwin 2002 tutorials from Electrotech online

    list  p=16f1827      ; list directive to define processor
    #include <p16f1827.inc> ; processor specific variable definitions
    ;------------------------------------------------------------------------------
    ;
    ; CONFIGURATION WORD SETUP
    ;    __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
      __CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
        __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF

    cblock  0x20    ;start of general purpose registers
      count1    ;used in delay routine
      counta    ;used in delay routine
      countb    ;used in delay routine
    endc
    LEDPORT Equ PORTB  ;set constant LEDPORT = 'PORTB'
    LEDTRIS Equ TRISB  ;set constant for TRIS register

    org 0x0000  ;org sets the origin, 0x0000 for the 16F628,
        ;this is where the program starts running
    ; movlw 0x07
    ; movwf CMCON  ;turn comparators off (make it like a 16F84)
    ;    bsf  STATUS,  RP0 ;This doesn't work on 16F1827 use BANKSEL instead
    BANKSEL TRISB
        movlw  b'00000000'  ;set PortB all outputs
        movwf  LEDTRIS
    ; bcf STATUS,  RP0 This doesn't work on 16F1827 use BANKSEL instead
    BANKSEL PORTB
    clrf LEDPORT  ;set all outputs low
    Loop
    movlw b'10000000'
    ; movlw b'11111111'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'01000000'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'00100000'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'00010000'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'00001000'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'00000100'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'00000010'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    movlw b'00000001'
    movwf LEDPORT
    call Delay  ;this waits for a while!
    goto Loop  ;go back and do it again
    Delay movlw d'250' ;d'250'  ;delay 250 ms (4 MHz clock)
    movwf count1
    d1 movlw 0xC7
    movwf counta
    movlw 0x01
    movwf countb
    Delay_0
    decfsz counta, f
    goto $+2
    decfsz countb, f
    goto Delay_0
    decfsz count1 ,f
    goto d1
    retlw 0x00
    end
    Reads ADC on AN0 and outputs the high 8 bits to LEDs on PORTB in asm.

    Code (asm):
    ;Modified from Nigel Goodwin's tutorials from Electrotech online

    list  p=16f1827      ; list directive to define processor
    #include <p16f1827.inc> ; processor specific variable definitions
    ERRORLEVEL 0, -302  ;suppress bank selection messages
    ;------------------------------------------------------------------------------
    ;
    ; CONFIGURATION WORD SETUP
    ;_FOSC_HS is external crystal, 20 mhz because I couldn't get internal 8 mhz working
    ;    __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
      __CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
        __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF

    cblock  0x20    ;start of general purpose registers
      RESULTHI
      RESULTLO
      count1    ;used in delay routine
      counta    ;used in delay routine
      countb    ;used in delay routine
    endc
    org 0x0000  ;org sets the origin, 0x0000 for the 16F628,
        ;this is where the program starts running

    ;This code block configures the ADC
    ;for polling, Vdd and Vss references, Frc
    ;clock and AN0 input.
    ;
    ;Conversion start & polling for completion
    ; are included.
    ;
    BANKSEL ADCON1 ;
    ; movlw  b'11110000' ;Right justify, Frc
    movlw  b'01110000' ;Left justify, Frc clock
    ; movlw  b'00100000' ;Left justify, /32
    MOVWF ADCON1 ;Vdd and Vss Vref
    BANKSEL TRISB
        movlw  b'00000000'  ;set PortB all outputs
        movwf  TRISB
    BANKSEL TRISA ;
    BSF TRISA,0 ;Set RA0 to input
    BANKSEL ANSELA ;
    BSF ANSELA,0 ;Set RA0 to analog
    Loop
    BANKSEL ADCON0 ;
    movlw  b'00000001' ;Select channel AN0
    MOVWF ADCON0 ;Turn ADC On
    ;CALL SampleTime ;Acquisiton delay
    call Delay50  ;this waits for a while!
    BSF ADCON0,ADGO ;Start conversion
    BTFSC ADCON0,ADGO ;Is conversion done?
    GOTO $-1 ;No, test again
    BANKSEL ADRESH ;
    MOVF ADRESH,W ;Left justified, Read upper Byte
    BANKSEL PORTB
    movwf PORTB
    MOVWF RESULTHI ;store in GPR space
    BANKSEL ADRESL ;
    MOVF ADRESL,W ;Read lower 8 bits
    MOVWF RESULTLO ;Store in GPR space
    goto Loop  ;go back and do it again



    Delay255 movlw 0xff  ;delay 255 mS
      goto d0
    Delay100 movlw d'100'  ;delay 100mS
      goto d0
    Delay50  movlw d'50'  ;delay 50mS
      goto d0
    Delay20  movlw d'20'  ;delay 20mS
      goto d0
    Delay5  movlw 0x05  ;delay 5.000 ms (20 MHz clock)
    d0  movwf count1
    d1  movlw 0xE7
      movwf counta
      movlw 0x04
      movwf countb
    Delay_0  decfsz counta, f
      goto $+2
      decfsz countb, f
      goto Delay_0
      decfsz count1 ,f
      goto d1
      retlw 0x00
    ;end of Delay routines
    end
     
     
    Last edited by a moderator: Oct 2, 2013
  2. ClydeCrashKop

    ClydeCrashKop Well-Known Member

    Joined:
    Apr 28, 2005
    Messages:
    1,032
    Likes:
    172
    Location:
    Florida
    If I had to read books again after being away from assembly for months, I decided to go with HI-TECH C instead. I like easy floating point math and sprintf to format output to the LCD.
    I use Nigel Goodwin's tutorials in asm... http://www.winpicprog.co.uk/ for an asm library and circuits. I use his 16F628a boards for the 16F1827. (same pinout)
    Now using HI-TECH C, I use Nigel's tutorials.. re-written in C by Ian Rogers. http://www.electro-tech-online.com/content/467-nigel-goodwin-s-tutorials-c.html as a starting place for C programs and subroutines.
    Thank you Nigel and Ian.
    Some things are changed in the 16F628a code for the enhanced 16F1827.
    This is a 16 bit counter using sprintf to format output to the LCD.
    This is the wiring for the LCD using Hitachi HD44780 (use on port B)
    http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm

    Code (C):

    // 16F1827 16 bit counter in HI-TECH C
    #include <pic.h>  // pic specific identifiers
    #include <stdlib.h>
    #include <stdio.h>
    #define _XTAL_FREQ  4000000  // Xtal speed
    //  __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
    __CONFIG(0x01E4);// Config1 bits
    //  __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
    __CONFIG(0x1CFF);    // Config2 bits
    #define LCD_PORT PORTB  // constants
    #define LCD_TRIS TRISB  //
    #define LCD_RS   RB4
    #define LCD_RW  RB6
    #define LCD_E  RB7
      // Required prototypes.. each function needs to be declared
      // if called BEFORE definition.
    void LCD_init(void), LCD_cmd(unsigned char ch);
    void LCD_goto(char line, char column), LCD_clr(void);
    void LCD_cur(unsigned char ch), pulse_E(void);
    void LCD_char(unsigned char ch), LCD_charD(unsigned char ch);
    void interrupt isr(void);
    // From ADC program
    void LCD_printC(const char *str), LCD_printR(char *str);
    void delayMs(int x), InitADC(void);
    int ReadADC(unsigned char ch);
    //Original
    unsigned char LCDbuffer[17];
    unsigned char text1[] = {"16 bit counter."};
    void main(void)  // program entry
      {
      OSCCONbits.IRCF = 0b00001101; // 4 MHz 4 bits
      ANSELB = 0;  //Set PORTB as digital I/O
      int index = 0;
      int number = 0;  // new counting variable
      LCD_TRIS = 0b00000000;  // Led port as outputs
      __delay_ms(150);  // let LCD stabilise
      LCD_init();  // Initalise screen
      LCD_goto(1,0);  // line 1.
      while(text1[index] != 0)  // while text1[index] is'nt zero
      LCD_char(text1[index++]);  // write message 1
      while(1)  // endless Loop
      {
      LCD_goto(2,1);
      sprintf(LCDbuffer,"%6u ",number);  // unsigned 6 digits
    //  sprintf(LCDbuffer,"%5d ",number);  // signed 5 digits
      LCD_printR(LCDbuffer);  // use sprintf to format
      number++;
      __delay_ms(180);
      }
      }
    void LCD_init()
      {
      LCD_cmd(0x20);  // 4 bit
      LCD_cmd(0x28);  // display shift
      LCD_cmd(0x6);  // character mode
      LCD_cmd(0xc);  // display on / off and cursor
      LCD_clr();  // clear display
      }
    void LCD_printR(char * str)    // This passes the start of a RAM character array
      {  // by default the pointer points to data section
      while(*str != 0)  // while the character pointed to isn't 0
      LCD_char(*str++);  // print out the character, then increment
      }
    void LCD_goto(char line, char column)  // combines line and lineW
      {
      unsigned char data = 0x80;  // default to 1
      if(line == 2)data = 0xc0;  // change to 2
      data += column;  // add in  column
      LCD_cmd(data);
      }
    void LCD_clr()
      {
      LCD_cmd(1);  // Clr screen
      }
    void LCD_cur(char on)
      {
      unsigned char cur = 0xc;  // cursor off
      if(on) cur = 0xd;  // cursor on
      LCD_cmd(cur);
      }
    void LCD_cmd(unsigned char ch)
      {
      LCD_PORT = ch >> 4 & 0xf;  // write high nibble
      LCD_RS = 0;
      pulse_E();
      LCD_PORT = ch & 0xf;  // write low nibble
      LCD_RS = 0;
      pulse_E();
      __delay_ms(5);
      }
    void LCD_charD(unsigned char ch)
      {
      ch+=0x30;
      LCD_char(ch);  // convert to ascii
      }
    void LCD_char(unsigned char ch)
      {
      LCD_PORT = ch >> 4 & 0xf;  // High nibble
      LCD_RS = 1;
      pulse_E();
      LCD_PORT = ch & 0xf;  // low nibble
      LCD_RS = 1;
      pulse_E();
      __delay_ms(5);
      }
    void pulse_E()
      {
      LCD_E = 1;
      __delay_us(1);
      LCD_E = 0;
      }
     
     
    Last edited: Mar 18, 2014
  3. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,301
    Likes:
    648
    Location:
    Derbyshire, UK
    Nice to see my tutorials moving on :)

    I've been using the 16F1827 a lot recently, it's a REALLY nice device, and I've been considering adding 1827 versions to the tutorials, as I've already done various parts of them (such as the LCD routines) - but like everything else, it's a question of getting round to it.
     
    • Like Like x 1
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. ClydeCrashKop

    ClydeCrashKop Well-Known Member

    Joined:
    Apr 28, 2005
    Messages:
    1,032
    Likes:
    172
    Location:
    Florida

    This uses the Ultrasonic Ranging Module HC-SR04 to measure distance.
    Data sheet http://elecfreaks.com/store/download/HC-SR04.pdf
    Many places have them for < $5.00.
    It uses the 16 bit Timer1 to measure the Echo pulse.
    There are only 4 pins. +5 volts, ground, Trigger goes to RB5 and Echo goes to RA2 on the 16F1827.
    There is a lot of application info online.
    This is the wiring for the LCD using Hitachi HD44780
    http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm

    Code (C):

    // 16F1827 and Ultrasonic Ranging Module HC-SR04 to measure distance.
    // LCD on port B. Trigger goes to RB5 and Echo goes to RA2.
    #include <pic.h> // pic specific identifiers
    #include <stdlib.h>
    #include <stdio.h>
    #define _XTAL_FREQ 4000000 // Xtal speed
    // __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
    __CONFIG(0x01E4); // Config1 bits
    // __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
    __CONFIG(0x1CFF); // Config2 bits
    #define LCD_PORT PORTB // constants
    #define LCD_TRIS TRISB //
    #define LCD_RS RB4
    #define LCD_RW RB6
    #define LCD_E RB7
    // Required prototypes.. each function needs to be declared
    // if called BEFORE definition.
    void LCD_init(void), LCD_cmd(unsigned char ch);
    void LCD_goto(char line, char column), LCD_clr(void);
    void LCD_cur(unsigned char ch), pulse_E(void);
    void LCD_char(unsigned char ch), LCD_charD(unsigned char ch);
    void LCD_printC(const char *str), LCD_printR(char *str);
    unsigned char LCDbuffer[17];
    unsigned char text1[] = {"Distance"};
    void main(void) // program entry
    {
    OSCCONbits.IRCF = 0b00001101; // 4 MHz 4 bits
    ANSELA = 0b11100011; //Set PORTA 2,3,4 as digital Input
    ANSELB = 0; //Set PORTB as digital I/O
    div_t x; // Needed for division
    int index = 0;
    int time = 0;
    int distance = 0;
    LCD_TRIS = 0b00000000; // LCD port as outputs
    __delay_ms(150); // let LCD stabilise
    LCD_init(); // Initalise screen
    LCD_goto(1,0); // line 1.
    while(text1[index] != 0) // while text1[index] is'nt zero
    LCD_char(text1[index++]); // write message 1
    while(1) // endless Loop
    {
    RB5 = 1; //Ping the sonar trigger
    __delay_ms(20);
    RB5 = 0; //turn off the sonar trigger
    TMR1H =0;
    TMR1L =0;
    while(RA2==0) // wait for echo pin to go high
    {}
    T1CONbits.TMR1ON = 1; // turn on T1, counting until echo pin goes low
    while(RA2==1) // wait for echo pin to go low
    {}
    T1CONbits.TMR1ON = 0; // turn off T1
    time =(TMR1L+(TMR1H*256)); // all of 16 bit Timer1
    LCD_goto(2,1); // line 2.
    // distance=time*0.028 + 1.093 ; // Calculating the distance
    distance = time / 145; // inches on mine
    sprintf(LCDbuffer,"%6u",distance); // unsigned? 6 digits
    LCD_printR(LCDbuffer); // use sprintf to format
    LCD_goto(2,7);
    LCD_char(34); // 34 is " character, 27 is '
    __delay_ms(180);
    }
    }
     
     
    void LCD_init()
    {
    LCD_cmd(0x20); // 4 bit
    LCD_cmd(0x28); // display shift
    LCD_cmd(0x6); // character mode
    LCD_cmd(0xc); // display on / off and cursor
    LCD_clr(); // clear display
    }
    void LCD_printR(char * str) // This passes the start of a RAM character array
    { // by default the pointer points to data section
    while(*str != 0) // while the character pointed to isn't 0
    LCD_char(*str++); // print out the character, then increment
    }
     
    void LCD_goto(char line, char column) // combines line and lineW
    {
    unsigned char data = 0x80; // default to 1
    if(line == 2)data = 0xc0; // change to 2
    data += column; // add in column
    LCD_cmd(data);
    }
    void LCD_clr()
    {
    LCD_cmd(1); // Clr screen
    }
    void LCD_cur(char on)
    {
    unsigned char cur = 0xc; // cursor off
    if(on) cur = 0xd; // cursor on
    LCD_cmd(cur);
    }
    void LCD_cmd(unsigned char ch)
    {
    LCD_PORT = ch >> 4 & 0xf; // write high nibble
    LCD_RS = 0;
    pulse_E();
    LCD_PORT = ch & 0xf; // write low nibble
    LCD_RS = 0;
    pulse_E();
    __delay_ms(5);
    }
    void LCD_charD(unsigned char ch)
    {
    ch+=0x30;
    LCD_char(ch); // convert to ascii
    }
    void LCD_char(unsigned char ch)
    {
    LCD_PORT = ch >> 4 & 0xf; // High nibble
    LCD_RS = 1;
    pulse_E();
    LCD_PORT = ch & 0xf; // low nibble
    LCD_RS = 1;
    pulse_E();
    __delay_ms(5);
    }
    void pulse_E()
    {
    LCD_E = 1;
    __delay_us(1);
    LCD_E = 0;
    }
     
     

    Attached Files:

    Last edited: Mar 18, 2014
  6. ClydeCrashKop

    ClydeCrashKop Well-Known Member

    Joined:
    Apr 28, 2005
    Messages:
    1,032
    Likes:
    172
    Location:
    Florida
    This is a Dual ADC on AN0 & AN1 for the 16F1827 with LCD on Port B

    Code (C):
    // Dual ADC on AN0 & AN1 for the 16F1827 with LCD on Port B
    // The wiring for the LCD using Hitachi HD44780 is at
    // http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm
     
    #include <pic.h>                // pic specific identifiers
    #include <stdio.h>
     
    #define _XTAL_FREQ  4000000        // Xtal speed
    //    __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF
    __CONFIG(0x01E4);    // Config1 bits
     
    //    __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
    __CONFIG(0x1CFF);      // Config2 bits
     
    #define LCD_PORT PORTB            // constants
    #define LCD_TRIS TRISB            //
    #define LCD_RS    RB4
    #define LCD_RW    RB6
    #define LCD_E    RB7
     
            // Required prototypes.. each function needs to be declared
            // if called BEFORE definition.
     
    void LCD_init(void), LCD_cmd(unsigned char ch);
    void LCD_goto(char line, char column), LCD_clr(void);
    void LCD_cur(unsigned char ch), pulse_E(void);
    void LCD_char(unsigned char ch), LCD_charD(unsigned char ch);
    void LCD_printC(const char *str), LCD_printR(char *str);
    void delayMs(int x), InitADC(void);
    int ReadADC(unsigned char ch);
     
        // Variables
        int number = 0;                    // new counting variable
     
    unsigned char LCDbuffer[17];
     
    void main(void)                        // program entry
        {
        OSCCONbits.IRCF = 0b00001101; // 4 MHz 4 bits
        ANSELB = 0;            //Set PORTB as digital I/O
        int index = 0;
        LCD_TRIS = 0b00000000;            // LCD port as outputs
        __delay_ms(150);                // let LCD stabilise
        LCD_init();                        // Initalise screen
        InitADC();                    // Initalise ADC
     
        while(1)                        // endless Loop
            {
    // Reads Analog voltage on AN0 & AN1 Be sure to InitADC();
            LCD_goto(1,0);
            number = ReadADC(0);    // ADC(0) is on AN0 (RA0)
            sprintf(LCDbuffer,"CH1 %3d %04X  ",number,number);
            LCD_printR(LCDbuffer);        // use sprintf to format hex
            delayMs(10);                // as well as decimal.
    // If you want the second ADC on AN1, use this.
    /*        LCD_goto(2,0);
            number = ReadADC(1);    // ADC(1) is on AN1 (RA1)
            sprintf(LCDbuffer,"CH2 %3d %04X  ",number,number);
            LCD_printR(LCDbuffer);
            delayMs(10);
    */

            } //while(1)
        } //main(void)
     
     
    void InitADC()
        {
        ADCON0 = 0b00000001;            // ADON
        ADCON1 = 0b11110000;            // Right justified FRC Clock                            // Set ADCON0 & 1
        }
     
    int ReadADC(unsigned char ch)
        {
        int ret = 0;
        ADCON0 = 0b00000001 + (ch<<2);    // set channel to read
        delayMs(5);
        GO_nDONE =1;        // 16F1827 start conversion
          while(GO_nDONE);                    // wait for conversion
     
          ret =  (ADRESH & 0x3) << 8;        // get
          ret +=    ADRESL;                    // result
        return ret;
        }
     
     
    // This may take calculated delay times. Don't use for LCD
    void delayMs(int x)
        {
        while(x--)
            __delay_ms(1);
        }
     
    void LCD_printC(const char * str)    // This passes the start a ROM character array
        {                                // by default the pointer points to data section
        while(*str != 0)                // while the character pointed to isn't 0
            LCD_char(*str++);            // print out the character, then increment
        }                                // the pointer down the array
     
    void LCD_printR(char * str)            // This passes the start of a RAM character array
        {                                // by default the pointer points to data section
        while(*str != 0)                // while the character pointed to isn't 0
            LCD_char(*str++);            // print out the character, then increment
        }
     
    void LCD_init()
        {
        LCD_cmd(0x20);                    // 4 bit
        LCD_cmd(0x28);                    // display shift
        LCD_cmd(0x6);                    // character mode
        LCD_cmd(0xc);                    // display on / off and cursor
        LCD_clr();                        // clear display
        }
     
    void LCD_goto(char line, char column)        // combines line and lineW
        {
        unsigned char data = 0x80;                // default to 1
        if(line == 2)data = 0xc0;                // change to 2
        data += column;                            // add in  column
        LCD_cmd(data);
        }
     
    void LCD_clr()
        {
        LCD_cmd(1);                                // Clr screen
        }
     
    void LCD_cur(char on)
        {
        unsigned char cur = 0xc;                // cursor off
        if(on) cur = 0xd;                        // cursor on
        LCD_cmd(cur);
        }
     
    void LCD_cmd(unsigned char ch)
        {
        LCD_PORT = ch >> 4 & 0xf;            // write high nibble
        LCD_RS = 0;
        pulse_E();
        LCD_PORT = ch & 0xf;                // write low nibble
        LCD_RS = 0;
        pulse_E();
        __delay_ms(5);
        }
     
    void LCD_charD(unsigned char ch)
        {
        ch+=0x30;
        LCD_char(ch);                        // convert to ascii
        }
     
    void LCD_char(unsigned char ch)
        {
        LCD_PORT = ch >> 4 & 0xf;            // High nibble
        LCD_RS = 1;
        pulse_E();
        LCD_PORT = ch & 0xf;                // low nibble
        LCD_RS = 1;
        pulse_E();
        __delay_ms(5);
        }
     
    void pulse_E()
        {
        LCD_E = 1;
        __delay_us(1);
        LCD_E = 0;
        }
     

    Attached Files:

    Last edited: Mar 18, 2014
  7. Mosaic

    Mosaic Well-Known Member

    Joined:
    Jun 3, 2010
    Messages:
    2,609
    Likes:
    129
    Location:
    Caribbean
    Just to add, if you're using the internal EEPROM the address for establishing assembler DE entries in these enhanced devices is no longer 0x2100. It is 0xF000!
     

Share This Page