Help on programming

Discussion in 'Help & Requests' started by S7SM, Oct 31, 2011.

Help on programming
  1. Unread #1 - Oct 31, 2011 at 7:12 AM
  2. S7SM
    Joined:
    Sep 11, 2011
    Posts:
    61
    Referrals:
    1
    Sythe Gold:
    0

    S7SM Member

    Help on programming

    Right now, I got my LCD working. Just that I have this code but not sure where to modify it at so that it'll display a word instead of just the light itself.

    Anyone can help me out with this code ?

    http://microdesignsinc.com/picbook/downloads/c/P3_MCC18.c


    /******* P3_MCC18.c ************************************************************
    *
    * Use 10 MHz crystal frequency.
    * Use Timer0 for ten millisecond looptime.
    * Blink "Alive" LED every two and a half seconds.
    * Use pushbutton to exercise Screens utility.
    *
    ******* Program hierarchy *****************************************************
    *
    * Mainline
    * Initial
    * InitLCD
    * LoopTime
    * DisplayC
    * T40
    * BlinkAlive
    * Pbutton
    * Screens
    * DisplayC
    * T40
    * Frequency
    * Period
    * PWmax
    * RateRPG
    * ByteDisplay
    * DisplayC
    * T40
    * DisplayV
    * T40
    * LoopTime
    *
    *******************************************************************************
    */

    #include <p18cxxx.h>

    /*******************************
    * Assembler directives
    *******************************
    */

    /*******************************
    * Definitions and equates
    *******************************
    */

    #define PBthres 30 // Pushbutton threshold for a long press

    /*******************************
    * Global variables
    *******************************
    */

    char TMR0LCOPY; // Copy of sixteen-bit Timer0 used by LoopTime
    char TMR0HCOPY;
    char INTCONCOPY; // Copy of INTCON for LoopTime subroutine
    char COUNT; // Counter available as local to subroutines
    char TEMP; // Temporary local variable
    char ALIVECNT; // Counter for blinking "Alive" LED
    char BYTE; // Eight-bit byte to be displayed
    char OLDPORTD; // Holds previous value of inputs
    char DELRPG; // Generated by RPG
    char RPGCNT; // Used to display RPG changes
    char PBCOUNT; // Counter for measuring duration of press
    char SCREEN; // State of LCD subroutine
    char LOOP10; // Scale of ten loop counter
    char THR; // Threshold value used by Pbutton

    struct { // Control/status bits for pushbutton
    unsigned ISC:1; // Initiate screen change for slow press
    unsigned ISA:1; // Initiate secondary action for fast press
    unsigned PDONE:1; // Pushbutton action has been taken
    unsigned OLDPB:1; // Old state of pushbutton
    unsigned NEWPB:1; // New state of pushbutton
    } PBSTATEbits;

    /*******************************
    * Constant strings
    *******************************
    */

    // For stability reasons, create an EVEN number of elements in any given array
    const char LCDstr[] = {0x33,0x32,0x28,0x01,0x0c,0x06,0x00,0x00};// LCD Initialization string
    const char StrtStr[] = {0x80,'P','u','s','h',' ','P','B',' ',0};// Startup screen
    const char BYTE_1[] = {0x80,'B','Y','T','E','=',' ',' ',' ',0};// Write "BYTE=" 1st line of LCD
    const char Clear1[] = {0x80,' ',' ',' ',' ',' ',' ',' ',' ',0};// Clear line 1
    const char Clear2[] = {0xC0,' ',' ',' ',' ',' ',' ',' ',' ',0};// Clear line 2
    const char FreqStr[] = {0x80,'F','r','e','q',' ','k','H','z',0};// Frequency instrument
    const char PerStr[] = {0x80,'P','e','r',' ',' ',' ','u','s',0};// Period instrument
    const char PWmaxStr[] = {0x80,'P','W','m','a','x',' ','u','s',0};// Max pulse width instrument

    /*******************************
    * Variable strings
    *******************************
    */

    char BYTESTR[] = {0,0,0,0,0,0,0,0,0,0}; // Display string for binary version of BYTE

    /*******************************
    * Function prototypes
    *******************************
    */

    void Initial(void);
    void InitLCD(void);
    void Looptime(void);
    void T40(void);
    void DisplayC(const char *);
    void DisplayV(char *);
    void BlinkAlive(void);
    void LoopTime(void);
    void ByteDisplay(void);
    void RateRPG(void);
    void Pbutton(void);
    void Screens(void);
    void Frequency(void);
    void Period(void);
    void PWmax(void);

    /////// Mainline program ////////////////////////////////////////

    /*******************************
    * main()
    *******************************
    */

    void main()
    {
    Initial(); // Initialize everything

    while(1)
    {
    PORTBbits.RB0 = !PORTBbits.RB0; // Toggle pin, to support measuring loop time
    BlinkAlive(); // Blink "Alive" LED
    Pbutton(); // Check pushbutton
    Screens(); // Deal with SCREEN state
    LoopTime(); // Make looptime be ten milliseconds
    }
    }

    /*******************************
    * Initial()
    *
    * This subroutine performs all initializations of variables and registers.
    *******************************
    */

    void Initial()
    {
    ADCON1 = 0b10001110; // Enable PORTA & PORTE digital I/O pins
    TRISA = 0b11100001; // Set I/O for PORTA
    TRISB = 0b11011100; // Set I/O for PORTB
    TRISC = 0b11010000; // Set I/0 for PORTC
    TRISD = 0b00001111; // Set I/O for PORTD
    TRISE = 0b00000000; // Set I/O for PORTE
    T0CON = 0b10001000; // Set up Timer0 for a looptime of 10 ms
    PORTA = 0b00010000; // Turn off all four LEDs driven from PORTA
    OLDPORTD = PORTD; // Initialize "old" value
    RPGCNT = 0; // Clear counter to be displayed
    PBCOUNT = 0; // and pushbutton count
    SCREEN = 0; // Initialize LCD's SCREEN variable
    THR = 0; // Initialize Pbutton's THR variable
    PBSTATEbits.ISC = 0; // Initialize pushbutton state
    PBSTATEbits.ISA = 0;
    PBSTATEbits.PDONE = 0;
    PBSTATEbits.OLDPB = 1;
    PBSTATEbits.NEWPB = 0;
    InitLCD(); // Initialize LCD
    DisplayC(StrtStr); // Display startup message
    }

    /*******************************
    * InitLCD()
    *
    * Initialize the Optrex 8x2 character LCD.
    * First wait for 0.1 second, to get past display's power-on reset time.
    *******************************
    */

    void InitLCD()
    {
    char currentChar;
    char *tempPtr;

    COUNT = 10; // Wait 0.1 second
    while (COUNT)
    {
    LoopTime(); // Call LoopTime() 10 times
    COUNT--;
    }

    PORTEbits.RE0 = 0; // RS=0 for command
    tempPtr = LCDstr;

    while (*tempPtr) // if the byte is not zero
    {
    currentChar = *tempPtr;
    PORTEbits.RE1 = 1; // Drive E pin high
    PORTD = currentChar; // Send upper nibble
    PORTEbits.RE1 = 0; // Drive E pin low so LCD will accept nibble
    LoopTime();
    currentChar <<= 4; // Shift lower nibble to upper nibble
    PORTEbits.RE1 = 1; // Drive E pin high again
    PORTD = currentChar; // Write lower nibble
    PORTEbits.RE1 = 0; // Drive E pin low so LCD will process byte
    LoopTime(); // Wait 40 usec
    tempPtr++; // Increment pointerto next character
    }
    }

    /*******************************
    * T40()
    *
    * Pause for 40 microseconds or 40/0.4 = 100 clock cycles.
    * Assumes 10/4 = 2.5 MHz internal clock rate.
    *******************************
    */

    void T40()
    {
    // Measured with oscilloscope to be about 42.80 us
    // including the time to call this routine. Decrementing each
    // "cCOUNT" takes approximately 4 us.

    unsigned char cCOUNT = 7;
    while (cCOUNT)
    cCOUNT--;
    }

    /*******************************
    * DisplayC(const char *)
    *
    * This subroutine is called with the passing in of an array of a constant
    * display string. It sends the bytes of the string to the LCD. The first
    * byte sets the cursor position. The remaining bytes are displayed, beginning
    * at that position.
    * This subroutine expects a normal one-byte cursor-positioning code, 0xhh, or
    * an occasionally used two-byte cursor-positioning code of the form 0x00hh.
    *******************************
    */

    void DisplayC(const char * tempPtr)
    {
    char currentChar;

    PORTEbits.RE0 = 0; // Drive RS pin low for cursor-positioning code
    while (*tempPtr) // if the byte is not zero
    {
    currentChar = *tempPtr;
    PORTEbits.RE1 = 1; // Drive E pin high
    PORTD = currentChar; // Send upper nibble
    PORTEbits.RE1 = 0; // Drive E pin low so LCD will accept nibble
    currentChar <<= 4; // Shift lower nibble to upper nibble
    PORTEbits.RE1 = 1; // Drive E pin high again
    PORTD = currentChar; // Write lower nibble
    PORTEbits.RE1 = 0; // Drive E pin low so LCD will process byte
    T40(); // Wait 40 usec
    PORTEbits.RE0 = 1; // Drive RS pin high for displayable characters
    tempPtr++; // Increment pointerto next character
    }
    }

    /*******************************
    * DisplayV(char *)
    *
    * This subroutine is called with the passing in of an array of a variable
    * display string. It sends the bytes of the string to the LCD. The first
    * byte sets the cursor position. The remaining bytes are displayed, beginning
    * at that position.
    *******************************
    */

    void DisplayV(char * tempPtr)
    {
    char currentChar;

    PORTEbits.RE0 = 0; // Drive RS pin low for cursor-positioning code
    while (*tempPtr) // if the byte is not zero
    {
    currentChar = *tempPtr;
    PORTEbits.RE1 = 1; // Drive E pin high
    PORTD = currentChar; // Send upper nibble
    PORTEbits.RE1 = 0; // Drive E pin low so LCD will accept nibble
    currentChar <<= 4; // Shift lower nibble to upper nibble
    PORTEbits.RE1 = 1; // Drive E pin high again
    PORTD = currentChar; // Write lower nibble
    PORTEbits.RE1 = 0; // Drive E pin low so LCD will process byte
    T40(); // Wait 40 usec
    PORTEbits.RE0 = 1; // Drive RS pin high for displayable characters
    tempPtr++; // Increment pointerto next character
    }
    }

    /*******************************
    * BlinkAlive()
    *
    * This subroutine briefly blinks the LED next to the PIC every two-and-a-half
    * seconds.
    *******************************
    */

    void BlinkAlive()
    {
    PORTAbits.RA4 = 1; // Turn off LED
    if (!(--ALIVECNT)) // Decrement loop counter and return if not zero
    {
    ALIVECNT = 250; // Reinitialize BLNKCNT
    PORTAbits.RA4 = 0; // Turn on LED for ten milliseconds every 2.5 sec
    }
    }

    /*******************************
    * LoopTime()
    *
    * This subroutine waits for Timer0 to complete its ten millisecond count
    * sequence. It does so by waiting for sixteen-bit Timer0 to roll over. To obtain
    * a period of precisely 10000/0.4 = 25000 clock periods, it needs to remove
    * 65536-25000 or 40536 counts from the sixteen-bit count sequence. The
    * algorithm below first copies Timer0 to RAM, adds "Bignum" to the copy ,and
    * then writes the result back to Timer0. It actually needs to add somewhat more
    * counts to Timer0 than 40536. The extra number of 12+2 counts added into
    * "Bignum" makes the precise correction.
    *******************************
    */

    void LoopTime()
    {
    #define Bignum 65536-25000+12+2

    while (!INTCONbits.T0IF); // Wait until ten milliseconds are up
    INTCONCOPY = INTCON; // Save INTCON bits
    INTCONbits.GIEH = 0; // Disable all interrupts from CPU
    INTCONbits.GIEL = 0;
    TMR0LCOPY = TMR0L; // Read 16-bit counter at this moment
    TMR0HCOPY = TMR0H;
    TMR0LCOPY += Bignum & 0x00FF; // add LSB
    if (STATUSbits.C) // If Carry, increment high byte
    TMR0HCOPY++;
    TMR0HCOPY += (Bignum>>8) & 0x00FF; // add MSB
    TMR0H = TMR0HCOPY;
    TMR0L = TMR0LCOPY; // Write 16-bit counter at this moment
    WREG = INTCONCOPY & 0b11000000; // Reenable interrupts to CPU if enabled prior
    INTCON = INTCON | WREG; // to LoopTime
    INTCONbits.T0IF = 0; // Clear Timer0 flag
    }

    /*******************************
    * ByteDisplay()
    *
    * Display whatever is in BYTE as a binary number.
    *******************************
    */

    void ByteDisplay()
    {
    DisplayC(BYTE_1); // Display "BYTE="

    COUNT = 8; // 8 bits in BYTE
    while (COUNT)
    {
    TEMP = (BYTE & 0b00000001); // Move bit 0 of BYTE into TEMP
    TEMP |= 0x30; // Convert to ASCII
    BYTESTR[COUNT] = TEMP; // and move to string
    BYTE = BYTE>>1; // Right shift bits in BYTE by 1
    COUNT--; // Decrement COUNT;
    }
    BYTESTR[0] = 0xC0; // Add cursor-positioning code
    BYTESTR[9] = 0; // and end-of-string terminator
    DisplayV(BYTESTR); // Display the string
    }


    /*******************************
    * RateRPG()
    *
    * This subroutine decyphers RPG changes into values of DELRPG.
    * DELRPG = +2 for fast CW change, +1 for slow CW change, 0 for no change,
    * -1 for slow CCW change and -2 for fast CCW change.
    *******************************
    */

    void RateRPG()
    {
    #define Threshold 3 // Value to distinguish between slow and fast
    char W_temp;

    PORTAbits.RA2 = 0; // Turn LED off
    DELRPG = 0; // Clear for "no change" return value
    W_temp = PORTD; // Copy PORTD into W_temp
    TEMP = W_temp; // and TEMP
    W_temp = W_temp ^ OLDPORTD; // Any change?
    W_temp = W_temp & 0b00000011; // If not, W_temp = 0
    if (W_temp != 0) // If the two bits have changed then...
    {
    W_temp = OLDPORTD>>1; // Form what a CCW change would produce
    if (OLDPORTD & 0x01) // Make new bit 1 = complement of old bit 0
    W_temp &= 0b11111101;
    else
    W_temp |= 0b00000010;
    W_temp = (W_temp ^ TEMP); // Did the RPG actually change to this output?
    W_temp &= 0b00000011; // Mask off upper 6 bits
    if (W_temp == 0) // If so, then change DELRPG to -1 for CCW
    {
    DELRPG--;
    if (THR != 0)
    {
    DELRPG--; // If fast turning, decrement again
    PORTAbits.RA2 = 1; // Turn LED on
    }
    }
    else
    {
    DELRPG++; // Otherwise, change DELRPG to +1 for CW
    if (THR != 0)
    {
    DELRPG++; // If fast turning, increment again
    PORTAbits.RA2 = 1; // Turn LED on
    }
    }
    THR = Threshold; // Reinitialize THR
    }
    if (THR != 0) // Does THR equal zero
    THR--; // If not, then decrement it
    OLDPORTD = TEMP; // Save PORTD as OLDPORTD for ten ms from now
    }

    /*******************************
    * Pbutton()
    *
    * This subroutine sorts out long and short pushbutton presses into two outputs:
    * ISC=1: Initiate screen change for slow press
    * ISA=1: Initiate secondary action for fast press
    * PDONE=1 One of the above actions has occurred for this press
    *******************************
    */

    void Pbutton()
    {
    PBSTATEbits.ISC = 0; // Clear Initiate Screen Change bit (if set)
    PBSTATEbits.ISA = 0; // Clear Initiate Secondary Action bit (if set)

    if (PORTDbits.RD3 == 1) // Copy pushbutton state to NEWPB
    PBSTATEbits.NEWPB = 1;
    else
    PBSTATEbits.NEWPB = 0;

    if (PBSTATEbits.OLDPB) // Look for leading edge (OLDPB=1, NEWPB=0)
    {
    if (!PBSTATEbits.NEWPB)
    PBCOUNT = PBthres; // Start counter
    }

    if (!PBSTATEbits.NEWPB) // Pushbutton is still pressed
    {
    if (!PBCOUNT) // and counter has passed threshold
    if (!PBSTATEbits.PDONE) // and no action has yet been taken
    {
    PBSTATEbits.ISC = 1; // Initiate screen change
    PBSTATEbits.PDONE = 1; // Done with pulse
    }
    }
    else // Pushbutton has been released
    PBSTATEbits.PDONE = 0; // so clear PDONE

    if (!PBSTATEbits.OLDPB) // Look for trailing edge (OLDPB=0, NEWPB=1)
    if (PBSTATEbits.NEWPB)
    {
    if (PBCOUNT) // Fast pulse
    PBSTATEbits.ISA = 1; // Initiate secondary action
    PBSTATEbits.PDONE = 0; // Done with pulse
    PBCOUNT = 0; // Finish counting
    }

    if (PBCOUNT) // Has counter reached zero?
    PBCOUNT--; // If not, then decrement it

    if (PBSTATEbits.NEWPB) // Copy NEWPB to OLDPB
    PBSTATEbits.OLDPB = 1;
    else
    PBSTATEbits.OLDPB = 0;
    }

    /*******************************
    * Screens()
    *
    * This subroutine uses the ISC bit from the Pbutton subroutine to cycle the
    * state of SCREEN and to take action based upon its value.
    * Initially SCREEN=0, so that whatever screen is displayed by the Initial
    * subroutine is not changed until a PB switch press. Then the screen
    * corresponding to SCREEN=1 is displayed. Subsequent PB switch
    * presses cycle through SCREEN=2, 3, etc., recycling back to SCREEN=1.
    *******************************
    */

    void Screens()
    {
    #define NumberOfScreens 4 // Change this value if new screens are added

    if (PBSTATEbits.ISC)
    {
    SCREEN++;
    if (SCREEN == (NumberOfScreens+1)) // Check if past last screen
    SCREEN = 1; // Cycle back to SCREEN = 1

    DisplayC(Clear1); // Clear the display when switching screens
    DisplayC(Clear2);
    }

    if (SCREEN == 1)
    {
    if (PBSTATEbits.ISC)
    DisplayC(FreqStr);
    Frequency();
    }

    if (SCREEN == 2)
    {
    if (PBSTATEbits.ISC)
    DisplayC(PerStr);
    Period();
    }

    if (SCREEN == 3)
    {
    if (PBSTATEbits.ISC)
    DisplayC(PWmaxStr);
    PWmax();
    if (PBSTATEbits.ISA) // Fast pulse, toggle PORTAbits.RA1
    PORTAbits.RA1 = !PORTAbits.RA1;
    }

    if (SCREEN == 4)
    {
    RateRPG(); // Decypher RPG inputs into DELRPG
    RPGCNT += DELRPG; // Increment or decrement RPGCNT from RPG
    BYTE = RPGCNT; // Point BYTE to RPGCNT
    ByteDisplay();
    if (PBSTATEbits.ISA) // Fast pulse, reset RPGCNT
    RPGCNT = 0;
    }
    }

    /////// Stubs for measurement subroutines /////////////////////////////////////


    void Frequency() { }
    void Period() { }
    void PWmax() { }
     
< ... | What do infractions do? >

Users viewing this thread
1 guest


 
 
Adblock breaks this site