joyrus 发表于 2012-7-9 00:36:18

c8051的LCD1602液晶驱动程序范例很有参考价值

本帖最后由 joyrus 于 2012-7-9 12:04 编辑

C/C++ code

//==============================================//
// Filename:   C8051f320_SMC1602A_Display.c   //
//                                              //
// Prozessor:C8051f320                        //
// Compiler:   Keil C51 7.06                  //
//                                              //
// Author:   Paul.Jia                         //
// QQ:         79974439                         //
// Copyright:MKL PSC TSD                      //
//==============================================//

//================================================
//1. SYSCLK is unlimited here
//2. Display by SMC1602A
//
//Use 3 ports for control
//Use 8 ports for data communications
//And initialize them right in the Main
//
//Need ms delay function from the Main
//    extern void delay_ms(unsigned short ms);
//
//Need initialize before use the diaplay function
//    void LCMInit(void);
//
//Export these 2 function
//    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
//    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData);
//================================================

//----------------------------
// Include Files
//----------------------------

#include <c8051f320.h>
#include <intrins.h>



//----------------------------
// Global Constants
//----------------------------

// Define control ports and data ports
// P0.5 - digital    push-pull    (1602)RS
// P0.6 - digital    push-pull    (1602)RW
// P0.7 - digital    push-pull    (1602)E
// P1.x - digital    push-pull    (1602)DATA
// Have to initalize these ports in the Main
//
sbit RS1602 = P0 ^ 5;                           // Register select signal port
sbit RW1602 = P0 ^ 6;                           // Data read/write port
sbit E1602= P0 ^ 7;                           // Enable signal port
#define DATA1602 P1                               // Data port

// Define macro definition basic the selected ports
//
#define W_D_IN   P1MDOUT &= 0x00                  // Change Data port to open-drain
#define W_D_OUTP1MDOUT |= 0xFF                  // Change Data port to push-pull

// Define device busy flag
//
#define Busy   0x80



//----------------------------
// Function Prototypes
//----------------------------

// Write data to SMC1602A
//
void WriteDataLCM(unsigned char WDLCM);

// Write command to SMC1602A
//
void WriteCommandLCM(unsigned char WCLCM, unsigned char BusyC);

// Read data from SMC1602A
//
unsigned char ReadDataLCM(void);

// Read command from SMC602A
//
unsigned char ReadStatusLCM(void);

// Initalize SMC1602A
//
void LCMInit(void);

// Display a char at the specified position
//
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);

// Display a string at the specified position
//
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData);

// Call a extern ms delay function
//
extern void delay_ms(unsigned short ms);



//----------------------------
// Subroutines
//----------------------------

//-----------------Write Data---------------------
void WriteDataLCM(unsigned char WDLCM)
//------------------------------------------------
{
    ReadStatusLCM();          // Detect Busy
    W_D_OUT;                  // Change Data port to push-pull
    DATA1602 = WDLCM;   // Write data
    RS1602 = 1;                  // LCM_RS = 1;
    RW1602 = 0;               // LCM_RW = 0;
    E1602 = 0;   // LCM_E = 0; If SYSCLK is high, add a small delay into here
    delay_ms(4);
    E1602 = 1;                  // LCM_E = 1;
}

//----------------Write Command-------------------
void WriteCommandLCM(unsigned char WCLCM, unsigned char BusyC)
//------------------------------------------------
{
    if(BusyC)                      // Decide if detect Busy from parameter
    {
      ReadStatusLCM();         // Detect Busy
    }
    W_D_OUT;                  // Change Data port to push-pull
    DATA1602 = WCLCM;   // Write command
    RS1602 = 0;                // LCM_RS = 0;
    RW1602 = 0;               // LCM_RW = 0;
    E1602 = 0;                  // LCM_E = 0; If SYSCLK is high, add a small delay into here
    delay_ms(4);
    E1602 = 1;                  // LCM_E = 1;
}

/*
//------------------Read Data---------------------
unsigned char ReadDataLCM(void)
//------------------------------------------------
{
    RS1602 = 1;          // LCM_RS = 1;
    RW1602 = 1;      // LCM_RW = 1;
    E1602 = 0;         // LCM_E = 0; If SYSCLK is high, add a small delay into here
    delay_ms(4);
    E1602 = 1;         // LCM_E = 1;
    W_D_IN;            // Change Data port to open-drain
    return DATA1602; // Return data
}
*/

//-----------------Read Command-------------------
unsigned char ReadStatusLCM(void)
//------------------------------------------------
{
    W_D_IN;          // Change Data port to open-drain
    RS1602 = 0;   // LCM_RS = 0;
    RW1602 = 1;    // LCM_RW = 1;
    E1602 = 0;      // LCM_E = 0; If SYSCLK is high, add a small delay into here
    delay_ms(4);
    E1602 = 1;      // LCM_E = 1;
    while(DATA1602 & Busy);    // Detect Busy
    return DATA1602;            // Return data
}

//------------------Initalize---------------------
void LCMInit(void)
//------------------------------------------------
{
    DATA1602 = 0;
      WriteCommandLCM(0x38, 0);      // Set display mode 3 times, no detect Busy
    delay_ms(5);
    WriteCommandLCM(0x38, 0);
    delay_ms(5);
    WriteCommandLCM(0x38, 0);
    delay_ms(5);
    // Keep above code

    WriteCommandLCM(0x38, 1);   // Set display mode(8 bits, 2 rows, 5x7), begin detect Busy everytime
    WriteCommandLCM(0x08, 1);    // Close display
    WriteCommandLCM(0x01, 1);    // Clear screen
    WriteCommandLCM(0x06, 1);    // Show the position of cursor move
    WriteCommandLCM(0x0C, 1);    // Show boot-strap cursor setting
    WriteCommandLCM(0x80, 1);    // The first position is row 1 line 1
}

//----------------Display one char----------------
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
//------------------------------------------------
{
    Y &= 0x1;
    X &= 0xF;         // Revise X<=15 Y<=1
    if(Y)                  // Add 0x40 to address for display row 2
    {
      X |= 0x40;
    }
    X |= 0x80;      // Count the address
    WriteCommandLCM(X, 0);    // Send the address to SMC1602A
    WriteDataLCM(DData);       // Write the char to SMC1602A
}

//----------------Display list char---------------
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData)
//------------------------------------------------
{
    unsigned char ListLength = 0;
    Y &= 0x1;
    X &= 0xF;       // Revise X<=15 Y<=1
    while(DData >= 0x20)   // If the string end, quit
    {
      if(X <= 0xF)
      {
            DisplayOneChar(X, Y, DData); // Display one char
            ListLength++;
            X++;
      }
    }
}
页: [1]
查看完整版本: c8051的LCD1602液晶驱动程序范例很有参考价值