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; */
正在阅读:
STM32F4_LCD12864串行并行驱动程序合集06-21
聊城、日照、企业09-29
(完整版)要 - 毕业设计找这个网站吧09-08
运筹学建模 炼油厂生产计划安排06-11
上海市城市总体规划05-15
高速公路隧道监控员工作计划09-07
研究生创新计划项目可行性研究报告05-18
招商信诺养老保险转移申请表相关说明08-31
2焊条04-16
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 合集
- 串行
- 并行
- 驱动程序
- 12864
- STM
- LCD
- 32
- hillstone防火墙配置实例介绍 - 图文
- 前六章多选题1
- 顾客网上购物10大心理分析
- 2012年中级财务管理 - 基础班 - 课后作业试题 - (1-8全)
- 杭州绿化建设现状分析
- 井工厂压裂高压管汇使用规定(试行)
- 病毒性肝炎诊疗常规0
- 省级主要媒体五四青年节评论员文章
- 发酵工程名词解释
- PD800用户手册(wince)
- 大理至南涧高速公路南涧段征地拆迁
- 人教版第六册数学教案
- MATLAB实践
- 十大杰出母亲评选方案
- 2017年12月份考试作业建筑经济与企业管理第3次
- 2010年中考数学试题分类大全46 - 综合型问题 - 图文
- 甲级单位编制炭块项目可行性报告(立项可研+贷款+用地+2013案例
- 为进一步加强对信访活动中违法犯罪行为依法处置工作
- 电气控制习题与答案
- 分析化学第5章思考题习题答案