前言

字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式 LCD,目前常用 161,162,202 和 402 行等的模块。
上面指的是以字符为单位,如161,也就是1行16列,最多能显示16个字符。其中,每个字符都是有几行乘几列的像素点组成,如168的像素点构成一个字符。本次介绍的液晶是12864。


正文


如上图所示,就是我要讲的液晶显示。CS1,CS2用于片选操作,也就是选择左半屏和右半屏,其中每一屏是64位,也就是说每一屏都是64x64dots,这里的液晶显示是4行16列,也就是说,一个字符,高是16dots,宽是8dots(一共128x64dots)。

引脚定义:

  • VSS 为接地
  • VDD 接 5V 正电源
  • RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器
    R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W
    共同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信
    号,当 RS 为高电平 R/W 为低电平时可以写入数据
  • E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。
  • D0~D7 为 8 位双向数据线

下面说说指令集:

1602 液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1 为
高电平、0 为低电平)

指令 1:清显示,指令码 01H,光标复位到地址 00H 位置。
指令 2:光标复位,光标返回到地址 00H。
指令 3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有
文字是否左移或者右移。高电平表示有效,低电平则无效。
指令 4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显
示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,
高电平闪烁,低电平不闪烁。
指令 5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。
指令 6:功能设置命令 DL:高电平时为 4 位总线,低电平时为 8 位总线 N:低电平时为单
行显示,高电平时双行显示 F: 低电平时显示 5x7 的点阵字符,高电平时显示 5x10 的点阵
字符。
指令 7:字符发生器 RAM 地址设置。
指令 8:DDRAM 地址设置。
指令 9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或
者数据,如果为低电平表示不忙。
指令 10:写数据。
指令 11:读数据。


关于如何写数据

1.让引脚RW置高电平
2.让引脚RS置高电平
3.如果是片选一,则让CS1置高电平,否则让CS2置高电平
4.让引脚RW置低电平 (RS高,RW低表示可以写入数据)
5.将数据写入引脚中(STM32每个GPIO口16个引脚)
6.让引脚E置高电平
7.延时1us
8.让引脚E置低电平
9.延时1us
10.让引脚RW置高电平
11.如果是片选一,则让CS1置低电平,否则让CS2置低电平


代码理解

 LCD_PRINT(0,0,lcd_show,"Input Card pwd:");

调用LCD_PRINT函数,对应4个参数

#define  LCD_PRINT(row, colum, buf, fmt, args...) do{\memset(buf, 0, sizeof(buf));\sprintf(buf, fmt,##args);\lcd_clr_row(row);\lcd_write(row, colum, buf, strlen(buf));}while(0)

发现,该函数是一个宏定义的函数,args表示参数缺省,首先先将将数组buf清空
int sprintf(char *str, const char *format, …) 发送格式化输出到 str 所指向的字符串
也就是让buf的值 = fmt的值 = Input Card pwd:
接着调用函数lcd_clr_row(row),看这名字,应该是lcd显示清空,row为行号
接着往lcd里面开始写入数据,我们先来看函数lcd_clr_row(row),如下

lcd_clr_row

 void lcd_clr_row(unsigned char row)
{unsigned char i;//CHAR_ROW_PIXEL = 16,LCD_PAGE_ROW_NUM = 8lcd_set_dsp_position(row*(CHAR_ROW_PIXEL/LCD_PAGE_ROW_NUM), 0);                       //选中左屏//LCD_COLUMN_PIXEL_SUM = 128for(i = 0; i < LCD_COLUMN_PIXEL_SUM/2; i++){    //一行两页,一次清除一页,其中一次只能清除8像素行,需要循环64次,清除lcd_write_data(0, CONCTROLLER_CS1);       //也就是清除row的内容.}lcd_set_dsp_position(row*(CHAR_ROW_PIXEL/LCD_PAGE_ROW_NUM) + 1, 0);                 for(i = 0; i < LCD_COLUMN_PIXEL_SUM/2; i++){lcd_write_data(0, CONCTROLLER_CS1);}lcd_set_dsp_position(row*(CHAR_ROW_PIXEL/LCD_PAGE_ROW_NUM), 64);                      //选中右屏for(i = 0; i < LCD_COLUMN_PIXEL_SUM/2; i++){lcd_write_data(0, CONCTROLLER_CS2);}lcd_set_dsp_position(row*(CHAR_ROW_PIXEL/LCD_PAGE_ROW_NUM) + 1, 64);for(i = 0; i < LCD_COLUMN_PIXEL_SUM/2; i++){lcd_write_data(0, CONCTROLLER_CS2);}
}

首先,根据上面传递的参数,row的值为0,表示选中左屏,那么一开始lcd_set_dsp_position(0,0),进入for循环,重复64次写入数据1,其中,CONCTROLLER_CS1 为1,CONCTROLLER_CS2为2。第二次的是lcd_set_dsp_position(1, 0),重复64次写入数据1。接着就是lcd_set_dsp_position(0, 64)和lcd_set_dsp_position(1, 64);这里我们有必要看看函数lcd_set_dsp_position,如下

lcd_set_dsp_position

/* set display positionpage: page num(0~7), column:column pixel num(0~127)*/
void lcd_set_dsp_position(unsigned char page, unsigned char column)
{unsigned char controller_cs;if( column >= LCD_COLUMN_PIXEL_SUM/2 )controller_cs = CONCTROLLER_CS2;else    controller_cs = CONCTROLLER_CS1;lcd_write_cmd(0xC0, controller_cs); //rowlcd_write_cmd(0x40 + (column & 0x3F), controller_cs);                 //collcd_write_cmd(0xB8 + (page & 0x07), controller_cs);                    //page
}

根据前面,我们知道page的范围是0-7,column像素的范围是0-127 (16行8个像素),首先往0xC0这个地址写入片选数据1,接着往0x40写入数据1,往0xB8 写入数据1,这里,我们研究左屏。0xC0表示设备起始行的地址,0x40表示设备的列地址,0xB8表示页地址。现在我们不难理解,这段函数的功能,那就是选中对应的显示位置。
lcd_write_data(0,1),数据为0表示清除该数据。
这里,这个函数的功能是清除第row行,那么如果我们要清除全部行(4行)怎么写呢?

lcd_clr

 void lcd_clr(void)
{unsigned char i, x=0;for(x=0; x<8; x++){lcd_set_dsp_position(x, 0);                       //选中左屏//clean all lcd//8 times = 8 page  left 64bit right 64bit // one page 8 pixel row 64 columnfor(i=0; i<64; i++){//clean one column 8 pixel rowlcd_write_data(0, CONCTROLLER_CS1); }lcd_set_dsp_position(x, 64);                      //选中右屏for(i=0; i<64; i++){lcd_write_data(0, CONCTROLLER_CS2);}}
}

这里,一次lcd_wirte_data,只能清除1列,8像素行(1页),所以x循环8次8页,循环128次128列。

lcd_write

/*row num(0~3), column num(0~15), lcd can display 4*16 chars*/
int lcd_write(unsigned char row, unsigned char column, char* data, unsigned char len)
{unsigned char controller_cs;   unsigned char page_addr_cmd;    unsigned char column_addr_cmd;  unsigned char i,j,page_index,column_index;  unsigned char code_idx1,code_idx2;  if((row > LCD_ROW_NUM -1 ) || (column > LCD_COLUMN_NUM - 1) || (data == NULL)){return -1;   }if((len + column) > LCD_COLUMN_NUM){len = LCD_COLUMN_NUM - column;    //超出范围,那么超出的部分不显示}//128*64//for (page_index=0;page_index<2;page_index++)for(page_index = 0; page_index < (CHAR_ROW_PIXEL/LCD_PAGE_ROW_NUM); page_index++){//for (column_index = 0,i=0;column_index<(3);column_index++,i++)for(column_index = column, i = 0; column_index < (column + len); column_index++, i++){//if (column_index>=16/2=8)if(column_index >= (LCD_COLUMN_NUM / 2)){controller_cs = CONCTROLLER_CS2;    //2}else{controller_cs = CONCTROLLER_CS1;  //1}lcd_write_cmd(0xC0, controller_cs);     //行地址page_addr_cmd = 0xB8 | row*(CHAR_ROW_PIXEL/LCD_PAGE_ROW_NUM) + page_index;   //页地址lcd_write_cmd(page_addr_cmd, controller_cs);   //写入页地址column_addr_cmd = 0x40 | ((column_index * CHAR_COLUMN_PIXEL) & 0x3f);   //列地址lcd_write_cmd(column_addr_cmd, controller_cs);//send data to lcdif(data[i] & 0x80){//chineseprintf("not support display chinese\r\n");}else{//CHAR_COLUMN_PIXEL = 8for(j = 0; j < CHAR_COLUMN_PIXEL; j++){code_idx1 = data[i]-ASCILL_TO_CODE_INDEX;  //32code_idx2 = j+LCD_PAGE_ROW_NUM*page_index;//j + 8 x page_indexlcd_write_data(char_code_8x16[code_idx1][code_idx2], controller_cs);}}}}return 0;
}

这段代码的意思就是,每一次写数据,假设data[] = “input”,前面说过,一个字符是宽8x高16个像素点,高16个像素点,就占两页,也就是外循环需要两次,内循环是字符串的长度列,其中每一列占8个像素点,就是最内层的j循环8次,j循环结束后,也就是1页 8x8个像素点。lcd_write_data是数据写入。

除了以上数据写入之外,我们还需要对液晶的初始化,如下

lcd_init

void lcd_init (void)
{lcd_gpio_init();   //引脚的初始化//打开背光GPIO_ResetBits(GPIOD, LCD_BL);    //BL = 0//resetGPIO_ResetBits(GPIOD, LCD_RST); //RST = 0,复位delay_ms(100);GPIO_SetBits(GPIOD, LCD_RST); //RST = 1delay_ms(100);GPIO_ResetBits(GPIOE, LCD_E);   //E = 0 使能delay_us(1);lcd_write_cmd(0xC0, CONCTROLLER_CS1);                            //设置显示起始行(左)lcd_write_cmd(0x3F, CONCTROLLER_CS1);                            //显示打开lcd_write_cmd(0xC0, CONCTROLLER_CS2);                             //设置显示起始行(右)lcd_write_cmd(0x3F, CONCTROLLER_CS2);                           //显示打开lcd_clr();                                                        //清屏
}

STM32液晶显示完整代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "systick.h"
#include "LCD12864.h"
#define CONCTROLLER_CS1 1
#define CONCTROLLER_CS2 2
int main( void )
{lcd_init();    //lcd_initshow_logo();  //显示logo}
void lcd_init (void)
{lcd_gpio_init();//打开背光GPIO_ResetBits(GPIOD, LCD_BL);//resetGPIO_ResetBits(GPIOD, LCD_RST);delay_ms(100);GPIO_SetBits(GPIOD, LCD_RST);delay_ms(100);GPIO_ResetBits(GPIOE, LCD_E);delay_us(1);lcd_write_cmd(0xC0, CONCTROLLER_CS1);                            //set first row adr leftlcd_write_cmd(0x3F, CONCTROLLER_CS1);                            //show openlcd_write_cmd(0xC0, CONCTROLLER_CS2);                          //set first row adr rightlcd_write_cmd(0x3F, CONCTROLLER_CS2);                          //show openlcd_clr();                                           //clear lcd
}
void show_logo(void)
{lcd_disp_full_img(newLandEduLogo); //myname是一维字符数组,大小是16 * 64delay_ms(1000);   //延时1000mslcd_clr();    //清除lcd内容
}
void lcd_disp_full_img(unsigned char *img)
{//img一维数组,需要自己使用字摸工具,使用。unsigned char i=0,j=0;for(i=0;i<8;i++){lcd_set_dsp_position(i, 0);                  //一次性一页,一共八页for(j=0;j<128;j++){if( j == 64 ){lcd_set_dsp_position(i, j);                   //选中右屏}if(j < 64)lcd_write_data(*img, CONCTROLLER_CS1);    //一次一页,因为数据引脚8位elselcd_write_data(*img, CONCTROLLER_CS2);img++;   //img++,指向下一个位置}}
}
void lcd_set_dsp_position(unsigned char page, unsigned char column)
{unsigned char controller_cs;if( column >= LCD_COLUMN_PIXEL_SUM/2 )controller_cs = CONCTROLLER_CS2;    //2elsecontroller_cs = CONCTROLLER_CS1;    //1lcd_write_cmd(0xC0, controller_cs);  //0x40 + 0x80 = 0xc0 row//µÚÒ»ÐеĵØÖ·ÊÇ80H = 0x80   lcd_write_cmd(0x40 + (column & 0x3F), controller_cs);                 //collcd_write_cmd(0xB8 + (page & 0x07), controller_cs);                    //page
}
void lcd_write_cmd(unsigned char cmd, unsigned char controller_cs)
{uint16_t data;if(controller_cs != CONCTROLLER_CS1 && controller_cs != CONCTROLLER_CS2) {printf("controller_cs(%d)error...\r\n", controller_cs);return;}//while(is_lcd_busy(controller_cs));GPIO_SetBits(GPIOD, LCD_RW);    // RW= 1set_lcd_data_gpio_to_output();//init lcd_rw outputGPIO_ResetBits(GPIOD, LCD_RS);   //RS = 1if(controller_cs == CONCTROLLER_CS1)GPIO_SetBits(GPIOD, LCD_CS1);elseGPIO_SetBits(GPIOD, LCD_CS2);GPIO_ResetBits(GPIOD, LCD_RW); //RW = 0data = GPIO_ReadInputData(GPIOE);data &= 0x00ff;data |= (cmd << 8);GPIO_Write(GPIOE, data);GPIO_SetBits(GPIOE, LCD_E);delay_us(1);GPIO_ResetBits(GPIOE, LCD_E);delay_us(1);GPIO_SetBits(GPIOD, LCD_RW);if(controller_cs == CONCTROLLER_CS1)GPIO_ResetBits(GPIOD, LCD_CS1);else if(controller_cs == CONCTROLLER_CS2)GPIO_ResetBits(GPIOD, LCD_CS2);
}
/* send lcd data to show */
void lcd_write_data(unsigned char wdata, unsigned char controller_cs)
{uint16_t data;if(controller_cs != CONCTROLLER_CS1 && controller_cs != CONCTROLLER_CS2) {printf("controller_cs(%d)error...\r\n", controller_cs);return;}//while(is_lcd_busy(controller_cs));GPIO_SetBits(GPIOD, LCD_RW);set_lcd_data_gpio_to_output();  //É豸Êý¾ÝÒý½ÅGPIO_SetBits(GPIOD, LCD_RS);if(controller_cs == CONCTROLLER_CS1)GPIO_SetBits(GPIOD, LCD_CS1);elseGPIO_SetBits(GPIOD, LCD_CS2);GPIO_ResetBits(GPIOD, LCD_RW);data = GPIO_ReadInputData(GPIOE);  //读取数据data &= 0x00ff;  //取低8位data |= (wdata << 8);  //wadata = 0x40GPIO_Write(GPIOE, data);    //写入数据GPIO_SetBits(GPIOE, LCD_E);delay_us(1);GPIO_ResetBits(GPIOE, LCD_E);delay_us(1);GPIO_SetBits(GPIOD, LCD_RW);if(controller_cs == CONCTROLLER_CS1)GPIO_ResetBits(GPIOD, LCD_CS1);elseGPIO_ResetBits(GPIOD, LCD_CS2);
}
unsigned char newLandEduLogo[]=
{//New land edu logo,128*64
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,
0xFE,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x60,0xE0,0xE0,0x78,0x78,0xE0,0xE0,0x60,0x60,0xE0,0xE0,0x60,0x60,0x60,
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,
0xC0,0xC0,0xE0,0xE0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xF0,0xF0,
0xF0,0xE0,0xC0,0xE0,0x20,0xE0,0xF0,0xF0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,
0x60,0x60,0x60,0xE0,0xE0,0xE0,0xE0,0x70,0x70,0x70,0x60,0xE0,0xE0,0x60,0x60,0x60,
0x00,0xC0,0xE0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF8,0xF8,0xE0,0xE0,0x80,0x80,
0x00,0x00,0xFA,0xFA,0xFB,0xFF,0xFE,0xFF,0xFB,0x9A,0x9A,0xFF,0xFF,0x02,0xFE,0xFE,
0xFE,0x02,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x83,0xE3,0xFB,0xFF,0xFF,0xFF,0x83,
0x83,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xBF,0xFF,0xE0,0xE6,0xE6,
0xE6,0x06,0xFF,0xFF,0x06,0xE6,0xE6,0x06,0x00,0x00,0x00,0x00,0xBA,0x9A,0x9F,0xDF,
0xFF,0xFF,0xBB,0xBB,0x03,0x1F,0x7F,0xF8,0xF0,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,
0x00,0xFB,0xFB,0xFB,0x6B,0x6B,0x6B,0x6B,0x6B,0x6B,0x6B,0x6B,0xFB,0xFB,0x02,0x00,
0x00,0x00,0x01,0x03,0x87,0x8F,0xCF,0xEF,0x33,0xBB,0xCC,0xEE,0x31,0xBB,0xC7,0xEF,
0x1F,0xBF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xBF,0x9F,0x0F,0x07,0x03,0x01,0x00,
0x00,0x00,0x0F,0x07,0x03,0x0F,0x0F,0x0F,0x01,0x03,0x07,0x07,0x03,0x00,0x0F,0x0F,
0x0F,0x00,0x00,0x00,0x00,0x0C,0x0E,0x06,0x07,0x03,0x03,0x01,0x00,0x00,0x03,0x03,
0x07,0x06,0x06,0x0E,0x0C,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x01,0x01,0x01,0x07,0x0F,
0x0F,0x0C,0x0F,0x0F,0x0C,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x01,0x0D,0x0D,0x0F,
0x0F,0x07,0x00,0x0C,0x0E,0x06,0x03,0x03,0x03,0x07,0x06,0x0E,0x00,0x00,0x00,0x00,
0x00,0x0F,0x0F,0x0F,0x03,0x03,0x03,0x03,0x03,0x03,0x0B,0x0F,0x0F,0x0F,0x00,0x00,
0x00,0x0C,0x0E,0x37,0x3B,0xDB,0xEC,0xEE,0x33,0xFB,0xCC,0xEE,0x33,0xBB,0xCC,0xEE,
0x33,0xBB,0xCC,0xEF,0x33,0xBB,0xCC,0xEE,0x33,0xBB,0xCC,0xEE,0x26,0x3A,0x18,0x00,
0x00,0x00,0xFE,0xFE,0x3E,0x78,0xF0,0xC0,0xFE,0xFE,0xFE,0xE0,0xF8,0xB8,0x98,0xD8,
0xF8,0x78,0xB8,0x28,0xF8,0xF0,0x80,0xE0,0xF8,0xF8,0xE0,0xC0,0xF8,0x38,0xFE,0xFE,
0xFE,0xE0,0xF8,0x38,0x38,0x18,0x18,0x38,0xF8,0xE0,0xE0,0xF0,0xF8,0x38,0x18,0x38,
0xF8,0xE0,0xE0,0xF0,0xF8,0x38,0x18,0x18,0x38,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xFE,0xFE,0x66,0x66,0x66,0x66,0x66,0x06,0x00,0xE0,0xF8,0x38,0x18,
0x18,0x38,0x00,0xFE,0xFE,0x00,0xF8,0xF8,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03,0x0B,0x0C,0x2E,0x33,0xBB,0xCC,0xEE,
0x33,0xBB,0xCC,0xEE,0x33,0x3B,0x0C,0x0E,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x0F,0x0F,0x00,0x00,0x01,0x03,0x0F,0x0F,0x0F,0x01,0x07,0x07,0x0F,0x0C,
0x0E,0x06,0x07,0x00,0x00,0x03,0x0F,0x07,0x01,0x03,0x0F,0x0F,0x03,0x00,0x0F,0x0F,
0x0F,0x01,0x07,0x07,0x0E,0x0E,0x0E,0x06,0x0F,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,
0x0F,0x0F,0x03,0x03,0x0F,0x0E,0x0E,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x00,0x03,0x07,0x0E,0x0E,
0x0E,0x0E,0x07,0x03,0x00,0x00,0x03,0x0F,0x0E,0x0E,0x0E,0x0F,0x07,0x03,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

总结

通过以上,我们掌握了基本的LCD使用方法。但这里,我们把LCD封装成函数,那么我们只要关心如何调用就好,如下:

  • show_logo() 显示logo,使用字摸工具128*64
  • LCD_PRINT(0,0,lcd_show,“Connect to sever”); 第0行0列,字符数组,显示的内容
  • lcd_clr_row(row) 清除第row行的内容(0-3)
  • lcd_clr(); //清除lcd所有内容

疑惑

每个GOIP口都有16个引脚,那么上述中的

data = GPIO_ReadInputData(GPIOE);
data &= 0x00ff;
data |= (cmd << 8);
其中cmd假设是0x40,无符号字符型,首先读取GPIOE的数据,存储到data,而data是两个字节的数据,接着跟0x00ff按位与,那么必然舍弃高8位,假设读取到的数据是0101 0101 1110 1110,那么按位与之后就是0000 0000 1110 1110,接着
data = data | (cmd<<8),疑惑就是cmd是8位的数据,往左移8位,按C语言语法来看,左移8位,低位自动补0,那么需要数据cmd的作用是什么?

这里,我猜测可能是编译器问题,当cmd的精度不够,它会自动转换成精度更高的数据类型,这里是uint16_t

基于STM32的12864液晶理解相关推荐

  1. 基于s3c2440的12864液晶驱动

    基于s3c2440的12864液晶驱动 12864是12864点阵液晶模块的点阵数简称,业界约定俗成的简称. 一.液晶显示模块概述 12864A-1 汉字图形点阵液晶显示模块,可显示汉字及图形,内置 ...

  2. STM32的12864液晶串行控制

    发现12864只有主函数中不断刷新才有数据显示,,原因是写指令和写数据中没有加延时,加一个延时就好了. 转载于:https://www.cnblogs.com/zhayunjia/p/3863502. ...

  3. 12864液晶深入学习笔记_1——基于msp430g2553

    12864液晶学习笔记 Created on: 2012-8-30 Author: zhang bin 这是我对12864的学习笔记,12864液晶功能很全面,使用起来也很方便,能够满足一般的研究和工 ...

  4. 关于基于stm32的0.96寸oled显示屏的学习理解心得。

    关于基于stm32的0.96寸oled显示屏的学习理解心得. oled粗了解 如何理解OLED分辨率? 这里0.96寸OLED分辨率是12864;即OLED显示是128行64列; 但是由于OLED不能 ...

  5. STM32驱动ST7920的12864液晶(串行方式)

    /****************************************************************************************** * 文件名称 : ...

  6. stm32捕获占空比_基于STM32超声波避障小车

    不管是对于初学者还是对于一个玩过单片机的电子爱好者来说,或多或少都接触到过小车项目,今天给大家介绍的的一个项目基于STM32超声波避障小车.这也是我曾经的一个课设,在此开源分享给大家,全文5000多字 ...

  7. stm32 带通滤波器_带通滤波 - 基于STM32芯片和TFT-LCD的便携式心电图仪设计

    相关推荐 3月10日,纽约州州长安德鲁-库默(Andrew Cuomo)曾在上月宣布,纽约大都市圈的公共交通系... 发表于 2018-04-16 08:50 • 88次阅读 LCD驱动我们只需要写硬 ...

  8. 基于STM32与OneNet平台的智能家居系统设计(代码开源含自制APP代码)

     前言:本文为手把手教学的基础物联网开发设计,项目包含对下位机(MCU对外设数据读取与控制)和上位机(包含服务平台和APP端)的设计.下位机选取STM32作为MCU,外设有LED灯和DHT11温湿度传 ...

  9. 基于STM32的OLED多级菜单GUI实现(简化版智能手表)

    前言:本文的OLED多级菜单UI为一个综合性的STM32小项目,使用多传感器与OLED显示屏实现智能终端的效果.项目中的多级菜单UI使用了较为常见的结构体索引法去实现功能与功能之间的来回切换,搭配DH ...

最新文章

  1. 微软软件测试的可借鉴之处
  2. JavaScript window.getComputedStyle()
  3. 739. Daily Temperatures - LeetCode
  4. 无法识别的属性“targetFramework”。请注意属性名称区分大小写。
  5. 虚拟化精华问答 | 如何为虚拟机分配任务?
  6. 网站服务器一般是多少宽带,服务器宽带一般是多少
  7. apms阅卷系统服务器,Win 8系统运行APMS阅卷系统的解决办法
  8. 科研热点|官宣!2022年JCR分区和影响因子发布时间确定!
  9. 【区块链108将】区块链为传统创业孵化器带来新机遇
  10. 如何成功对接APP项目资源
  11. 必应壁纸php,PHP版Bing壁纸下载源码
  12. 姜维拥兵10万 为何守不住刘备的半壁江山
  13. vue预览word,excel,pptx,pdf文件
  14. 关于研发过程中测试工作的一些思考
  15. android otg读写文件,Android USB Host在USB设备OTG中读/写文件
  16. 什么是重排和重绘?何时会触发?
  17. 腾讯云香港轻量新IP段简单测评
  18. 小侃设计模式(十五)-命令模式
  19. 技术揭秘 | 互联网广告黑产盛行,如何反作弊?
  20. 恶意软件及其类型(病毒、蠕虫、木马、间谍软件、勒索软件、恐吓软件、Bots和Rootkits等)的介绍

热门文章

  1. [QDialog]qt虚拟键盘的实现以及qdateedit实现打开虚拟键盘
  2. 基于summernote的富文本编辑器,粘贴时去除word格式
  3. RubyProgramming:向Ruby之父学程序设计pdf
  4. java是什么?好学吗?
  5. 【IDEA】出现 Wrong tag ‘Author_‘ 错误的 Author 标签等的黄色警告问题
  6. 计算机导论部分知识整理
  7. 查看本机MAC地址的方法
  8. ASP.NET Web应用程序发布到IIS
  9. Python黑白转换程序
  10. TypeScript 初学者指南