51 Single-chip computer-lcd1602 driver

51 Single-chip computer-lcd1602 driver

This paper describes and summarizes the driver of 51 single-chip computer external lcd1602. The clock circuit of 51 single-chip computer uses 12MHz crystal oscillation, P0 port external pull-up resistance is connected with LCD1602 data port D0-D7, P2.7 and LCD1602 enable E-terminal connection, P2.6 and LCD1602 read/write select R/W terminal connection, P2.5 and LCD1602 data/command select RS terminal connection.Start with code below:

#define LCD1602_DATA P0  // D0-D7 is an 8-bit bidirectional data line
sbit LCD1602_E = P2^7;     // E-end is the enabling end, when E-end changes from high level to low level, LCD module executes commands
sbit LCD1602_RW = P2^6;    // R/W is read and write signal line, read at high level and write at low level
sbit LCD1602_RS = P2^5;    // RS is register selection, data register at high level and instruction register at low level

lcd1602 built-in command

The built-in LCD1602 command is macro-defined so that it can control LCD1602 more effectively when writing drivers, and avoid turning over the user manual every time you configure lcd1602.Only a few LCD1602 control commands are simple. The following code divides the configurable options of each command by line breaks. The macro definition functions are detailed in the code comments.

#define LCD1602_CLEAN_DISPLAY 0x01  // Clear display, instruction code 01H, cursor reset to address 00H position

#define LCD1602_CURSOR_RETURN 0x02  // Cursor reset, cursor return to address 00H

#define LCD1602_CURSOR_RIGHT_MOVE 0x02  // Cursor movement direction, high level right shift, low level left shift
#define LCD1602_CURSOR_LEFT_MOVE  0x00
#define LCD1602_WORD_MOVE_ENABLE  0x01  // Whether all text on the screen is moved left or right.High level means valid, low level means invalid
#define LCD1602_WORD_MOVE_DISABLE 0x00
#define LCD1602_INPUT_MODE (0x04 | LCD1602_CURSOR_RIGHT_MOVE | LCD1602_WORD_MOVE_DISABLE)

#define LCD1602_DISPLAY_ENABLE     0x04  // Controls the overall display on and off, high level on display, low level on display
#define LCD1602_DISPLAY_DISABLE    0x00
#define LCD1602_CURSOR_ENABLE      0x02  // Control cursor on and off, high level means cursor, low level means no cursor
#define LCD1602_CURSOR_DISABLE     0x00
#define LCD1602_CURSOR_TWINKLE     0x01  // Control whether the cursor blinks, high level blinks, low level does not blink
#define LCD1602_CURSOR_NOT_TWINKLE 0x00
#define LCD1602_DISPLAY_CONTROL (0x08 | LCD1602_DISPLAY_ENABLE | LCD1602_CURSOR_DISABLE | LCD1602_CURSOR_NOT_TWINKLE)

#define LCD1602_WORDS_MOVE  0x08  // Move text at high level and cursor at low level
#define LCD1602_CURSOR_MOVE 0x00
#define LCD1602_RIGHT_MOVE  0x04  // Move right at high level and left at low level
#define LCD1602_LEFT_MOVE   0x00
#define LCD1602_MOVE_CONTROL (0x10 | LCD1602_CURSOR_MOVE | LCD1602_RIGHT_MOVE)

#define LCD1602_DATA_BUS_8BIT 0x10  // 8-bit bus at high level and 4-bit bus at low level
#define LCD1602_DATA_BUS_4BIT 0x00
#define LCD1602_DISPLAY_2LINE 0x08  // Low level single line display, high level double line display
#define LCD1602_DISPLAY_1LINE 0x00
#define LCD1602_DISPLAY_5x10  0x04  // Show 5x7 dot matrix characters at low level and 5x10 at high level
#define LCD1602_DISPLAY_5x7   0x00
#define LCD1602_FUNCTION_SET (0x20 | LCD1602_DATA_BUS_8BIT | LCD1602_DISPLAY_2LINE | LCD1602_DISPLAY_5x7)

lcd1602 driver external interface rendering

The function interfaces provided by lcd1602 are as follows, and the function functions are detailed in the code notes:

void lcd1602_check_busy(void);  // LCD1602 Busy Detection
void lcd1602_write_cmd(u8 cmd);   // LCD1602 Writes 8-bit Commands
void lcd1602_write_data(u8 dat);  // LCD1602 Writes 8-Bit Data
void lcd1602_init(void);          // LCD1602 Initialization
void lcd1602_deinit(void);        // LCD1602 De-initialization
void lcd1602_delay_ms(u16 ms);    // 12MHZ clock, delay 1ms function for 52 single-chip computer
void lcd1602_delay_10us(u16 n);  // 12MHZ Clock with Delay of 10us Function for 52 Single-chip Computer
s8 lcd1602_set_pos(u8 x, u8 y);   // LCD1602 Cursor Positioning
void lcd1602_write_str(string str);      // LCD1602 Writing String
s8 lcd1602_write_num(u8 width, s32 num);  // LCD1602 Write Numbers
void lcd1602_write_space(u8 cnt);        // LCD1602 Write Space
void lcd1602_clean(void);  // LCD1602 Clear Screen
void test_lcd1602(void);   // LCD1602 test code

lcd1602 driver-busy signal detection

After receiving the command from 51 single-chip computer, lcd1602 takes much less time to process the command, such as: displaying a character takes much less time than clearing the screen. During processing the command, lcd1602 can not be written. By setting the state of reading command, the busy detection can be done to get the status of lcd1602 data pin D7 to determine whether it is busy.

/*******************************************************************************
* Function name: lcd1602_check_busy
* Function function: LCD1602 busy detection
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_check_busy(void)  // LCD1602 Busy Detection
{
    u8 state = 0xff;

    LCD1602_E = 0;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        state = LCD1602_DATA;
        LCD1602_E = 0;     // Unenable after reading status to prevent LCD output from interfering with bus
    } while (state & 0x80);      // If the LCD is busy, keep checking until it is not busy
}

lcd1602 driver-write command

The lcd1602 built-in command control display is set to the write command state.

/*******************************************************************************
* Function name: lcd1602_write_cmd
* Function function: LCD1602 writes 8-bit commands
* Input: cmd:hexadecimal command value
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_cmd(u8 cmd)  // LCD1602 Writes 8-bit Commands
{
    lcd1602_check_busy();
    LCD1602_E = 0;         // Enabling
    LCD1602_RS = 0;        // Select Send Command
    LCD1602_RW = 0;        // Select Write
    LCD1602_DATA = cmd;    // Place Command
    lcd1602_delay_10us(1);  // Waiting for data to stabilize
    LCD1602_E = 1;         // Write Sequence
    lcd1602_delay_10us(1);  // Hold Time
    LCD1602_E = 0;
}

lcd1602 driver-write data

Control lcd1602 display content, default lcd1602 supports ascii code, does not involve custom lcd1602 character related content.

/*******************************************************************************
* Function name: lcd1602_write_data
* Function function: LCD1602 writes 8-bit data
* Input: dat:ascii code
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_data(u8 dat)  // LCD1602 Writes 8-Bit Data
{
    lcd1602_check_busy();
    LCD1602_E = 0;         // Enable clearing
    LCD1602_RS = 1;        // Select Input Data
    LCD1602_RW = 0;        // Select Write
    LCD1602_DATA = dat;    // Write data
    lcd1602_delay_10us(1);
    LCD1602_E = 1;         // Write Sequence
    lcd1602_delay_10us(1);  // Hold Time
    LCD1602_E = 0;
}

lcd1602 driver - set cursor position

Controls the position at which lcd1602 displays a character.

/*******************************************************************************
* Function name: lcd1602_set_pos
* Function function: LCD1602 cursor positioning
* Input: x/y: horizontal/vertical coordinates
* Output: s8: Return-1 Set coordinate value exception
* Name: none
*******************************************************************************/
s8 lcd1602_set_pos(u8 x, u8 y)  // LCD1602 Cursor Positioning
{
    if ((x >= LCD1602_WIDTH) || (y >= LCD1602_HIGH)) {
        return -1;
    }

    if (y == 0) {
        lcd1602_write_cmd(LCD1602_1LINE_ADDRESS + x);
    } else if (y == 1) {
        lcd1602_write_cmd(LCD1602_2LINE_ADDRESS + x);
    }

    return 0;
}

lcd1602 driver-display string

Call lcd1602_write_data() continuously based on the length of the string.

/*******************************************************************************
* Function name: lcd1602_write_str
* Function function: LCD1602 Writing string
* Input: str: String
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_str(string str)  // LCD1602 Writing String
{
    for (; (*str) != '\0'; str++) {
        lcd1602_write_data(*str);
    }
}

lcd1602 driver-digital display

Output digits on lcd1602, support positive/negative integer display, control display bit width, when the digits to be displayed are not wide enough, 0 will be added at the front, only part of the lower digits will be displayed when the digits to be displayed exceed the bit width.Note: For C51 programming, malloc() is suspected not to be supported by the keil compiler.

/*******************************************************************************
* Function name: lcd1602_write_num
* Function function: LCD1602 write numbers
* Input: width: Display number of digits, num: number
* Output: s8: Return-1 Input Display Bit Exception
* Name: none
*******************************************************************************/
s8 lcd1602_write_num(u8 width, s32 num)  // LCD1602 Write Numbers
{
    u8 i;
    u8 dat[10] = { 0 };  // malloc is not supported

    if (width > sizeof(dat)) {
        return -1;
    }

    if (num < 0) {
        lcd1602_write_data('-');
        num = -num;
    }
    for (i = 0; num; i++) {
        if (i >= width) {
            break;
        }
        dat[i] = (num % 10 + '0');
        num /= 10;
    }

    for (; i < width; i++) {
        dat[i] = '0';
    }

    for (; i; i--) {
        lcd1602_write_data(dat[i - 1]);  // Write data
    }

    return 0;
}

Appendix - LCD1602 driver (lcd1602.h)

#ifndef __LCD1602_H__
#define __LCD1602_H__

#include <reg52.h>
#include "include.h"

#define LCD1602_DATA P0  // D0-D7 is an 8-bit bidirectional data line
sbit LCD1602_E = P2^7;     // E-end is the enabling end, when E-end changes from high level to low level, LCD module executes commands
#ifdef ELECTRONIC_MARS
sbit LCD1602_RW = P2^6;    // R/W is read and write signal line, read at high level and write at low level
sbit LCD1602_RS = P2^5;    // RS is register selection, data register at high level and instruction register at low level
#endif
#ifdef ELECTRONIC_MOON
sbit LCD1602_RW = P2^5;
sbit LCD1602_RS = P2^6;
#endif

#define LCD1602_WIDTH 16  // Display Width
#define LCD1602_HIGH   2  // Display Height

#define LCD1602_1LINE_ADDRESS 0xc0  // Show header address
#define LCD1602_2LINE_ADDRESS 0x80

#define LCD1602_CLEAN_DISPLAY 0x01  // Clear display, instruction code 01H, cursor reset to address 00H position

#define LCD1602_CURSOR_RETURN 0x02  // Cursor reset, cursor return to address 00H

#define LCD1602_CURSOR_RIGHT_MOVE 0x02  // Cursor movement direction, high level right shift, low level left shift
#define LCD1602_CURSOR_LEFT_MOVE  0x00
#define LCD1602_WORD_MOVE_ENABLE  0x01  // Whether all text on the screen is moved left or right.High level means valid, low level means invalid
#define LCD1602_WORD_MOVE_DISABLE 0x00
#define LCD1602_INPUT_MODE (0x04 | LCD1602_CURSOR_RIGHT_MOVE | LCD1602_WORD_MOVE_DISABLE)

#define LCD1602_DISPLAY_ENABLE     0x04  // Controls the overall display on and off, high level on display, low level on display
#define LCD1602_DISPLAY_DISABLE    0x00
#define LCD1602_CURSOR_ENABLE      0x02  // Control cursor on and off, high level means cursor, low level means no cursor
#define LCD1602_CURSOR_DISABLE     0x00
#define LCD1602_CURSOR_TWINKLE     0x01  // Control whether the cursor blinks, high level blinks, low level does not blink
#define LCD1602_CURSOR_NOT_TWINKLE 0x00
#define LCD1602_DISPLAY_CONTROL (0x08 | LCD1602_DISPLAY_ENABLE | LCD1602_CURSOR_DISABLE | LCD1602_CURSOR_NOT_TWINKLE)

#define LCD1602_WORDS_MOVE  0x08  // Move text at high level and cursor at low level
#define LCD1602_CURSOR_MOVE 0x00
#define LCD1602_RIGHT_MOVE  0x04  // Move right at high level and left at low level
#define LCD1602_LEFT_MOVE   0x00
#define LCD1602_MOVE_CONTROL (0x10 | LCD1602_CURSOR_MOVE | LCD1602_RIGHT_MOVE)

#define LCD1602_DATA_BUS_8BIT 0x10  // 8-bit bus at high level and 4-bit bus at low level
#define LCD1602_DATA_BUS_4BIT 0x00
#define LCD1602_DISPLAY_2LINE 0x08  // Low level single line display, high level double line display
#define LCD1602_DISPLAY_1LINE 0x00
#define LCD1602_DISPLAY_5x10  0x04  // Show 5x7 dot matrix characters at low level and 5x10 at high level
#define LCD1602_DISPLAY_5x7   0x00
#define LCD1602_FUNCTION_SET (0x20 | LCD1602_DATA_BUS_8BIT | LCD1602_DISPLAY_2LINE | LCD1602_DISPLAY_5x7)

void lcd1602_check_busy(void);  // LCD1602 Busy Detection
void lcd1602_write_cmd(u8 cmd);   // LCD1602 Writes 8-bit Commands
void lcd1602_write_data(u8 dat);  // LCD1602 Writes 8-Bit Data
void lcd1602_init(void);          // LCD1602 Initialization
void lcd1602_deinit(void);        // LCD1602 De-initialization
void lcd1602_delay_ms(u16 ms);    // 12MHZ clock, delay 1ms function for 52 single-chip computer
void lcd1602_delay_10us(u16 n);  // 12MHZ Clock with Delay of 10us Function for 52 Single-chip Computer
s8 lcd1602_set_pos(u8 x, u8 y);   // LCD1602 Cursor Positioning
void lcd1602_write_str(string str);      // LCD1602 Writing String
s8 lcd1602_write_num(u8 width, s32 num);  // LCD1602 Write Numbers
void lcd1602_write_space(u8 cnt);        // LCD1602 Write Space
void lcd1602_clean(void);  // LCD1602 Clear Screen
void test_lcd1602(void);   // LCD1602 test code

#endif

Appendix - LCD1602 driver (lcd1602.c)

#include "lcd1602.h"

/*******************************************************************************
* Function name: lcd1602_check_busy
* Function function: LCD1602 busy detection
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_check_busy(void)  // LCD1602 Busy Detection
{
    u8 state = 0xff;

    LCD1602_E = 0;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        state = LCD1602_DATA;
        LCD1602_E = 0;     // Unenable after reading status to prevent LCD output from interfering with bus
    } while (state & 0x80);      // If the LCD is busy, keep checking until it is not busy
}

/*******************************************************************************
* Function name: lcd1602_write_cmd
* Function function: LCD1602 writes 8-bit commands
* Input: cmd:hexadecimal command value
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_cmd(u8 cmd)  // LCD1602 Writes 8-bit Commands
{
    lcd1602_check_busy();
    LCD1602_E = 0;         // Enabling
    LCD1602_RS = 0;        // Select Send Command
    LCD1602_RW = 0;        // Select Write
    LCD1602_DATA = cmd;    // Place Command
    lcd1602_delay_10us(1);  // Waiting for data to stabilize
    LCD1602_E = 1;         // Write Sequence
    lcd1602_delay_10us(1);  // Hold Time
    LCD1602_E = 0;
}

/*******************************************************************************
* Function name: lcd1602_write_data
* Function function: LCD1602 writes 8-bit data
* Input: dat:ascii code
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_data(u8 dat)  // LCD1602 Writes 8-Bit Data
{
    lcd1602_check_busy();
    LCD1602_E = 0;         // Enable clearing
    LCD1602_RS = 1;        // Select Input Data
    LCD1602_RW = 0;        // Select Write
    LCD1602_DATA = dat;    // Write data
    lcd1602_delay_10us(1);
    LCD1602_E = 1;         // Write Sequence
    lcd1602_delay_10us(1);  // Hold Time
    LCD1602_E = 0;
}

/*******************************************************************************
* Function name: lcd1602_init
* Function function: LCD1602 initialization
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_init(void)  // LCD1602 Initialization
{
    lcd1602_write_cmd(LCD1602_FUNCTION_SET);  // Open Display
    lcd1602_write_cmd(LCD1602_DISPLAY_CONTROL);  // Turn on display without cursor
    lcd1602_write_cmd(LCD1602_INPUT_MODE);  // Write a pointer plus 1
    lcd1602_clean();  // Clear screen
    lcd1602_set_pos(1, 0);  // Set Data Pointer Start Point
}

/*******************************************************************************
* Function name: lcd1602_deinit
* Function function: LCD1602 de-initialization
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_deinit(void)        // LCD1602 De-initialization
{
    lcd1602_clean();  // Clear screen
    lcd1602_write_cmd(0x08 |
                      LCD1602_DISPLAY_DISABLE |
                      LCD1602_CURSOR_DISABLE |
                      LCD1602_CURSOR_NOT_TWINKLE);
}

/*******************************************************************************
* Function name: lcd1602_delay_ms
* Function function: 52 single chip 12MHZ clock, delay 1ms function
* Input: ms: Delayed MS
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_delay_ms(u16 ms)  // 12MHZ clock, delay 1ms function for 52 single-chip computer
{
    u16 i;

    for (; ms; ms--) {
        for (i = 0; i < 123; i++);
    }
}

/*******************************************************************************
* Function name: lcd1602_delay_10us
* Function function: 52 single chip 12MHZ clock, delay 10us function
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_delay_10us(u16 n)  // 12MHZ Clock with Delay of 10us Function for 52 Single-chip Computer
{
    while (n--);
}

/*******************************************************************************
* Function name: lcd1602_set_pos
* Function function: LCD1602 cursor positioning
* Input: x/y: horizontal/vertical coordinates
* Output: s8: Return-1 Set coordinate value exception
* Name: none
*******************************************************************************/
s8 lcd1602_set_pos(u8 x, u8 y)  // LCD1602 Cursor Positioning
{
    if ((x >= LCD1602_WIDTH) || (y >= LCD1602_HIGH)) {
        return -1;
    }

    if (y == 0) {
        lcd1602_write_cmd(LCD1602_1LINE_ADDRESS + x);
    } else if (y == 1) {
        lcd1602_write_cmd(LCD1602_2LINE_ADDRESS + x);
    }

    return 0;
}

/*******************************************************************************
* Function name: lcd1602_write_str
* Function function: LCD1602 Writing string
* Input: str: String
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_str(string str)  // LCD1602 Writing String
{
    for (; (*str) != '\0'; str++) {
        lcd1602_write_data(*str);
    }
}

/*******************************************************************************
* Function name: lcd1602_write_num
* Function function: LCD1602 write numbers
* Input: width: Display number of digits, num: number
* Output: s8: Return-1 Input Display Bit Exception
* Name: none
*******************************************************************************/
s8 lcd1602_write_num(u8 width, s32 num)  // LCD1602 Write Numbers
{
    u8 i;
    u8 dat[10] = { 0 };  // malloc is not supported

    if (width > sizeof(dat)) {
        return -1;
    }

    if (num < 0) {
        lcd1602_write_data('-');
        num = -num;
    }
    for (i = 0; num; i++) {
        if (i >= width) {
            break;
        }
        dat[i] = (num % 10 + '0');
        num /= 10;
    }

    for (; i < width; i++) {
        dat[i] = '0';
    }

    for (; i; i--) {
        lcd1602_write_data(dat[i - 1]);  // Write data
    }

    return 0;
}

/*******************************************************************************
* Function name: lcd1602_write_space
* Function function: LCD1602 write space
* Input: cnt: Number of spaces
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_write_space(u8 cnt)  // LCD1602 Write Space
{
    for(; cnt; cnt--) {
        lcd1602_write_data(' ');
    }
}

/*******************************************************************************
* Function name: lcd1602_clean
* Function function: LCD1602 screen cleaner
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void lcd1602_clean(void)  // LCD1602 Clear Screen
{
    lcd1602_write_cmd(LCD1602_CLEAN_DISPLAY);
    lcd1602_delay_ms(5);  // Writing instructions immediately after screen clearing failed with a delay of 5 ms
}

/*******************************************************************************
* Function name: test_lcd1602
* Function function: LCD1602 test code
* Input: void
* Output: void
* Name: none
*******************************************************************************/
void test_lcd1602(void)  // LCD1602 test code
{
    u8 i;

    lcd1602_init();

    for (i = 1; i < 200; i++) {
        lcd1602_set_pos(0, 1);
        lcd1602_write_str("test_lcd1602 ###");
        lcd1602_set_pos(14, 1);
        lcd1602_write_space(2);

        lcd1602_set_pos(0, 0);
        lcd1602_write_num(2, i);
        lcd1602_set_pos(8, 0);
        lcd1602_write_num(5, -i);

        lcd1602_delay_ms(500);
        lcd1602_clean();
    }
}

Appendix-General (include.h)

#ifndef __INCLUDE_H__
#define __INCLUDE_H__

/*
################################################################

                                Operating Platform Selection

################################################################
*/
#define ELECTRONIC_MARS    // Homemade calendar
//#define ELECTRONIC_MOON // 51 development board

typedef char s8;
typedef unsigned char u8;
typedef short s16;
typedef unsigned short u16;
typedef long s32;
typedef unsigned long u32;
typedef char* string;



#endif
Two original articles have been published. Approved 0. Visits 77
Private letter follow

Keywords: ascii less Programming

Added by phenley on Sat, 22 Feb 2020 04:54:57 +0200