#define _LCD_DRV_C_
#include "Drv.h"
#include "Fmm.h"
//----------------------------------------------------------
void Delay(INT16U times)
{
while(times)
{
times--;
}
}
//----------------------------------------------------------
void M_Delay(INT16U NOs)
{
while(NOs)
{
Delay(200);
NOs--;
}
}
//----------------------------------------------------------
//IO输入
void IOInitIn()
{
GPIO_InitTypeDef InitType;
InitType.GPIO_Speed=GPIO_Speed_50MHz;
InitType.GPIO_Pin = DATAH;
InitType.GPIO_Mode=GPIO_Mode_IN_FLOATING;//数据引脚为浮空输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_Init(GPIOB,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;
InitType.GPIO_Pin = DATAL0;
InitType.GPIO_Mode=GPIO_Mode_IN_FLOATING;//数据引脚为浮空输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Init(GPIO_LCD_CMD_DATAL0_SELECT,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;
InitType.GPIO_Pin = DATAL1;
InitType.GPIO_Mode=GPIO_Mode_IN_FLOATING;//数据引脚为浮空输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_Init(GPIO_LCD_CMD_DATAL1_SELECT,&InitType);
}
//IO输出
void IOInitOut()
{
GPIO_InitTypeDef InitType;
InitType.GPIO_Speed=GPIO_Speed_50MHz;
InitType.GPIO_Pin = DATAH;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_Init(GPIOB,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;
InitType.GPIO_Pin = DATAL0;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Init(GPIO_LCD_CMD_DATAL0_SELECT,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;
InitType.GPIO_Pin = DATAL1;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_Init(GPIO_LCD_CMD_DATAL1_SELECT,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;//RS
InitType.GPIO_Pin = PORT_LCD_RS;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Init(GPIO_LCD_RS,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;//RW
InitType.GPIO_Pin = PORT_LCD_RW;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Init(GPIO_LCD_RW,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;//EN
InitType.GPIO_Pin = PORT_LCD_EN;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Init(GPIO_LCD_EN,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;//CS1
InitType.GPIO_Pin = PORT_LCD_CS1;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Init(GPIO_LCD_CS1,&InitType);
InitType.GPIO_Speed=GPIO_Speed_50MHz;//CS2
InitType.GPIO_Pin = PORT_LCD_CS2;
InitType.GPIO_Mode=GPIO_Mode_Out_PP;//数据引脚为推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Init(GPIO_LCD_CS2,&InitType);
}
//检测忙
void CheckState()
{
GPIO_WriteBit(GPIO_LCD_RS,
PORT_LCD_RS,
(BitAction)PIN_LCD_RS_ENABLE);
GPIO_WriteBit(GPIO_LCD_RW,
PORT_LCD_RW,
(BitAction)PIN_LCD_RW_DISABLE);
GPIO_WriteBit(GPIO_LCD_EN,
PORT_LCD_EN,
(BitAction)PIN_LCD_EN_DISABLE); //EN下降沿
IOInitIn();
while(GPIO_ReadInputData(GPIOB) & 0x0100);
GPIO_WriteBit(GPIO_LCD_EN,
PORT_LCD_EN,
(BitAction)PIN_LCD_EN_ENABLE); //EN下降沿
IOInitOut();
}
/*写命令到LCD*/
void SendCommandToLCD(INT8U com)
{
INT16U Tcom;
Tcom=com;
CheckState();//状态检测LCD是否忙
GPIO_WriteBit(GPIO_LCD_RS,
PORT_LCD_RS,
(BitAction)PIN_LCD_RS_ENABLE); //向LCD发送命令。RS=0写指令,RS=1写数据
GPIO_WriteBit(GPIO_LCD_RW,
PORT_LCD_RW,
(BitAction)PIN_LCD_RW_ENABLE);//R/W="L",E="H->L"数据被写到IR或DR
//DATA=com; //com :命令
GPIOB->ODR=(GPIOB->ODR & 0xfc0f)|((Tcom<<2)&0xfff3);
if(com&0x01)
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL0_SELECT,
DATAL0,
(BitAction)PIN_LCD_RW_DISABLE);
}
else
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL0_SELECT,
DATAL0,
(BitAction)PIN_LCD_RW_ENABLE);
}
if(com&0x02)
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL1_SELECT,
DATAL1,
(BitAction)PIN_LCD_RW_DISABLE);
}
else
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL1_SELECT,
DATAL1,
(BitAction)PIN_LCD_RW_ENABLE);
}
GPIO_WriteBit(GPIO_LCD_EN,
PORT_LCD_EN,
(BitAction)PIN_LCD_EN_DISABLE);//EN下降沿
GPIO_WriteBit(GPIO_LCD_EN,
PORT_LCD_EN,
(BitAction)PIN_LCD_EN_ENABLE);//EN下降沿
}
/*设置页0Xb8是页的首地址*/
void SetLine(INT8U page)
{page=0xb8|page; //1011 1xxx 0<=page<=7设定页地址 --X 0-7,8行为一页64/8=8,共8页
SendCommandToLCD(page);
}
/*设定显示开始行,0xc0是行首地址*/
void SetStartLine(INT8U startline)
{startline=0xc0|startline; //1100 0000
SendCommandToLCD(startline); //设置从哪行开始:0--63,一般从0行开始显示
}
/*设定列地址--Y 0-63,0x40为列首地址*/
void SetColumn(INT8U column)
{column=column &0x3f; //column最大值为64,输出 0=<column<=63
column= 0x40|column; //01xx xxxx
SendCommandToLCD(column);
}
/*开关显示,0x3f是开显示,0x3e是关显示*/
void SetOnOff(INT8U onoff)
{onoff=0x3e|onoff; //0011 111x,onoff只能为0/1
SendCommandToLCD(onoff);
}
/*写显示数据*/
void WriteByte(INT8U dat)
{
INT16U Tcom;
Tcom=dat;
CheckState();//状态检查,LCD是否忙
GPIO_WriteBit(GPIO_LCD_RS,
PORT_LCD_RS,
(BitAction)PIN_LCD_RS_DISABLE); //向LCD发送命令。RS=0写指令,RS=1写数据 //RS=0写指令 RS=1写数据
GPIO_WriteBit(GPIO_LCD_RW,
PORT_LCD_RW,
(BitAction)PIN_LCD_RW_ENABLE);//R/W="L",E="H->L"数据被写到IR或DR////R/W="L",E="H->L"数据被写到IR/DR
GPIOB->ODR=(GPIOB->ODR & 0xfc0f)|((Tcom<<2)&0xfff3);
if(dat&0x01)
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL0_SELECT,
DATAL0,
(BitAction)PIN_LCD_RW_DISABLE);
}
else
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL0_SELECT,
DATAL0,
(BitAction)PIN_LCD_RW_ENABLE);
}
if(dat&0x02)
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL1_SELECT,
DATAL1,
(BitAction)PIN_LCD_RW_DISABLE);
}
else
{
GPIO_WriteBit(GPIO_LCD_CMD_DATAL1_SELECT,
DATAL1,
(BitAction)PIN_LCD_RW_ENABLE);
}//dat:显示数据
GPIO_WriteBit(GPIO_LCD_EN,
PORT_LCD_EN,
(BitAction)PIN_LCD_EN_DISABLE);//EN下降沿
GPIO_WriteBit(GPIO_LCD_EN,
PORT_LCD_EN,
(BitAction)PIN_LCD_EN_ENABLE);//EN下降沿
}
/*选择屏幕 0全屏,1左屏 2右屏*/
void SelectScreen(INT8U screen)
{switch(screen)
{
case 0: GPIO_WriteBit(GPIO_LCD_CS1,
PORT_LCD_CS1,
(BitAction)PIN_LCD_CS1_DISABLE);//全屏
GPIO_WriteBit(GPIO_LCD_CS2,
PORT_LCD_CS2,
(BitAction)PIN_LCD_CS2_DISABLE);
break;
case 1: GPIO_WriteBit(GPIO_LCD_CS1,
PORT_LCD_CS1,
(BitAction)PIN_LCD_CS1_DISABLE);//左屏
GPIO_WriteBit(GPIO_LCD_CS2,
PORT_LCD_CS2,
(BitAction)PIN_LCD_CS2_ENABLE);
break;
case 2: GPIO_WriteBit(GPIO_LCD_CS1,
PORT_LCD_CS1,
(BitAction)PIN_LCD_CS1_ENABLE);//右屏
GPIO_WriteBit(GPIO_LCD_CS2,
PORT_LCD_CS2,
(BitAction)PIN_LCD_CS2_DISABLE);
break;
}
}
//初始化液晶
void LcdDrvInit(void)
{
//初始化端口
IOInitOut();
//复位液晶
//延时
//初始化变量
memset(&gLcdDrvData,0,sizeof(LCD_DRV_DATA_STRUCT));
}
//初始化液晶端口
void LcdDrvPortInit(void)
{
GPIO_InitTypeDef InitType;
InitType.GPIO_Speed=GPIO_Speed_50MHz;
//置输出上拉
InitType.GPIO_Pin = DATAH;
InitType.GPIO_Mode=GPIO_Mode_IN_FLOATING;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_Init(GPIOB,&InitType);
}
//延时
void LcdDrvDelay(INT16U DelayTime)
{
for(;DelayTime>0;DelayTime--);
}
//加载对比度
void LcdDrvLoadContrastValue(INT8U ContrastValue)
{
//对比度值越界
#if 0
if(ContrastValue>=CONTRAST_MAX_VALUE)
return;
//发送对比度调节命令
LcdDrvSendLcdData(SEND_LCD_COMMAND,
DISPLAY_COMMAND_SET_CONTRAST_MODE);
//发送对比度调节数据
LcdDrvSendLcdData(SEND_LCD_COMMAND,
ContrastValue);
#endif
}
//发送液晶数据
void LcdDrvSendLcdData(LCD_DRV_SEND_CMD_DATA_SELECT_Def SelectType,
INT8U SendData)
{
#if 0
INT8U i,DelayNop;
//选择发送类型
switch(SelectType)
{
//发送指令
case SEND_LCD_COMMAND:
GPIO_WriteBit(GPIO_LCD_CMD_DATA_SELECT,
PORT_LCD_CMD_DATA_SELECT,
(BitAction)PIN_LCD_CMD_SELECT);
break;
//发送数据
case SEND_LCD_DATA:
GPIO_WriteBit(GPIO_LCD_CMD_DATA_SELECT,
PORT_LCD_CMD_DATA_SELECT,
(BitAction)PIN_LCD_DATA_SELECT);
break;
default:
return;
}
//片选
GPIO_WriteBit(GPIO_LCD_CHIP_SELECT,
PORT_LCD_CHIP_SELECT,
(BitAction)PIN_LCD_CHIP_SELECT_ENABLE);
//发送
for(i=0;i<8;i++)
{
if((SendData&0x80)==0x80)
GPIO_WriteBit(GPIO_LCD_SOUT,
PORT_LCD_SOUT,
(BitAction)PIN_LCD_SOUT_HIGH);
else
GPIO_WriteBit(GPIO_LCD_SOUT,
PORT_LCD_SOUT,
(BitAction)PIN_LCD_SOUT_LOW);
//延时
DelayNop=DelayNop;DelayNop=DelayNop;
DelayNop=DelayNop;DelayNop=DelayNop;
//产生时钟上升沿
GPIO_WriteBit(GPIO_LCD_SCLK,
PORT_LCD_SCLK,
(BitAction)PIN_LCD_SCLK_HIGH);
//延时
DelayNop=DelayNop;DelayNop=DelayNop;
DelayNop=DelayNop;DelayNop=DelayNop;
//恢复时钟信号低电平
GPIO_WriteBit(GPIO_LCD_SCLK,
PORT_LCD_SCLK,
(BitAction)PIN_LCD_SCLK_LOW);
SendData<<=1;
}
//撤消片选
GPIO_WriteBit(GPIO_LCD_CHIP_SELECT,
PORT_LCD_CHIP_SELECT,
(BitAction)PIN_LCD_CHIP_SELECT_DISABLE);
#endif
}
//显示半角汉字/数字/字母
void Displayen(INT8U ss,INT8U page,INT8U column,INT8U *number)
{INT8U i;//选屏参数,page选页参数,column选列参数,number选第几汉字输出
SelectScreen(ss);
column=column&0x3f;
SetLine(page); //写上半页
SetColumn(column);
for(i=0;i<8;i++)
{WriteByte(number);}
SetLine(page+1); //写下半页
SetColumn(column);
for(i=0;i<8;i++)
{WriteByte(number[i+8]);}
}
/*显示全角汉字*/
void Display(INT8U ss,INT8U page,INT8U column,INT8U *number)
{INT8U i; //选屏参数,page选页参数,column选列参数,number选第几汉字输出
SelectScreen(ss);
column=column&0x3f;
SetLine(page); //写上半页
SetColumn(column); //控制列
for(i=0;i<16;i++) //控制16列的数据输出
{WriteByte(number);}//i+32*number汉字的前16个数据输出
SetLine(page+1); //写下半页
SetColumn(column); //控制列
for(i=0;i<16;i++) //控制16列的数据输出
{WriteByte(number[i+16]);}//i+32*number+16汉字的后16个数据输出
}
//液晶驱动
void LcdDrvLoadLcdData(INT8U lin,
INT8U column,INT8U *LcdData,
INT8U Len)
{
INT8U ss=0;
//×?·?
if(Len==16)
{
column=column*8;
//if(column<8) SelectScreen(0); //如果列队<8(0,1,2,3,4,5,6,7)则写在第一屏上面
if(column<64)
{
ss=1;
}
else
{
ss=2;
column=column-64;
}
lin=lin<<1;
Displayen(ss,lin,column,LcdData);
}
if(32==Len)
{
column=column*16;
if(column<64)
{
ss=1;
}
else
{
ss=2;
column=column-64;
}
lin=lin<<1;
Display(ss,lin,column,LcdData);
}
}
/*------------------显示边框-------------------------------*/
void frame()
{
INT8U i;
SelectScreen(2);
for (i = 0;i < 8;i++)
{
SetLine( i); //共8页
SetColumn( 31); //最后一页
WriteByte(0xff); //ff表示每页的8行全亮
//#define Page_Add 0xb8 //起始页地址
//#define Start_Line 0xc0 //起始行地址
}
}
/*清屏screen: 0-全屏,1-左屏,2-右屏*/
void ClearScreen(INT8U screen)
{INT8U i,j;
SelectScreen(screen);
for(i=0;i<8;i++) //控制页数0-7,共8页
{SetLine(i);
SetColumn(0);
for(j=0;j<64;j++) //控制列数0-63,共64列
{WriteByte(0x00);} //写点内容,列地址自动加1
}
}
/*初始化LCD*/
void init_lcd()
{
CheckState();
SelectScreen(0);
SetOnOff(0); //关显示
SelectScreen(0);
SetOnOff(1); //开显示
SelectScreen(0);
ClearScreen(0);//清屏
SetStartLine(0); //开始行:0
}
|