📄 hal_lcdc.c
字号:
}
do
{ GUI_Point(x0, y0, color); // 逐点显示,描出垂直线
y0++;
}while(y1>y0);
GUI_Point(x0, y0, color);
}
////////////////////////////////////////////////////////////////////////
//函数:CountZkAdr(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4)
//功能:计算汉字点阵在芯片中的地址
//参数:c1,c2,c3,c4:4字节汉字内码通过参数c1,c2,c3,c4传入,双字节内码通过参数c1,c2传入,c3=0,c4=0
//返回:汉字点阵的字节地址(byte address)。如果用户是按 word mode 读取点阵数据,则其地址(word
//address)为字节地址除以2,即:word address = byte address / 2 .
//例如:“啊”字的内码为0xb0a1,则byte address = g(0xb0,0xa1,0x00,0x00) *32+0xa7700
//word address = byte address / 2
//“ ”字的内码为0x8139ee39,则byte address = g(0x81,0x39,0xee,0x39) *32+0xa7700
//word address = byte address / 2
//说明:在以上计算字节地址中byte address = g(0xb0,0xa1,0x00,0x00) *32+0xa7700的0xa7700是15X16
//点阵字库相对整个字库芯片0000 0000的偏移地址
/////////////////////////////////////////////////////////////////////////////
uint32_t CountZkAdr(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4)
{
uint32_t h;
if(c1 >= 0xb0 && c2 >= 0xA1 && c3 == 0 && c4 == 0)//汉字2区 B0A1 --- F7FE 0xAF8C0
{
return (uint32_t)((c1-0xB0)*94+(c2-0xA1))*32+0xAF8C0;
}
else if(c1 >= 0xAA && c2 >= 0x40 && c3 == 0 && c4 == 0)//16点阵4区汉字 AA40 --- FEAE 0x113EC0
{
if(c2>0x7f)c2--;
if(c2 > 0xA0) c2 = 0x40;
return (uint32_t)((c1-0xAA)*96+(c2-0x40))*32+0x113EC0;
}
else if(c1 >= 0xA8 && c3 == 0 && c4 == 0)//字符5区 A840 --- A996 0xAE0C0
{
if(c1>=0xA8 && c2>=0xA1);
else if(c2>0x7f)c2--;
if(c2>=0xA1)
return (uint32_t)((c1-0xA1)*94+(c2-0xA1))*32+0xA7700;
else
return (uint32_t)((c1-0xA8)*96+(c2-0x40))*32+0xAE0C0;
}
else if(c1 >= 0xA1 && c3 == 0 && c4 == 0)//字符1区 A1A1 --- A9FE 0xA7700
{
return (uint32_t)((c1-0xA1)*94+(c2-0xA1))*32+0xA7700;
}
else if(c1 >= 0x81 && c3 == 0 && c4 == 0)//汉字3区 8140 --- A0FE 0xE46C0
{
if(c2>0x7f)c2--;
return (uint32_t)((c1-0x81)*190+(c2-0x40))*32+0xE46C0;
}
else if(c2>=0x30)//汉字4区
{
// four bytes HZ
h=(((uint32_t)(c1-0x81)*10+(c2-0x30))*126+(uint32_t)(c3-0x81))*10+(c4-0x30);
h-=12439;
//if(h<0 || h>=6530) return(0);
if(h>=6530) return(0);
h += 22046;
return h*32+0xA7700;
}
return 0;
}
//字节倒序 eg: D7....D0 H--->L 转换后为 L -->H D0....D7
uint8_t ByteReverseOrder(uint8_t dbyte)
{
uint8_t i,buff;
buff=0;
for(i=0;i<8;i++)
{
buff<<=1;
buff|=(dbyte>>i)&0x01;
}
return buff;
}
//进行8×8点矩阵转换 ConIn 要进行转换的数据指针 ConOut 转换后的数据指针
void ByteConversion_8(uint8_t *ConIn,uint8_t *ConOut)
{
uint8_t i,j;
// memcpy(ConOut,ConIn,8);
for(i=0;i<8;i++)
{
ConOut[i]=0;
for(j=0;j<8;j++)
{
ConOut[i]<<=1;
ConOut[i]|=(ByteReverseOrder(ConIn[j])>>(7-i))&0x01;
}
}
}
//fg=0 不取反显示 fg=1 取反显示
//void LCD_Dis2Byte(uint16_t adr,uint8_t *dat,uint8_t fg)
void LCD_Dis2Byte(uint16_t adr,uint8_t *dat)
{
uint8_t i;
DisCursorSetup(CSRDIR_DOWN,adr);
for(i=0;i<8;i++)
LCD_WriteData(dat[i]);
}
//反白显示与非反白显示
//ReveVo = 1 反白显示 ReveVo = 0 不反白显示
void Reverse_Vidio(uint8_t ReveVo,uint8_t ChineseLen,uint8_t English_len,uint16_t CSR_ADR)
{
uint8_t i,j;
uint8_t tp[8];
if(ReveVo==1)
memset(tp,0xff,sizeof(tp));
else
memset(tp,0,sizeof(tp));
// LCD_WriteCommand(OVLAY);
// LCD_WriteData(0x0e);//合成异或方式
for(i=0;i<ChineseLen;i++)
{
for(j=0;j<2;j++,CSR_ADR++)
{
LCD_Dis2Byte(CSR_ADR,tp); //显示白方块做为底色
CSR_ADR+=8*40;
LCD_Dis2Byte(CSR_ADR,tp);
CSR_ADR-=8*40;
}
}
for(i=0;i<English_len;i++,CSR_ADR++)
{
LCD_Dis2Byte(CSR_ADR,tp); //显示白方块做为底色
CSR_ADR+=8*40;
LCD_Dis2Byte(CSR_ADR,tp);
CSR_ADR-=8*40;
}
// LCD_WriteCommand(OVLAY);
// LCD_WriteData(0x0C);//合成或方式
}
//////////////////////////////////////////////////////////////////////////
//名称: LcdDisplay()
//功能: 从指定行与指定列显示内容
//入口参数: x 指定行 取值范围: 0-239
// y 指定列 取值范围: 0-319 且所取值为 y%8=0 即第行最多可显示40个字符
// dat 显示数据缓冲指针
// ModeParameter: 参数取值范围 已宏定义
//低4位 0: 清除全屏后再显示
// 1: 清除本显示行后再显示
// 2: 不清除即显示
// 3: 清除指定内容再显示
//高4位 1: 取反显示
// 0: 不取反显示
//ch_len=中文内码长度 en_len=西方内码长度
//////////////////////////////////////////////////////////////////////////
void LcdDisplay(uint16_t x,uint16_t y,uint8_t *dat,uint8_t ModeParameter)
{
uint8_t i,j,len,flag,ch_len,en_len;
uint8_t bm1,bm2,bm3,bm4,hzi;
uint8_t strbuff[32],buff[40];
uint32_t addr;
uint16_t CursorAddress;
CursorAddress=(x*40)+(y/8);//计算显示的起始位置
// TM3Disable;
if((ModeParameter&0x0F) == LcdClearAll) //清全屏再显示
LCD_FillAll(0);
if((ModeParameter&0xF0)==LcdBothControl)//双屏控制
CursorAddress+=0x4000;
if((ModeParameter&0x0F)==LcdClearHov) //清除本行后再显示
{
DisCursorSetup(CSRDIR_RIGHT,x*40);
for(i=0;i<16;i++)
{
for(j=0;j<40;j++)LCD_WriteData(0);//16点阵字节 × 40Byte
}
}
len=0; ch_len=0; en_len=0;
while(dat[len]!=0)len++;//统计字符长度
for(i=0;i<len;i++)
{
if(dat[i]>0x80) //中文显示方式
{
ch_len++;
hzi = i;
bm1=dat[hzi++];
bm2=dat[hzi++];
bm3=dat[hzi++];
bm4=dat[hzi];
if(bm1 >= 0x82 && bm2 > 0x35)
{
bm3 = bm4 = 0;
i += 1;
}
else i += 3;
// if((ModeParameter&0xf0)!=LcdControry && (ModeParameter&0xf0)!=LcdDeoxidize)//不为取消反色显示==反色显示应该读出字库
if((ModeParameter&0xf0)!=LcdControry && (ModeParameter&0xf0)!=LcdDeoxidize)//不为取消反色显示==反色显示应该读出字库
{
addr = CountZkAdr(bm1,bm2,bm3,bm4);
SerialFlashRead(ZiKu,addr,32,buff);//读取一个汉字点阵
for(j=0;j<4;j++)//进行一个汉字的点阵转换
ByteConversion_8(&buff[j*8],&strbuff[j*8]);
//////////////////////////////////////////////////////////////////
for(j=0;j<2;j++,CursorAddress++)
{
LCD_Dis2Byte(CursorAddress,&strbuff[j*8]);
CursorAddress+=8*40;
LCD_Dis2Byte(CursorAddress,&strbuff[j*8+16]);
CursorAddress-=8*40;
}
}
}
else //是西方显示
{
en_len++;
if((ModeParameter&0xf0)!=LcdControry && (ModeParameter&0xf0)!=LcdDeoxidize)//不为取消反色显示==反色显示
{
addr = 0x18A010+(dat[i]-0x20)*16;//西方字库地址
SerialFlashRead(ZiKu,addr,16,buff);//读取西文点阵
for(j=0;j<2;j++)
{
ByteConversion_8(&buff[j*8],&strbuff[j*8]);
}
LCD_Dis2Byte(CursorAddress,&strbuff[0]);
CursorAddress+=8*40;
LCD_Dis2Byte(CursorAddress,&strbuff[8]);
CursorAddress-=8*40;
CursorAddress++;
}
}
}
switch(ModeParameter&0xf0)
{
case LcdControry://取反显示
flag=1;
break;
case LcdDeoxidize://取消反白显示
flag=0;
break;
default:break;
}
if((ModeParameter&0xf0)==LcdControry || (ModeParameter&0xf0)==LcdDeoxidize)//取反显示或不取反显示
{
CursorAddress=(x*40)+(y/8)+0x4000;
Reverse_Vidio(flag,ch_len,en_len,CursorAddress);
}
// TM3Enable;
}
/****************************************************************************
* 名称:GUI_Line()
* 功能:画任意两点之间的直线。
* 入口参数: x0 直线起点的x坐标值
* y0 直线起点的y坐标值
* x1 直线终点的x坐标值
* y1 直线终点的y坐标值
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
void GUI_Line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, TCOLOR color)
{ int dx; // 直线x轴差值变量
int dy; // 直线y轴差值变量
int dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
int dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
uint16_t dx_x2; // dx*2值变量,用于加快运算速度
uint16_t dy_x2; // dy*2值变量,用于加快运算速度
int di; // 决策变量
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
/* 判断增长方向,或是否为水平线、垂直线、点 */
if(dx>0) // 判断x轴方向
{ dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{ if(dx<0)
{ dx_sym = -1; // dx<0,设置dx_sym=-1
}
else
{ // dx==0,画垂直线,或一点
GUI_RLine(x0, y0, y1, color);
return;
}
}
if(dy>0) // 判断y轴方向
{ dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{ if(dy<0)
{ dy_sym = -1; // dy<0,设置dy_sym=-1
}
else
{ // dy==0,画水平线,或一点
GUI_HLine(x0, y0, x1, color);
return;
}
}
/* 将dx、dy取绝对值 */
dx = dx_sym * dx;
dy = dy_sym * dy;
/* 计算2倍的dx及dy值 */
dx_x2 = dx*2;
dy_x2 = dy*2;
/* 使用Bresenham法进行画直线 */
if(dx>=dy) // 对于dx>=dy,则使用x轴为基准
{ di = dy_x2 - dx;
while(x0!=x1)
{ GUI_Point(x0, y0, color);
x0 += dx_sym;
if(di<0)
{ di += dy_x2; // 计算出下一步的决策值
}
else
{ di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
GUI_Point(x0, y0, color); // 显示最后一点
}
else // 对于dx<dy,则使用y轴为基准
{ di = dx_x2 - dy;
while(y0!=y1)
{ GUI_Point(x0, y0, color);
y0 += dy_sym;
if(di<0)
{ di += dx_x2;
}
else
{ di += dx_x2 - dy_x2;
x0 += dx_sym;
}
}
GUI_Point(x0, y0, color); // 显示最后一点
}
}
/****************************************************************************
* 名称:GUI_LineS()
* 功能:多个点之间的连续连线。从第一点连到第二点,再连到第三点...
* 入口参数: points 多个点坐标数据的指针,数据排列为(x0,y0)、(x1,y1)、(x2,y2)...
* no 点数目,至少要大于1
* color 显示颜色
* 出口参数:无
* 说明:操作失败原因是指定地址超出有效范围。
****************************************************************************/
void GUI_LineS(uint8_t const *points, uint16_t no, TCOLOR color)
{ uint16_t x0, y0;
uint16_t x1, y1;
uint16_t i;
/* 入口参数过滤 */
//if(0==no) return;
//if(1==no) // 单点
if(no==0)return;
else if(no==1) // 单点
{ x0 = *points++;
y0 = *points;
GUI_Point(x0, y0, color);
}
/* 画多条线条 */
x0 = *points++; // 取出第一点坐标值,作为原起点坐标值
y0 = *points++;
for(i=1; i<no; i++)
{ x1 = *points++; // 取出下一点坐标值
y1 = *points++;
GUI_Line(x0, y0, x1, y1, color);
x0 = x1; // 更新原起点坐标
y0 = y1;
}
}
// if((ModeParameter&0xf0)==LcdControry)//取反显示
// {
// memset(tp,0xff,sizeof(tp));
// flag=1;
// temp=CursorAddress;//保存显示的原地址
//
// LCD_WriteCommand(OVLAY);
// LCD_WriteData(0x0d);//合成异或方式
//
// CursorAddress+=0x4000;
//
// for(j=0;j<2;j++,CursorAddress++)
// {
// LCD_Dis2Byte(CursorAddress,tp); //显示白方块做为底色
// CursorAddress+=8*40;
// LCD_Dis2Byte(CursorAddress,tp);
// CursorAddress-=8*40;
// }
// LCD_WriteCommand(OVLAY);
// LCD_WriteData(0x0C);//合成或方式
//
// CursorAddress=temp;//恢复初始显示地址
// }
// else flag=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -