STM32F4_LCD12864串行并行驱动程序合集

更新时间:2024-06-21 16:32:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

LCD12864.c文件:

/********************************************************** * @ File name -> lcd12864.c * @ Version -> V1.1

* @ Date -> 07-15-2017

* @ Brief -> LCD12864驱动函数

* 适用于ST7920驱动芯片

V1.0

* @ Revise -> A、修正操作命令宏定义。 * @ -> B、显示字符串函数增加显示长度选择,即显示多少个ASCII可显示字符,汉字x2即可

* @ -> C、去掉显示数组函数,合并在字符串显示里

V1.1

* @ Revise -> A、增加STM32硬件SPI控制接口

* @ -> B、修正STM32并口控制LCD12864接口(但未测试)

**********************************************************/

#include \

/********************************************************** 自定义显示字符

**********************************************************/

#define CGRAM_Value 64 //写入CGRAM数量

u8 CGROM_Code[] = {

//电量100Percent(add_h=0,add_l=0)

0x00,0x00,0x00,0x00,0xFF,0xFE,0x80,0x02,0xB6,0xDA,0xB6,0xDB,0xB6,0xDB,0xB6,0xDB, 0xB6,0xDB,0xB6,0xDB,0xB6,0xDB,0xB6,0xDA,0x80,0x02,0xFF,0xFE,0x00,0x00,0x00,0x00, //月亮图形(add_h=0,add_l=2)

0x01,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x3C,0x00,0x78,0x00,0x78,0x00,0x78,0x00,

0x78,0x00,0x7C,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x03,0xF0,0x00,0x30, //存储设备(add_h=0,add_l=4) 0x00,0x00,0x0F,0xF8,0x08,0x08,0x0B,0x68,0x08,0x08,0x3F,0xFE,0x3F,0xFE,0x3F,0xFE, 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1F,0xFC,0x0F,0xF8,0x07,0xF0,0x03,0xE0, //天线图形(add_h=0,add_l=6)

0x10,0x10,0x20,0x08,0x40,0x04,0x84,0x42,0x88,0x22,0x90,0x12,0x93,0x92,0x93,0x92,

0x91,0x12,0x88,0x22,0x85,0x42,0x41,0x04,0x21,0x08,0x11,0x10,0x03,0x80,0x03,0x80

//CD图形

//0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0x07,0xc9,0xb3,0x9d,0xb9,0x9f,0xb9,0x9f,0xb9,

//0x9f,0xb9,0x9f,0xb9,0x9d,0xb9,0xc9,0xb3,0xe3,0x07,0xff,0xff,0xff,0xff,0xff,0xff,

//右指向手型

//0x00,0x00,0x1e,0x00,0x12,0x00,0x73,0xfc,0x52,0x02,0x52,0x1c,0x53,0xe0,0x52,0x10,

//0x53,0xe0,0x52,0x10,0x53,0xe0,0x52,0x10,0x73,0xe0,0x12,0x00,0x1e,0x00,0x00,0x00

//摄氏图形

//0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x70,0x14,0xd8,0x1d,0x88,0x01,0x80,0x01,0x80, //0x01,0x80,0x01,0x80,0x01,0x88,0x00,0xc8,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,

//天线图形1

//0xff,0xff,0x80,0x01,0xbf,0xfd,0xdf,0xfb,0xec,0x37,0xf6,0x6f,0xfb,0xdf,0xfd,0xbf, //0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xff,0xff, //蓝牙图形 //0x07,0xe0,0x0e,0x70,0x1e,0xb8,0x3e,0xdc,0x36,0xec,0x3a,0xdc,0x3c,0xbc,0x3e,0x7c, //0x3e,0x7c,0x3c,0xbc,0x3a,0xdc,0x36,0xec,0x3e,0xdc,0x1e,0xb8,0x0e,0x70,0x07,0xe0, };

u8 const ClearCGRAM[] = {

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

u8 const SunIcon[] = { 0x00,0x80,0x40,0x82,0x20,0x84,0x10,0x08,0x03,0xC0,0x07,0xE0,0x0F,0xF0,0xEF,0xF7, 0x0F,0xF0,0x0F,0xF0,0x07,0xE0,0x03,0xC0,0x10,0x08,0x20,0x84,0x40,0x82,0x00,0x80 };

u8 const MoonIcon[] = {

0x01,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x3C,0x00,0x78,0x00,0x78,0x00,0x78,0x00, 0x78,0x00,0x7C,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x03,0xF0,0x00,0x30, };

u8 const AntennaIcon[] = { 0x10,0x10,0x20,0x08,0x40,0x04,0x84,0x42,0x88,0x22,0x90,0x12,0x93,0x92,0x93,0x92, 0x91,0x12,0x88,0x22,0x85,0x42,0x41,0x04,0x21,0x08,0x11,0x10,0x03,0x80,0x03,0x80 };

u8 const WIFIConnection[] = {

0x00,0x00,0x00,0x00,0x0F,0xF0,0x3F,0xFC,0x70,0x0E,0xE0,0x07,0x07,0xE0,0x0F,0xF0, 0x1C,0x38,0x00,0x00,0x01,0x80,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00,0x00,0x00 };

u8 const Battery_100Percent[] = {

0x00,0x00,0x00,0x00,0xFF,0xFE,0x80,0x02,0xB6,0xDA,0xB6,0xDB,0xB6,0xDB,0xB6,0xDB, 0xB6,0xDB,0xB6,0xDB,0xB6,0xDB,0xB6,0xDA,0x80,0x02,0xFF,0xFE,0x00,0x00,0x00,0x00 };

u8 const Battery_80Percent[] = {

0x00,0x00,0x00,0x00,0xFF,0xFE,0x80,0x02,0xB6,0xC2,0xB6,0xC3,0xB6,0xC3,0xB6,0xC3, 0xB6,0xC3,0xB6,0xC3,0xB6,0xC3,0xB6,0xC2,0x80,0x02,0xFF,0xFE,0x00,0x00,0x00,0x00 };

u8 const Battery_60Percent[] = {

0x00,0x00,0x00,0x00,0xFF,0xFE,0x80,0x02,0xB6,0x02,0xB6,0x03,0xB6,0x03,0xB6,0x03, 0xB6,0x03,0xB6,0x03,0xB6,0x03,0xB6,0x02,0x80,0x02,0xFF,0xFE,0x00,0x00,0x00,0x00 };

u8 const Battery_40Percent[] = {

0x00,0x00,0x00,0x00,0xFF,0xFE,0x80,0x02,0xB0,0x02,0xB0,0x03,0xB0,0x03,0xB0,0x03, 0xB0,0x03,0xB0,0x03,0xB0,0x03,0xB0,0x02,0x80,0x02,0xFF,0xFE,0x00,0x00,0x00,0x00 };

u8 const Battery_20Percent[] = {

0x00,0x00,0x00,0x00,0xFF,0xFE,0x80,0x02,0x80,0x02,0x80,0x03,0x80,0x03,0x80,0x03, 0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x02,0x80,0x02,0xFF,0xFE,0x00,0x00,0x00,0x00 };

u8 const ASCII_Table[] = {

0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,/*\

0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00,/*\

0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00,/*\ 0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00,/*\,3*/ 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,0x44,0x44,0x7E,0x04,0x04,0x1E,0x00,0x00,/*\,4*/ 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,/*\,5*/ 0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00,/*\,6*/ 0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,/*\,7*/ 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00,/*\,8*/ 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1A,0x02,0x02,0x24,0x38,0x00,0x00 /*\};

u8 LCD12864_LockedFlag; //LCD12864 locked flag

//=========================================================

void LCD_delay_1us() { int i = 200; //最小90可以稳定工作 while (i--); }

void LCD_delay_nus(int nus) { while (nus--)LCD_delay_1us(); }

#ifdef LCD_Work_Mode_Parallel //如果定义了,则使用并口工作模式

GPIO_InitTypeDef GPIOStru; //定义用于定义所以引脚为输出的变量

//=========================================================

/********************************************************** * 函数功能 --->把所有数据端口初始化为推挽输出模式的函数。 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCDDataBus_OUT(void) { RCC_APB2PeriphClockCmd(DataBusGPIOCLK,ENABLE);

GPIOStru.GPIO_Pin = DataBusPins; //LCD数据端口对应的引脚 GPIOStru.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIOStru.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIOStru.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIOStru.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(DataBusGPIO,&GPIOStru); }

/********************************************************** * 函数功能 --->把数据引脚初始化为浮空输入的函数 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCDDataBus_IN(void) { RCC_APB2PeriphClockCmd(DataBusGPIOCLK,ENABLE);

GPIOStru.GPIO_Pin = DataBusPins; //LCD数据端口对应的引脚 GPIOStru.GPIO_Mode = GPIO_Mode_IN; //普通输入模式 GPIOStru.GPIO_OType = GPIO_OType_OD; //开漏模式 GPIOStru.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIOStru.GPIO_PuPd = GPIO_PuPd_NOPULL; //无上下拉 GPIO_Init(DataBusGPIO,&GPIOStru); }

/********************************************************** * 函数功能 ---> LCD12864判断忙 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/

void LCD_Check_Busy(void) { static u16 busytimeout; //忙超时

//===================================================== LCDDataBus_IN(); //把数据引脚定义为浮空输入 do { busytimeout++; if(busytimeout > 300) break; LCD_RS = 0; LCD_Delay(); LCD_RW = 1; LCD_Delay(); LCD_EN = 1; LCD_Delay(); }while(GPIO_ReadInputData(DataBusGPIO) & DataBusPin7); //等待LCD忙完 LCD_EN = 0; LCDDataBus_OUT(); //把数据引脚定义为输出

//===================================================== if(busytimeout >= 300) printf(\ busytimeout = 0; }

/**********************************************************

* 函数功能 ---> LCD写入一个字节命令或者数据,判断忙标志(8位数据一次发送完毕) * 入口参数 ---> dat:要写入的字节

* ord:判断dat是命令还是数据依据,“0”为命令,“1”为数据 * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Write_Byte(u8 dat,u8 ord) {

//=====================================================

LCD_Check_Busy(); //判断是否在忙? LCD_EN = 0; LCD_Delay(); LCD_RW = 0; LCD_Delay();

if(ord & 0x01) LCD_RS = 1; //放上数据或者命令判断位 else LCD_RS = 0; LCD_EN = 1; LCD_Delay(); LCDWriteData(dat); //放入数据 LCD_Delay(); LCD_EN = 0;

//===================================================== }

//=========================================================

#else //没定义则使用串口通讯模式

#ifdef LCD_Work_Mode_HardSPI //串行模式-采用硬件SPI

//========================================================= /**********************************************************

* 函数功能 --->初始化硬件SPI1模块,配置为主机模式 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,

ENABLE); //使能GPIOB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //使能SPI1时钟 //GPIOB3,5初始化设置(仅使用SCK,MOSI引脚) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5; //PB3~5复用功能输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed =

GPIO_Speed_100MHz; //100MHz //上拉

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB,

&GPIO_InitStructure);

//初始化 GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3复用为 SPI1(SCK)

//GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4复用为 SPI1(MISO)

GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5复用为 SPI1(MOSI) //这里只针对SPI口初始化

RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE); //复位SPI1 RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE); //停止复位SPI1

SPI_InitStructure.SPI_Direction

=

SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 //LCD1286时钟为上升沿有效,而且必须保证第一个上升沿也有数据,这里是调试的难点 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个上升沿数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler =

SPI_BaudRatePrescaler_2; //定义波特率预分频的值:波特率预分频值为16 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI1, ENABLE); //使能SPI外设

}

/**********************************************************

* 函数功能 ---> LCD写入一个字节命令或者数据 * 入口参数 ---> dat:要写入的命令或者数据

* ord:命令或者数据判断为。0为命令,1为数

* 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Write_Byte(u8 dat,u8 ord) { u8 lcd_data_msb,lcd_data_lsb; lcd_data_msb = 0xf0&dat; lcd_data_lsb = (0x0f&dat)<<4;

if(ord == 0)//写命令 {

while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET); //等待SPI1发送缓存空

SPI_I2S_SendData(SPI1,0xf8); //SPI1发送数据--命令指令-- }

else//写数据 {

while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET); //等待SPI1发送缓存空

SPI_I2S_SendData(SPI1,0xfa); //SPI1发送数据--数据指令 } LCD_delay_nus(73); //LCD12864响应时间73us while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//等待SPI1发送缓存空 SPI_I2S_SendData(SPI1,lcd_data_msb); //SPI1发送数据--数据指令 LCD_delay_nus(73); //LCD12864响应时间73us while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//等待SPI1发送缓存空 SPI_I2S_SendData(SPI1,lcd_data_lsb); //SPI1发送数据--数据指令 LCD_delay_nus(73); //LCD12864响应时间73us }

//========================================================= #else //GPIO模拟SPI //========================================================= /**********************************************************

* 函数功能 ---> LCD启动字节 * 入口参数 ---> dt:传输的字节,高5位在函数内部设定为1 * 只是确定RW和RS为,最后那位也是内部确定 * 返回数值 ---> none * 功能说明 --->首先传送一个启动字节,送入连续5个“1”用来启 * 动一个周期,此时传输计数被重置,并且串行传输 * 被同步,紧接着的两个位指定传输方向(R/W,确 * 定是读还是写)和传输性质(RS,确定是命令寄存 * 器还是数据寄存器),最后的第八位是一个“0” **********************************************************/ void LCD12864_Start(u8 dt) { u8 dat,j; dat = dt | 0xf8; //高5位设定为“1”,第八位设定为“0” LCD_SCL = 0; LCD_Delay();LCD_Delay();

LCD_CS = 1; //选中显示屏,高电平有效 for(j = 0;j < 8;j++) {

LCD_SCL = 1; //发送数据,上升沿有if(dat & 0x80) LCD_SDA = 1; //放数据到else LCD_SDA = 0;

数据线 LCD_Delay();LCD_Delay();LCD_Delay(); 效

LCD_Delay();LCD_Delay();LCD_Delay(); LCD_SCL = 0; dat <<= 1; //左移一位,先发的是高位 } LCD_Delay();LCD_Delay();LCD_Delay(); LCD_SCL = 0; LCD_Delay();LCD_Delay();LCD_Delay(); //等待硬件反应(等待数据发送完全) } /********************************************************** 据

* 函数功能 ---> LCD写入一个字节命令或者数据 * 入口参数 ---> dat:要写入的命令或者数据

* ord:命令或者数据判断为。0为命令,1为数

* 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Write_Byte(u8 dat,u8 ord) { u8 tem; u8 i,j;

tem = dat & 0xf0; //先发送高4位 LCD12864_Start((ord << 1) | 0xf0); //置RW为“0”、RS为“ord”并启动串行传输为数据格式 for(j = 0;j < 2;j++) //一个字节数据或者命令分两次发送 { 化 LCD_Delay();LCD_Delay();LCD_Delay(); 放上数据,屏蔽低4位

LCD_SCL = 0; //允许数据线电平变

for(i = 0;i < 8;i++) { if(tem & 0x80) LCD_SDA = 1; //

else LCD_SDA = 0;

LCD_Delay();LCD_Delay();LCD_Delay();

}

LCD_SCL = 0;

tem <<= 1; //左移一位,先

LCD_SCL = 1; //发送数据,上升

沿有效 LCD_Delay();LCD_Delay();LCD_Delay(); 发的是高位

tem = (dat << 4) & 0xf0; //发完高4位,再次发送低4位 } LCD_Delay();LCD_Delay();LCD_Delay(); LCD_SDA = 0; LCD_Delay();LCD_Delay();LCD_Delay(); LCD_SCL = 0; LCD_Delay();LCD_Delay();LCD_Delay(); LCD_CS = 0; LCD_Delay();LCD_Delay();LCD_Delay(); //等待硬件反应(等待数据发送完全) } //========================================================= #endif #endif

//=========================================================

/**********************************************************

* 函数功能 --->设置LCD显示位置

* 入口参数 ---> x:行,取值范围:1 ~ 4 * y:列,取值范围:0 ~ 7 * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Set_xy(u8 x,u8 y) { switch(x) { case 1: LCD_Write_Byte((One_LineAddress + y),0); //写入操作地址 break; case 2:

case 3: case 4: default:

LCD_Write_Byte((Two_LineAddress + y),0); //写入操作地址 break;

LCD_Write_Byte((Three_LineAddress + y),0); break;

//写入操作地址

LCD_Write_Byte((Four_LineAddress + y),0); //写入操作地址 break;

LCD_Write_Byte((One_LineAddress + y),0); //写入操作地址 break; } }

/********************************************************** * 函数功能 --->写入自定义字符到LCD的CGRAM * 入口参数 ---> *data_code:写入的数组 * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Write_CGRAM_ALL(const u8 *data_code) { u8 i; LCD_Write_Byte(0x34,0); //打开字符扩展指令 LCD_Write_Byte(0x02,0); //SR=0,允许输入 LCD_Write_Byte(0x30,0); //恢复基本指令 LCD_Write_Byte(0x40,0); //CGRAM地址 for(i = 0;i < CGRAM_Value;i++) { LCD_Write_Byte(data_code[i*2],1); LCD_Write_Byte(data_code[i*2+1],1); } }

/********************************************************** * 函数功能 ---> Modify the character content of the first CGRAM space * 入口参数 ---> *data_code:写入的数组 * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Write_CGRAM_ONE(const u8 *data_code,u8 add_h,u8 add_l) { u8 i; //Locked flag check if(LCD12864_LockedFlag==1)return;

else LCD12864_LockedFlag = 1; LCD_Write_Byte(0x34,0); //打开字符扩展指令 LCD_Write_Byte(0x02,0); //SR=0,允许输入 LCD_Write_Byte(0x30,0); //恢复基本指令 LCD_Write_Byte(0x40,0); //CGRAM地址 if(add_l==0) { for(i = 0;i < 16;i ++) { CGROM_Code[i*2] = data_code[i*2]; CGROM_Code[i*2+1] = data_code[i*2+1]; } } else if(add_l==2) { for(i = 0;i < 16;i ++) { CGROM_Code[i*2+32] = data_code[i*2]; CGROM_Code[i*2+33] = data_code[i*2+1]; } } else if(add_l==4) { for(i = 0;i < 16;i ++) { CGROM_Code[i*2+64] = data_code[i*2]; CGROM_Code[i*2+65] = data_code[i*2+1]; } } else if(add_l==6) { for(i = 0;i < 16;i ++) { CGROM_Code[i*2+96] = data_code[i*2]; CGROM_Code[i*2+97] = data_code[i*2+1]; } } for(i = 0;i < CGRAM_Value;i++) { LCD_Write_Byte(CGROM_Code[i*2],1); LCD_Write_Byte(CGROM_Code[i*2+1],1);

} //Locked flag recovery LCD12864_LockedFlag = 0; }

/********************************************************** * 函数功能 --->显示一个CGRAM内容 * 入口参数 ---> x:行 * y:列

* add_h:CGRAM高位地址 * add_l:CGRAM低位地址 * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void Display_CGRAM(u8 x,u8 y,u8 add_h,u8 add_l) { //Locked flag check if(LCD12864_LockedFlag==1)return; else LCD12864_LockedFlag = 1;

LCD_Set_xy(x,y); //设置显示地址 LCD_Write_Byte(add_h,1); LCD_Write_Byte(add_l,1); //Locked flag recovery LCD12864_LockedFlag = 0; }

/********************************************************** * 函数功能 ---> LCD显示字符串 * 入口参数 ---> x:行 * y:列

* *str:要显示的字符串 * len:显示的长度 * 返回数值 ---> none

* 功能说明 --->可以从显示数组的任意位置starsum开始显示len长度的字符串 **********************************************************/ void Display_String(u8 x,u8 y,u8 *str,u8 len) { //Locked flag check if(LCD12864_LockedFlag==1)return; else LCD12864_LockedFlag = 1; LCD_Set_xy(x,y); //设置显示地址 while(len--)

{ LCD_Write_Byte(*str,1); str++; } //Locked flag recovery LCD12864_LockedFlag = 0; }

/**********************************************************

* 函数功能 ---> LCD显示字符串 * 入口参数 ---> x:行 * y:列

* *str:要显示的字符串 * len:显示的长度 * 返回数值 ---> none

* 功能说明 --->可以从显示数组的任意位置starsum开始显示len长度的字符串 **********************************************************/ void Display_String1(u8 x,u8 y,u8 *str,u8 starsum,u8 len) { u8 i; //Locked flag check if(LCD12864_LockedFlag==1)return; else LCD12864_LockedFlag = 1; LCD_Set_xy(x,y); //设置显示地址 for(i = starsum;i < starsum + len;i++) { LCD_Write_Byte(str[i],1); } //Locked flag recovery LCD12864_LockedFlag = 0; }

/********************************************************** * 函数功能 ---> Clear GDRAM of LCD12864 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void ClearGDRAM(void) { u8 x,y; for(y=0;y<64;y++)

for(x=0;x<16;x++) { LCD_Write_Byte(0x34,0); LCD_Write_Byte(0x80+y,0); //Row address LCD_Write_Byte(0x80+x,0); //Line address LCD_Write_Byte(0x30,0); LCD_Write_Byte(0x00,1); LCD_Write_Byte(0x00,1); } }

/********************************************************** * 函数功能 ---> Display Exposure Time * 入口参数 ---> ExpTime:Exposure time

* InversePos:Inverse position

* 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void DisplayExposureTime(u16 ExpTime,u8 InversePos) { u8 i; u8 tempH,tempL; LCD_Write_Byte(0x34,0); //Open expansion instruction LCD_Write_Byte(0x36,0); //Open drawing function //One hundred thousand and ten thousand tempH = ExpTime/100000; tempL = ExpTime/10000; for(i=0;i<16;i++) { LCD_Write_Byte(0x80+i,0); //Row address LCD_Write_Byte(0x8B,0); //Line addres if(InversePos==1) LCD_Write_Byte(~ASCII_Table[tempH*16+i],1); else LCD_Write_Byte(ASCII_Table[tempH*16+i],1); if(InversePos==2) LCD_Write_Byte(~ASCII_Table[tempL*16+i],1); else LCD_Write_Byte(ASCII_Table[tempL*16+i],1); }

//Thousand and hundred tempH = ExpTime/1000; tempL = ExpTime/100; for(i=0;i<16;i++)

{ LCD_Write_Byte(0x80+i,0); //Row address LCD_Write_Byte(0x8C,0); //Line addres if(InversePos==3) LCD_Write_Byte(~ASCII_Table[tempH*16+i],1); else LCD_Write_Byte(ASCII_Table[tempH*16+i],1); if(InversePos==4) LCD_Write_Byte(~ASCII_Table[tempL*16+i],1); else LCD_Write_Byte(ASCII_Table[tempL*16+i],1); } //decade and single tempH = ExpTime/10; tempL = ExpTime; for(i=0;i<16;i++) { LCD_Write_Byte(0x80+i,0); //Row address LCD_Write_Byte(0x8D,0); //Line addres if(InversePos==5) LCD_Write_Byte(~ASCII_Table[tempH*16+i],1); else LCD_Write_Byte(ASCII_Table[tempH*16+i],1); if(InversePos==6) LCD_Write_Byte(~ASCII_Table[tempL*16+i],1); else LCD_Write_Byte(ASCII_Table[tempL*16+i],1); } LCD_Write_Byte(0x30,0); }

/********************************************************** * 函数功能 ---> Display collection number * 入口参数 ---> ColNum:collection number * InversePos:Inverse position * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void DisplayCollectNum(u16 ColNum,u8 InversePos) { u8 i; u8 tempH,tempL; LCD_Write_Byte(0x34,0); //Open expansion instruction

LCD_Write_Byte(0x36,0); //Open drawing function

//Thousand and hundred tempH = ColNum/1000; tempL = ColNum/100; for(i=0;i<16;i++) { LCD_Write_Byte(0x90+i,0); //Row address LCD_Write_Byte(0x8D,0); //Line addres if(InversePos==1) LCD_Write_Byte(~ASCII_Table[tempH*16+i],1); else LCD_Write_Byte(ASCII_Table[tempH*16+i],1); if(InversePos==2) LCD_Write_Byte(~ASCII_Table[tempL*16+i],1); else LCD_Write_Byte(ASCII_Table[tempL*16+i],1); } //decade and single tempH = ColNum/10; tempL = ColNum; for(i=0;i<16;i++) { LCD_Write_Byte(0x90+i,0); //Row address LCD_Write_Byte(0x8E,0); //Line addres if(InversePos==3) LCD_Write_Byte(~ASCII_Table[tempH*16+i],1); else LCD_Write_Byte(ASCII_Table[tempH*16+i],1); if(InversePos==4) LCD_Write_Byte(~ASCII_Table[tempL*16+i],1); else LCD_Write_Byte(ASCII_Table[tempL*16+i],1); } LCD_Write_Byte(0x30,0); }

/********************************************************** * 函数功能 ---> LCD写入GDRAM绘图 * 入口参数 ---> x:行 * y:列

* width:显示图片的宽度 * hieght:显示图片的高度 * *bmp:要显示的字符串

* dis_mode:显示模式,是半屏显示还是全屏显示 * 0:半屏显示。1:全屏显示 * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/

void Display_GDRAM(u8 x,u8 y,u8 width,u8 height,const u8 *bmp,u8 dis_mode) { u8 i,j,k; u8 base_x,base_y; //起始坐标 //Locked flag check

if(LCD12864_LockedFlag==1)return; else LCD12864_LockedFlag = 1;

/******全屏绘图显示******/ if(dis_mode) { switch(x) { case 1: base_y = One_LineAddress + y; break; case 2: base_y = Two_LineAddress + y; break; case 3: base_y = Three_LineAddress + y; break; case 4: base_y = Four_LineAddress + y; break; default: break; }

LCD_Write_Byte(MPU_8bit_Expansion_Draw_Close,0); //扩充指令 LCD_Write_Byte(MPU_8bit_Expansion_Draw_Open,0); //打开绘图功能 for(j = 0;j < height;j++) //32 { LCD_Write_Byte(base_y + j,0); //写入行号,即第几行开始 LCD_Write_Byte(One_LineAddress,0); //横坐标的第几个字节开始写 for(i = 0;i < width;i++) //上半屏 {

}

LCD_Write_Byte(bmp[width * j + i],1); //开始写入数据 }

for(k = 0;k < width;k++) //下半屏 {

LCD_Write_Byte(bmp[width * (j + height) + k],1); //开始写入数据

} }

/******分开上半屏或者下半屏写******/ else { switch(x) //判断显示的横坐标,确定起始行 {

case 1: //上半屏 base_x = One_LineAddress; //起始地址为0x80 break; case 2: //下半屏 base_x = One_LineAddress; //起始地址为0x80 break;

case 3: //下半屏 base_x = Three_LineAddress; //起始地址为0x88 break; default: break; }

base_y = base_x + y; //x轴方向的偏移,基地址 + 偏移地址

LCD_Write_Byte(MPU_8bit_Expansion_Draw_Close,0); //扩充指令 LCD_Write_Byte(MPU_8bit_Expansion_Draw_Open,0); //打开绘图功能

if(x == 1 || x == 3) //直接在同一个半屏的,直接写完32位数据 {

for(i = 0;i < 32;i++) //写地址有讲究,先写垂直再写水平,详见“设定绘图RAM{ LCD_Write_Byte(One_LineAddress + i,0);

地址”说明 是下半屏

//写入垂直地址,不管上半屏还

LCD_Write_Byte(base_y,0); //写入水平地址

for(j = 0;j < 2;j++) //两组8bit数据,组成16bit {

}

}

}

}

LCD_Write_Byte(*bmp++,1); //写入数据

if(x == 2) //数据显示不在同一半屏上的,先写上半屏,在写下半屏 { for(i = 0;i < 16;i++) //上半屏16行点阵数据 { }

}

LCD_Write_Byte(Two_LineAddress + i,0); //写入垂直地址 LCD_Write_Byte(base_y,0); //写入水平地址

for(j = 0;j < 2;j++) //两组8bit数据,组成16bit { }

LCD_Write_Byte(*bmp++,1); //写入数据

for(i = 0;i < 16;i++) //下半屏16行点阵数据 { LCD_Write_Byte(Three_LineAddress + i,0); //写入垂直地址 LCD_Write_Byte(base_y + 8,0); //写入水平地址 }

for(j = 0;j < 2;j++) //两组8bit数据,组成16bit { }

LCD_Write_Byte(*bmp++,1); //写入数据

LCD_Write_Byte(MPU_8bit_Expansion_Draw_Open,0); //扩充指令,打开绘图功能 // LCD_Write_Byte(Instruct_Basic8,0); //Locked flag recovery LCD12864_LockedFlag = 0; }

/********************************************************** * 函数功能 ---> LCD12864清屏 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Clear(void) {

//Locked flag check

if(LCD12864_LockedFlag==1)return; else LCD12864_LockedFlag = 1;

LCD_Write_Byte(Clear_Display,0); //清屏 //Locked flag recovery LCD12864_LockedFlag = 0; }

/********************************************************** * 函数功能 ---> LCD12864GPIO初始化 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;

#ifdef Soft_PSB

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIO时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIO #endif

#ifdef LCD_Work_Mode_Parallel

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIO时钟 GPIO_InitStructure.GPIO_Pin = DataBusPins|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIO #else //硬件SPI

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD, ENABLE);//使能GPIO时钟 //RST GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIO //CS GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO //LCD_PWDN/LCD_BLK GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIO LCD_PWDN = 0; LCD_BLK = 1; #ifdef LCD_Work_Mode_HardSPI //硬件SPI SPI1_Init();

#else//软件模拟SPI RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIO时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIO #endif #endif }

/********************************************************** * 函数功能 ---> LCD12864初始化 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none

**********************************************************/ void LCD_Init(void) {

/******PSB(串口并口通讯选择******/

#ifdef Soft_PSB //使用软件控制

#ifdef LCD_Work_Mode_Parallel //如果定义了,则使用并口工作模式 LCD_PSB = 1; //高电平为并口通讯模式 #else LCD_PSB = 0; //低电平为串口通讯模式 #endif

#endif /*********************************/ LCD_GPIO_Init(); /*********************************/

LCD_RST = 0; //显示屏复位 LCD_Delay(); LCD_Delay(); LCD_RST = 1;

LCD_CS = 0; //选中显示屏,高电平有效 LCD_Delay(); LCD_Delay();

LCD_CS = 1; //选中显示屏,高电平有效 //LCD_Write_Byte(Instruct_Expansion8,0); //指令0x34,拓展指令集,绘图关 LCD_Write_Byte(MPU_8bit_Expansion_Draw_Open,0); //指令0x36,拓展指令集,绘图开 LCD_Write_Byte(Open_Display,0); //整体显示开,光标关,显示反白关,0x0c LCD_Write_Byte(Clear_Display,0); //清屏,0x01 LCD_Write_Byte(Vernier_ShiftRight,0); //设定起点,光标右移,0x06 /*******************************/ LCD_Write_CGRAM_ALL(CGROM_Code); //写入自定义字符 LCD12864_LockedFlag = 0; }

void LCD_BLK_Manage(__IO uint16_t ADC_Result) { static u8 LCDBLKIcon = 0xff;//When the LCD backlight state does not change, //the repeated display of backlight icons is not

allowed // ADC_ConvertedValueLocal[1] =(float) ADC_ConvertedValue[1]/4096*(float)3.291; // //LCD显示 // sprintf(ShowBuf_ADC,\// Display_String(1,0,(u8*)ShowBuf_ADC,5); //if the voltage of photosensitive resistor is higher than 2.0V(=2489.21),turn off the backlight if(ADC_Result>=2489) { if(LCDBLKIcon!=1)//Prevent repeat display mechanism { LCD_BLK = 0; //turn on the backlight LCD_Write_CGRAM_ONE(MoonIcon,0,2); Display_CGRAM(1,6,0,2); //Show moon icon } LCDBLKIcon = 1; } else { if(LCDBLKIcon!=2)//Prevent repeat display mechanism { LCD_BLK = 1; //turn off the backlight LCD_Write_CGRAM_ONE(SunIcon,0,2); Display_CGRAM(1,6,0,2); //Clear moon icon } LCDBLKIcon = 2; } }

/*********************************************************/

LCD12864.h文件:

/********************************************************** * @ File name -> lcd12864.h * @ Version -> V1.1.2

* @ Date -> 11-30-2013

* @ Brief -> LCD12864驱动函数头文件 * 适用于ST7920驱动芯片

V1.1

* @ Revise -> A、修正操作命令宏定义。

* @ -> B、增加串口、并口转换宏定义,增加对高速度MCU控制通讯频率延时函数

* @ -> C、显示字符串函数增加显示长度选择,即显示多少个ASCII可显示字符,

汉字x2即可

* @ -> D、去掉显示数组函数,合并在字符串显示里

V1.1.1

* @ Revise ->增加字符串显示函数,可以从要显示的数组中任意位置显示一定长度字符串

V1.1.2

* @ Revise -> A、增加对低速晶振系统的MCU通讯频率是否使用的宏定义 * @ -> B、增加在检测液晶忙超时退出,预防死循环 **********************************************************/

#ifndef _lcd12864_h_ #define _lcd12864_h_

/**********************************************************

外部函数头文件

应用到不同的外设头文件请在这里修改即可

**********************************************************/

#include \

/********************************************************** LCD工作模式选择

LCD并口和串口选择请修改此参数和硬件电路即可

**********************************************************/ //#define LCD_Work_Mode_Parallel 1 //并行工作模式 //#define LCD_Work_Mode_SoftSPI 1 //串行工作模式(GPIO模拟SPI) #define LCD_Work_Mode_HardSPI 1 //串行工作模式(硬件SPI)

//#define Soft_PSB 1 //定义:使用硬件控制串口--->并口模式 //未定义:使用软件控制串口--->并口模式

/********************************************************** 延时调整通讯频率参数

需要使用不同频率的请修改此延时函数值

**********************************************************/ #define LCD_Delay() LCD_delay_1us();

/********************************************************** 定义接口信息

**********************************************************/

#ifdef Soft_PSB //定义了则使用软件控制

#define LCD_PSB PBout(12) //LCD并口和串口通讯选择口:0-串口;1-并口

#endif

//=========================================================

#ifdef LCD_Work_Mode_Parallel /* 并口工作模式 */

//=========================================================

#define DataBusGPIO GPIOB //定义12864要使用的I/O端口。 #define DataBusGPIOCLK RCC_APB2Periph_GPIOB //定义12864要使用的I/O端口的时钟。 #define DataBusPins GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7 //定义12864使用的数据引脚。

#define DataBusPin7 GPIO_Pin_7 #define LCDWriteData(x) GPIOB->ODR=((GPIOB->ODR & 0xff00)|x); //此处,只有直接操作寄存器才能

//达到,只改变输出数据寄存器ODR的低8位,其它位

//不变的目的。因为,只有低8位是数据引脚,

//其它位可能是控制引脚,不能改变。 #define LCD_EN PBout(8) #define LCD_RW PBout(9) #define LCD_RS PBout(10) #define LCD_RST PBout(11)

//=========================================================

#else /* 串口工作模式 */

#define LCD_RST PBout(6) //LCD复位脚RST #define LCD_CS PAout(15) //LCD对应管脚为RS #define LCD_PWDN PDout(4) //LCD电源使能引脚,低电平有效 #define LCD_BLK PDout(5) //LCD背光使能引脚,低电平有

效 //========================================================= #ifdef LCD_Work_Mode_HardSPI /***********串口模式时接口定义***********/ #else #define LCD_SCL PBout(3) //LCD对应管脚为EN #define LCD_SDA PBout(5) //LCD对应管脚为RW #endif //=========================================================

#endif //结束串口、并口模式选择

//=========================================================

/********************************************************** 参数宏定义

**********************************************************/

#define LCD_Busy 0x80 //LCD忙标志

#define Graph_BassADD 0x00 //显示GRAM基地址

//////////////////////////////////////////////////////

//LCD12864指令集

////////////////////////////////////////////////////// #define One_LineAddress 0x80 //第一行基地址 #define Two_LineAddress 0x90 //第二行基地址 #define Three_LineAddress 0x88 //第三行基地址 #define Four_LineAddress 0x98 //第四行基地址

//基本指令宏定义 #define MPU_Busy 0x80 //LCD忙,同时也读出了地址计数器(AC)数值

#define Clear_Display 0x01 //清屏指令 #define Zero_Address 0x02 //显示地址归零,AC = 0

//扩充指令宏定义

#define LCD_Standby 0x01 //待机指令,先设置RE = 1(功能设定寄存器),在送此命令即进入待机模式

//退出待机,写入任意指令可以退出,再将RE = 0即可

/***********基本指令***********/

//进入设定点(entry mode set)

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 0 0 0 1 I/D S #define Entry_ModeSet 0x04

#define Vernier_ShiftRight #define Vernier_ShiftLeft

//基数

(Entry_ModeSet | (1<<1)) //游标右移,AC+1 (Entry_ModeSet | (0<<1)) //游标右移,AC-1

#define Frames_ShiftRight (Vernier_ShiftLeft | 0x01) //画面整体右移 #define Frames_ShiftLeft (Vernier_ShiftRight | 0x01) //画面整体左移

//显示开关设置(display status)

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 0 0 1 D C B #define Display_Status

#define Open_Display #define Close_Display

#define Open_Vernier #define Close_Vernier

0x08 //基数

(Display_Status | (1<<2)) //整体显示开 (Display_Status | (0<<2)) //整体显示关 (Display_Status | (1<<1)) //游标显示开 (Display_Status | (0<<1)) //游标显示关

(Display_Status | 0x01) //游标位置显示反白开 (Display_Status | 0x00) //游标位置显示反白关,正常显示

#define Vernier_White_Open

#define Vernier_White_Close

//游标或显示移位控制(cursor and display shift control) // b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 0 1 S/C R/L1 X X #define Cursor_Display_Control 0x10 //基数

#define Cursor_ShiftLeft 1

(Cursor_Display_Control | (0<<2)) //游标向左移动,AC = AC -

#define Cursor_ShiftRight (Cursor_Display_Control | (1<<2)) //游标向右移动,AC = AC + 1

#define Display_ShiftLeft (Cursor_Display_Control | (2<<2)) //显示向左移动,游标跟着移动,AC = AC

#define Display_ShiftRight (Cursor_Display_Control | (3<<2)) //显示向右移动,游标跟着移动,AC = AC

//功能设定(function set)

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 1 DL X 0/RE X X #define Function_SetBasic 0x20 //基数

#define MPU_8bit

(Function_SetBasic | (1<<4)) (Function_SetBasic | (0<<4))

//0x30--8bit //0x20--4bit

MPU接口

#define MPU_4bit MPU接口

#define Instruct_Basic4 MPU接口,基本指令集 #define Instruct_Basic8

(MPU_4bit | (0<<2)) (MPU_8bit | (0<<2))

//0x20--4bit //0x30--8bit

MPU接口,基本指令集

#define Instruct_Expansion4 MPU接口,扩充指令集 #define Instruct_Expansion8

(MPU_4bit | (1<<2)) (MPU_8bit | (1<<2))

//0x24--4bit //0x34--8bit

MPU接口,扩充指令集

//设定CGRAM地址

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 1 A5 A4 A3 A2 A1 A0 #define CGRAM_Set 0x40 //基数 //设定CGRAM地址到地址计数器(AC),AC范围为0x00 ~ 0x3f,需确认扩充指令中SR = 0(卷动位置或RAM地址选择)

//设定DDRAM地址

// b7 b6 b5 b4 b3 b2 b1 b0 // 1 0 A5 A4 A3 A2 A1 A0

#define DDRAM_Set 0x80 //基数 //设定CGRAM地址到地址计数器(AC)

//写显示数据到RAM(RS = 1 RW = 0) // b7 b6 b5 b4 b3 b2 b1 b0 // D7 D6 D5 D4 D3 D2 D1 D0

//写入数据后会使AC改变,每个RAM(CGRAM、DDRAM、IRAM)地址都可以连续写入2字节的显示数据,

//当写入第二个字节时,地址计数器(AC)的值自动加1

//读取显示数据到RAM(RS = 1 RW = 1) // b7 b6 b5 b4 b3 b2 b1 b0 // D7 D6 D5 D4 D3 D2 D1 D0

//读取数据后会使AC改变,设定RAM(CGRAM、DDRAM、IRAM)地址后,先要Dummy read一次后才能读取到正确的显示数据,

//第二次读取不需要Dummy read,除非重新设定了RAM地址

/***********扩充指令***********/

//卷动位置或RAM地址选择

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 0 0 0 0 1 SR #define Write_Roll_Address_Allow #define Write_IRAM_Address_Allow 定CGRAM地址(基本指令)

//反白显示

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 0 0 0 1 0 R0 #define Display_White_One #define Display_White_Two

0x03 //允许输入垂直卷动地址 0x02 //允许输入IRAM地址(扩充指令),及允许设

0x04 0x05 //第一行反白显示 //第二行反白显示

//睡眠模式

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 0 0 1 SL 0 0 #define LCD_Sleep_Open #define LCD_Sleep_Close

//扩充功能设定

// b7 b6 b5 b4 b3 b2 b1 b0 // 0 0 1 DL X RE G X #define MPU_4bit_Basic_Draw_Open 接口,基本指令,绘图开

#define MPU_4bit_Basic_Draw_Close 接口,基本指令,绘图关

#define MPU_8bit_Basic_Draw_Open 接口,基本指令,绘图开

#define MPU_8bit_Basic_Draw_Close

(0x08 | (1<<2)) (0x08 | (0<<2))

//进入睡眠模式 //退出睡眠模式

(Instruct_Basic4 | (1<<1)) //0x22--4bit MPU

(Instruct_Basic4 | (0<<1)) //0x20--4bit MPU

(Instruct_Basic8 | (1<<1)) //0x32--8bit MPU(Instruct_Basic8 | (0<<1))

//0x30--8bit MPU

接口,基本指令,绘图关

#define MPU_8bit_Expansion_Draw_Open (Instruct_Expansion8 | (1<<1)) 接口,扩充指令,绘图开

#define MPU_8bit_Expansion_Draw_Close (Instruct_Expansion8 | (0<<1))

//0x36--8bit MPU//0x34--8bit MPU

接口,扩充指令,绘图关

#define MPU_4bit_Expansion_Draw_Open (Instruct_Expansion4 | (1<<1)) //0x26--4bit MPU接口,扩充指令,绘图开

#define MPU_4bit_Expansion_Draw_Close (Instruct_Expansion4 | (0<<1)) //0x24--4bit MPU接口,扩充指令,绘图关

//设定IRAM地址或卷动地址

// b7 b6 b5 b4 b3 b2 b1 b0

// 0 1 A5 A4 A3 A2 A1 A0

#define IRAM_Set 0x40 //基数

//SR = 1,A5 ~ A0为垂直卷动地址,SR = 0,A3 ~ A0为IRAM地址

//设定绘图RAM地址

// b7 b6 b5 b4 b3 b2 b1 b0

// 1 0 0 0 A3 A2 A1 A0 --->水平地址范围:A3 ~ A0 // 1 A6 A5 A4 A3 A2 A1 A0 --->垂直地址范围:A6 ~ A0 #define Draw_RAMSet 0x80 //基数 //设定GDRAM地址到地址计数器(AC),先设置垂直位置再设置水平位置(连续写入2字节数据来完成垂直与水平坐标的设置)。

extern u8 LCD12864_LockedFlag;

extern u8 CGROM_Code[]; extern u8 const ClearCGRAM[]; extern u8 const MoonIcon[]; extern u8 const SunIcon[]; extern u8 const AntennaIcon[]; extern u8 const WIFIConnection[]; extern u8 const Battery_100Percent[]; extern u8 const Battery_80Percent[]; extern u8 const Battery_60Percent[]; extern u8 const Battery_40Percent[]; extern u8 const Battery_20Percent[];

/********************************************************** 外部功能函数

**********************************************************/

void LCD_Init(void); //LCD YB12864ZB初始化

void LCD_Clear(void); //LCD YB12864ZB清屏

void LCD_Write_CGRAM_ONE(const u8 *data_code,u8 add_h,u8 add_l);//Modify the character content of the first CGRAM space

void Display_String(u8 x,u8 y,u8 *str,u8 len); //LCD显示字符串

void Display_String1(u8 x,u8 y,u8 *str,u8 starsum,u8 len); //LCD显示字符串

void ClearGDRAM(void);

void DisplayExposureTime(u16 ExpTime,u8 InversePos);

void DisplayCollectNum(u16 ColNum,u8 InversePos);

void Display_CGRAM(u8 x,u8 y,u8 add_h,u8 add_l); //显示一个CGRAM内容

void Display_GDRAM(u8 x,u8 y,u8 width,u8 height,const u8 *bmp,u8 dis_mode); //LCD写入GDRAM绘图

void LCD_BLK_Manage(__IO uint16_t ADC_Result);

#endif

/*********************************************************/ /*

1、指令表1(RE = 0,基本指令集)

___________________________________________________________________________ | | 控制信号 | 控制代码 | 执行 | | |____________|_______________________________________| | | 指令名称 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 时间 | HEX |_______________|____|_______|____|____|____|____|____|____|____|____|______| | 清除显示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1.6ms| 0x01

|_______________|____|_______|____|____|____|____|____|____|____|____|______| | 地址归0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | X | 72us | 0x02 //不改变DDRAM内容

|_______________|____|_______|____|____|____|____|____|____|____|____|______| | 进入设定点 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D| S | 72us | 0x06 游标右移 0x07 画面整体左移

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 0x04 游标左移 0x05 画面整体右移

| 显示开关设置 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | S | 72us | D = 1; 整体显示开 D = 0; 整体显示关 // 不改变DDRAM内容

|_______________|____|_______|____|____|____|____|____|____|____|____|______| C = 1; 游标显示开 C = 0; 游标显示关 S = 1; 游标位置显示反白 S = 0; 正常显示

| 移位控制 | 0 | 0 | 0 | 0 | 0 | 1 | S/C| R/L| X | X | 72us | 0x10 游标向左移动 AC = AC - 1 0x14 游标向右移动 AC = AC + 1

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 0x18 显示向左移动 AC = AC 0x1c 显示向右移动 AC = AC

| 功能设定 | 0 | 0 | 0 | 0 | 1 | DL | X |0/RE| X | X | 72us | 0x30 8bit接口,基本指令 0x34 8bit接口,扩充指令

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 0x20 4bit接口,基本指令 0x24 4bit接口,扩充指令

| 设定CGRAM地址 | 0 | 0 | 0 | 1 | A5 | A4 | A3 | A2 | A1 | A0 | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 设定CGRAM地址到地址计数器(AC),AC范围0x00 ~ 0x3f,需确认扩充指令中SR = 0 | 设定DDRAM地址 | 0 | 0 | 1 | 0 | A5 | A4 | A3 | A2 | A1 | A0 | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 设定DDRAM地址到地址计数器(AC),第一行AC范围 0x80 ~ 0x8f 第二行AC范围 0x90 ~ 0x9f

| 读忙标志和地址| 0 | 1 | BF | A6 | A5 | A4 | A3 | A2 | A1 | A0 | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| BF = 0; //可以接受新数据

| 写显示数据 | 1 | 0 | 显示数据 | 72us | |_______________|____|_______|_______________________________________|______| 每个RAM(CGRAM、DDRAM、IRAM)地址都可以连续写入2个字节,第二个字节时AC自动增加1

| 读显示数据 | 1 | 1 | 显示数据 | 72us | |_______________|____|_______|_______________________________________|______| 设定RAM(CGRAM、DDRAM、IRAM)地址后,先要Dummy read(假读)一次后才能读到正确的显示

数据,第二次读取不需要再Dummy read(假读)一次,除非重新设置了RAM地址

2、指令表2(RE = 1,扩充指令集)

___________________________________________________________________________ | | 控制信号 | 控制代码 | 执行 | | |____________|_______________________________________| | | 指令名称 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 时间 | HEX |_______________|____|_______|____|____|____|____|____|____|____|____|______|

| 待命模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 72us | 0x01 该指令不能改变RAM内容

|_______________|____|_______|____|____|____|____|____|____|____|____|______| | 卷动地址或 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | SR | 72us |

| RAM地址选择 | | | | | | | | | | | | 初始值0x02, 0x03 允许输入垂直卷动地址

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 0x02 允许输入IRAM地址(扩充指令),及允许设定CGRAM地址(基本指令) | 反白显示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | R1 | R0 | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 初始值0x04 0x05反白显示

| 睡眠模式 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | SL | X | X | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 0x0c 脱离睡眠模式 0x08 进入睡眠模式

| 扩充功能设定 | 0 | 0 | 0 | 0 | 1 | DL | X |1/RE| G | 0 | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| |设定IRAM地址或 | 0 | 0 | 0 | 1 | A5 | A4 | A3 | A2 | A1 | A0 | 72us |

| 卷动地址 | | | | | | | | | | | | SR = 1; //A5 ~ A0为垂直卷动地址

|_______________|____|_______|____|____|____|____|____|____|____|____|______| SR = 0; //A3 ~ A0为IRAM地址

| | | | | 0 | 0 | 0 | A3 | A2 | A1 | A0 | |

| | | | |____|____|____|____|____|____|____| | 设定GDRAM地址到计数器地址(AC),先设置垂直地址再设置水平地址,

|设定绘图RAM地址| 0 | 0 | 1 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | 72us | (连续写入2个字节数据来完成垂直和水平地址设置)

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 垂直地址范围:AC6 ~ AC0 水平地址范围:AC3 ~ AC0

扩充功能设定: DL = 1; //8bit MPU接口 DL = 0;

RE = 1;

//扩充指令 RE = 0; //绘图显示开 G = 0;

//4bit MPU接口 //基本指令 // 绘图显示关

G = 1; */

| 扩充功能设定 | 0 | 0 | 0 | 0 | 1 | DL | X |1/RE| G | 0 | 72us |

|_______________|____|_______|____|____|____|____|____|____|____|____|______| |设定IRAM地址或 | 0 | 0 | 0 | 1 | A5 | A4 | A3 | A2 | A1 | A0 | 72us |

| 卷动地址 | | | | | | | | | | | | SR = 1; //A5 ~ A0为垂直卷动地址

|_______________|____|_______|____|____|____|____|____|____|____|____|______| SR = 0; //A3 ~ A0为IRAM地址

| | | | | 0 | 0 | 0 | A3 | A2 | A1 | A0 | |

| | | | |____|____|____|____|____|____|____| | 设定GDRAM地址到计数器地址(AC),先设置垂直地址再设置水平地址,

|设定绘图RAM地址| 0 | 0 | 1 | A6 | A5 | A4 | A3 | A2 | A1 | A0 | 72us | (连续写入2个字节数据来完成垂直和水平地址设置)

|_______________|____|_______|____|____|____|____|____|____|____|____|______| 垂直地址范围:AC6 ~ AC0 水平地址范围:AC3 ~ AC0

扩充功能设定: DL = 1; //8bit MPU接口 DL = 0;

RE = 1;

//扩充指令 RE = 0; //绘图显示开 G = 0;

//4bit MPU接口 //基本指令 // 绘图显示关

G = 1; */

本文来源:https://www.bwwdw.com/article/koi3.html

Top