魄柜 发表于 2025-6-11 15:25:35

LCD1602 单片机上代码的实现和代码结构的分析

1、单片机引脚和设备引脚之间的通信
LCD1602使用并口与单片机进行通信,主要包括D0-D7 8个数据线和3根控制线(RS(指令和数据寄存器的区分),R/W(读写控制引脚),E(开始读写引脚,理解为串行总线的时钟线))。设备可以被配置为使用4线或8线数据宽度的数据线通信(实现方式为刚开始的几个配置指令只识别高4位)。下面是51单片机实现的数据通信的代码,代码写的比较low,主要分析代码架构:
database1602.h 基本数据交流的头文件:
#ifndef _DATABASE1602_H
#define _DATABASE1602_H

void delay1ms(void);
void delay(u16 time);


u8 read_status_8(void);
u8 read_data_8(void);
void write_data_8(u8 wdata);
void write_commond_8(u8 commond);


u8 read_status_4(void);
u8 read_data_4(void);
void write_data_4(u8 wdata);
void write_commond_4(u8 commond);
void write_commond_4_4(u8 commond);



#endif对应的.c文件:
#include "config.h"
#include "database1602.h"


/*延时1ms程序*/
void delay1ms(void)                               
{
        u8 i,j;
        i = 2;
        j = 199;
        do
        {
                while (--j);
        } while (--i);
}

/*根据设定的值延迟*/
void delay(u16 time){
        while(time--);
}

/*读取LCD1602状态寄存器的值*/
u8 read_status_8(void){
        u8 value = 0;
        //datap = 0xff;
        DATA0 = 1;
        DATA1 = 1;
        DATA2 = 1;
        DATA3 = 1;
        DATA4 = 1;
        DATA5 = 1;
        DATA6 = 1;
        DATA7 = 1;
        EN = 0;
        delay(50);
        RS = 0;
        RW = 1;
        delay(50);
        EN = 1;
        delay(10);
        //value = datap;
        if(DATA0 == 1){
                value = value | 0x01;
        }else{
                value = value | 0x00;
        }
        if(DATA1 == 1){
                value = value | 0x02;
        }else{
                value = value | 0x00;
        }
        if(DATA2 == 1){
                value = value | 0x04;
        }else{
                value = value | 0x00;
        }
        if(DATA3 == 1){
                value = value | 0x08;
        }else{
                value = value | 0x00;
        }
        if(DATA4 == 1){
                value = value | 0x10;
        }else{
                value = value | 0x00;
        }
        if(DATA5 == 1){
                value = value | 0x20;
        }else{
                value = value | 0x00;
        }
        if(DATA6 == 1){
                value = value | 0x40;
        }else{
                value = value | 0x00;
        }
        if(DATA7 == 1){
                value = value | 0x80;
        }else{
                value = value | 0x00;
        }
        delay(10);
        EN = 0;
        RS = 0;
        RW = 0;
        return value;
}


/*读取数据寄存器的值*/
u8 read_data_8(void){
        u8 rdata = 0;
        //datap = 0xff;
        DATA0 = 1;
        DATA1 = 1;
        DATA2 = 1;
        DATA3 = 1;
        DATA4 = 1;
        DATA5 = 1;
        DATA6 = 1;
        DATA7 = 1;
       
        EN = 0;
        delay(50);
        RS = 1;
        RW = 1;
        delay(50);
        EN = 1;
        delay(10);
        //rdata = datap;
       
        if(DATA0 == 1){
                rdata = rdata | 0x01;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA1 == 1){
                rdata = rdata | 0x02;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA2 == 1){
                rdata = rdata | 0x04;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA3 == 1){
                rdata = rdata | 0x08;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA4 == 1){
                rdata = rdata | 0x10;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA5 == 1){
                rdata = rdata | 0x20;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA6 == 1){
                rdata = rdata | 0x40;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA7 == 1){
                rdata = rdata | 0x80;
        }else{
                rdata = rdata | 0x00;
        }
        //rdata = P0;
        delay(10);
        EN = 0;
        RS = 0;
        RW = 0;
        return rdata;
}


/*写数据到数据寄存器*/
void write_data_8(u8 wdata){
        u8 value = wdata;
        EN = 0;
        delay(50);
        RS = 1;
        RW = 0;
        delay(50);
        EN = 1;
        delay(50);
        //datap = value;
        if(value & 0x01){
                DATA0 = 1;
        }else{
                DATA0 = 0;
        }
        if((value >> 1) & 0x01){
                DATA1 = 1;
        }else{
                DATA1 = 0;
        }
        if((value >> 2) & 0x01){
                DATA2 = 1;
        }else{
                DATA2 = 0;
        }
        if((value >> 3) & 0x01){
                DATA3 = 1;
        }else{
                DATA3 = 0;
        }
        if((value >> 4) & 0x01){
                DATA4 = 1;
        }else{
                DATA4 = 0;
        }
        if((value >> 5) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 6) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 7) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        //P0 = value;
        delay(50);
        EN = 0;
        RS = 0;
        RW = 0;
}


/*写命令到命令寄存器*/
void write_commond_8(u8 commond){
        u8 value = commond;
        EN = 0;
        delay(50);
        RS = 0;
        RW = 0;
        delay(50);
        EN = 1;
        delay(50);
        //datap = value;
        if(value & 0x01){
                DATA0 = 1;
        }else{
                DATA0 = 0;
        }
        if((value >> 1) & 0x01){
                DATA1 = 1;
        }else{
                DATA1 = 0;
        }
        if((value >> 2) & 0x01){
                DATA2 = 1;
        }else{
                DATA2 = 0;
        }
        if((value >> 3) & 0x01){
                DATA3 = 1;
        }else{
                DATA3 = 0;
        }
        if((value >> 4) & 0x01){
                DATA4 = 1;
        }else{
                DATA4 = 0;
        }
        if((value >> 5) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 6) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 7) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        //P0 = value;
        delay(50);
        EN = 0;
        RS = 0;
        RW = 0;
}


/*读取LCD1602状态寄存器的值*/
u8 read_status_4(void){
        u8 value = 0;
        //datap = 0xff;
        DATA4 = 1;
        DATA5 = 1;
        DATA6 = 1;
        DATA7 = 1;
        EN = 0;
        delay(50);
        RS = 0;
        RW = 1;
        delay(50);
        EN = 1;
        delay(10);
        //value = datap;
        if(DATA4 == 1){
                value = value | 0x10;
        }else{
                value = value | 0x00;
        }
        if(DATA5 == 1){
                value = value | 0x20;
        }else{
                value = value | 0x00;
        }
        if(DATA6 == 1){
                value = value | 0x40;
        }else{
                value = value | 0x00;
        }
        if(DATA7 == 1){
                value = value | 0x80;
        }else{
                value = value | 0x00;
        }
        delay(10);
        EN = 0;
        delay(10);
        EN = 1;
        delay(10);
        if(DATA4 == 1){
                value = value | 0x01;
        }else{
                value = value | 0x00;
        }
        if(DATA5 == 1){
                value = value | 0x02;
        }else{
                value = value | 0x00;
        }
        if(DATA6 == 1){
                value = value | 0x04;
        }else{
                value = value | 0x00;
        }
        if(DATA7 == 1){
                value = value | 0x08;
        }else{
                value = value | 0x00;
        }
        delay(10);
        EN = 0;
        RS = 0;
        RW = 0;
        return value;
}

/*读取数据寄存器的值*/
u8 read_data_4(void){
        u8 rdata = 0;
        //datap = 0xff;
        DATA4 = 1;
        DATA5 = 1;
        DATA6 = 1;
        DATA7 = 1;
       
        EN = 0;
        delay(50);
        RS = 1;
        RW = 1;
        delay(50);
        EN = 1;
        delay(10);
        if(DATA4 == 1){
                rdata = rdata | 0x10;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA5 == 1){
                rdata = rdata | 0x20;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA6 == 1){
                rdata = rdata | 0x40;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA7 == 1){
                rdata = rdata | 0x80;
        }else{
                rdata = rdata | 0x00;
        }
        delay(10);
        EN = 0;
        delay(10);
        EN = 1;
        delay(10);
        if(DATA4 == 1){
                rdata = rdata | 0x01;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA5 == 1){
                rdata = rdata | 0x02;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA6 == 1){
                rdata = rdata | 0x04;
        }else{
                rdata = rdata | 0x00;
        }
        if(DATA7 == 1){
                rdata = rdata | 0x08;
        }else{
                rdata = rdata | 0x00;
        }
        delay(10);
        EN = 0;
        RS = 0;
        RW = 0;
        return rdata;
}


/*写数据到数据寄存器*/
void write_data_4(u8 wdata){
        u8 value = wdata;
        EN = 0;
        delay(50);
        RS = 1;
        RW = 0;
        delay(50);
        EN = 1;
        delay(50);
        if((value >> 4) & 0x01){
                DATA4 = 1;
        }else{
                DATA4 = 0;
        }
        if((value >> 5) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 6) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 7) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        delay(50);
        EN = 0;
        delay(50);
        EN = 1;
        delay(50);
        if(value & 0x01){
                DATA4 = 1;
        }else{
                DATA4 = 0;
        }
        if((value >> 1) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 2) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 3) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        delay(50);
        EN = 0;
        RS = 0;
        RW = 0;
}


/*写命令到命令寄存器*/
void write_commond_4(u8 commond){
        u8 value = commond;
        EN = 0;
        delay(50);
        RS = 0;
        RW = 0;
        delay(50);
        EN = 1;
        delay(50);
        if((value >> 4) & 0x01){
                DATA4 = 1;
        }else{
                DATA4 = 0;
        }
        if((value >> 5) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 6) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 7) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        delay(50);
        EN = 0;
        delay(50);
        EN = 1;
        delay(50);
        if(value & 0x01){
                DATA4 = 1;
        }else{
                DATA4= 0;
        }
        if((value >> 1) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 2) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 3) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        delay(50);
        EN = 0;
        RS = 0;
        RW = 0;
}

void write_commond_4_4(u8 commond){
        u8 value = commond;
        EN = 0;
        delay(50);
        RS = 0;
        RW = 0;
        delay(50);
        EN = 1;
        delay(50);
        if((value >> 4) & 0x01){
                DATA4 = 1;
        }else{
                DATA4 = 0;
        }
        if((value >> 5) & 0x01){
                DATA5 = 1;
        }else{
                DATA5 = 0;
        }
        if((value >> 6) & 0x01){
                DATA6 = 1;
        }else{
                DATA6 = 0;
        }
        if((value >> 7) & 0x01){
                DATA7 = 1;
        }else{
                DATA7 = 0;
        }
        delay(50);
        EN = 0;
        RS = 0;
        RW = 0;
}2、通过基础数据通信对设备的操作代码,相当于通过基础的交流进行更上一层的交互,这里主要包括怎么样初始化设备,怎么样配置设备,和对设备的操作(设备实现的功能)。
下面是设备操作的代码:
driver1602.h是关于设备内部寄存器和控制位的声明(这里写的不是很好,后续再进一步改进):
#ifndef _DRIVER1602_H#define _DRIVER1602_H#include "config.h"#define CLEAR_DISPLAY 0x01        #define RETURN_HOME 0x02 #define STATUS_BF_BUSY 0x80#define STATUS_BF_READY 0x00/*** 接口数据宽度定义,4位和8位宽两种*/#define interface_data_width_4 (0 cursor_blink;                write_commond_status(tmp);        }else if(onoff == display_on){                lcd->display_on_off = display_on;                tmp = 0x0c | lcd->cursor_on_off | lcd->cursor_blink;                write_commond_status(tmp);        }else{                return -1;        }        return 0;}/***设置显示的光标是否打开*/s8 lcd1602_set_cursor_on_off(LCD1602_initTypeDef *lcd,u8 onoff){        u8 tmp = 0;        if(onoff == cursor_off){                lcd->cursor_on_off = cursor_off;                tmp = 0x08 | lcd->display_on_off | lcd->cursor_blink;                write_commond_status(tmp);        }else if(onoff == cursor_on){                lcd->cursor_on_off = cursor_on;                tmp = 0x0a | lcd->display_on_off | lcd->cursor_blink;                write_commond_status(tmp);        }else{                return -1;        }        return 0;}/***设置显示的光标是否闪烁*/s8 lcd1602_set_cursor_blink(LCD1602_initTypeDef *lcd,u8 onoff){        u8 tmp = 0;        if(onoff == cursor_character_blink_off){                lcd->cursor_blink = cursor_character_blink_off;                tmp = 0x08 | lcd->display_on_off | lcd->cursor_on_off;                write_commond_status(tmp);        }else if(onoff == cursor_character_blink_on){                lcd->cursor_blink = cursor_character_blink_on;                tmp = 0x09 | lcd->display_on_off | lcd->cursor_on_off;                write_commond_status(tmp);        }else{                return -1;        }        return 0;}/***设置改变DDRAM内容时光标和显示的移动*/s8 lcd1602_set_change_ddram_cursor_display(LCD1602_initTypeDef *lcd,u8 cursor_display,u8 direction){        u8 tmp = 0;        if(cursor_display == ddram_move_cursor){                lcd->ddram_cursor_display_move = ddram_move_cursor;        }else if(cursor_display == ddram_move_display){                lcd->ddram_cursor_display_move = ddram_move_display;        }else{                return -1;        }                if(direction == ddram_move_direction_left){                lcd->ddram_sc_move_driection = ddram_move_direction_left;        }else if(direction == ddram_move_direction_right){                lcd->ddram_sc_move_driection = ddram_move_direction_right;        }else{                return -1;        }        tmp = 0x10 | lcd->ddram_sc_move_driection | lcd->ddram_cursor_display_move;        write_commond_status(tmp);        return 0;}/***设置字体格式*/s8 lcd1602_set_font(LCD1602_initTypeDef *lcd,u8 font){        u8 tmp = 0;        if(font == font_mode_5_8){                lcd->display_font = font_mode_5_8;                tmp = 0x30 | lcd->display_lines;                write_commond_status(tmp);        }else if(font == font_mode_5_10){                lcd->display_font = font_mode_5_10;                tmp = 0x34 | lcd->display_lines;                write_commond_status(tmp);        }else{                return -1;        }        return 0;}/*读取默认位置的数据,当前数据指针所指数据*/u8 read_data_current(void){        u8 cur = 0;        u8 value;        if(width == interface_data_width_8){                cur = read_status_8();        }else{                cur = read_status_4();        }        cur = cur & 0x7f;        cur = cur | 0x80;        value = read_data_local(cur);        return value;}/*读取指定位置的字符*/u8 read_data_local(u8 addr){        u8 value;        write_commond_status(addr|0x80);        if(width == interface_data_width_8){                value = read_data_8();        }else{                value = read_data_4();        }        return value;}/*从指定位置,读取指定长度的字符串*/void read_string(u8 addr,u8 len,u8 *val){        u8 i = 0;        write_commond_status(addr|0x80);        for(i=0;i 7){                return -1;        }        write_commond_status(CGRAM_ADDRESS_SET_BASE| (local3){                return -1;        }        write_commond_status(CGRAM_ADDRESS_SET_BASE| (localDDRAM_PER_LINE_SIZE){                len = DDRAM_PER_LINE_SIZE - local;        }        write_commond_status(DDRAM_ADDRESS_SECOND_LINE + local);        while(len > 0){                write_data_status(*str);                str++;                len--;        }        return 0;}/*根据行号判断写入第一行还是第二行,写入字符串*/s8 write_string(u8 local,u8 line,u8 *str){        if(line == 1){                write_first_line_string(local,str);        }else if(line == 2){                write_second_line_string(local,str);        }else{                return -1;        }        return 0;}/*清除特定位置的字符并保持原来地址计数器的位置不变*/s8 clear_char(u8 local,u8 line){        u8 curlocation = read_counter();        if(local > DDRAM_PER_LINE_SIZE){                return -1;        }        if(line == 1){                write_commond_status(DDRAM_ADDRESS_FIRST_LINE + local);        }else if(line == 2){                write_commond_status(DDRAM_ADDRESS_SECOND_LINE + local);        }else{                return -2;        }        write_data_status(0x20);        write_commond_status(curlocation|0x80);        return 0;}/*清除一行,一行的40个字符全部清除*/s8 clear_line(u8 line){        u8 i = 0;        if(line == 1){                write_commond_status(DDRAM_ADDRESS_FIRST_LINE);        }else if(line == 2){                write_commond_status(DDRAM_ADDRESS_SECOND_LINE);        }else{                return -1;        }        for(i = 0;i DDRAM_PER_LINE_SIZE){                return -1;        }        if((s + length) > DDRAM_PER_LINE_SIZE){                length = DDRAM_PER_LINE_SIZE - s;        }        if(line == 1){                write_commond_status(DDRAM_ADDRESS_FIRST_LINE + s);        }else if(line == 2){                write_commond_status(DDRAM_ADDRESS_SECOND_LINE + s);        }else{                return -2;        }        for(i = 0;i DDRAM_PER_LINE_SIZE){                return -1;        }        if(line == 1){                write_commond_status(DDRAM_ADDRESS_FIRST_LINE + s);        }else if(line == 2){                write_commond_status(DDRAM_ADDRESS_SECOND_LINE + s);        }else{                return -2;        }        write_data_status(value);        write_commond_status(curlocation|0x80);        return 0;}/*替换特定位置的几个字符*/s8 replace_string(u8 local,u8 line,u8 *str){        u8 s = local;        u8 i = 0;        u8 curlocation = read_counter();        u8 len = strlen(str);        if(local > DDRAM_PER_LINE_SIZE){                return -1;        }        if(line == 1){                write_commond_status(DDRAM_ADDRESS_FIRST_LINE + s);        }else if(line == 2){                write_commond_status(DDRAM_ADDRESS_SECOND_LINE + s);        }else{                return -2;        }        if((s + len) > DDRAM_PER_LINE_SIZE){                len = DDRAM_PER_LINE_SIZE - s;        }        while(len > 0){                write_data_status(*str);                str++;                len--;        }        write_commond_status(curlocation|0x80);        return 0;}/*从开始位置显示一整段字符到可显示的位置*/void displaystring(u8 *str){        u8 length = strlen(str);        if(length
页: [1]
查看完整版本: LCD1602 单片机上代码的实现和代码结构的分析