⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_lcdc.c

📁 320240LCD显示控制程序
💻 C
📖 第 1 页 / 共 2 页
字号:
   }

   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 + -