GUI开发--LCD屏幕的使用(非第三方库)--笔记_gui液晶屏-程序员宅基地

技术标签: 图片显示  字体显示  gui  st7789  嵌入式c  

导:界面交互需要GUI,GUI需要文字和图片,所有此处总结在M4芯片上实现GUI的基本操作!该芯片具有160K大小的内存,有512K的flash;故而没有使用第三方库! 

LCD屏幕的使用--笔记

           1.汉字显示-两种方式

                      ·字符数组格式

                      ·汉字库格式

          2.双色2位图显示

          3.真彩色16位图显示

条件:

                屏幕:ST7789   尺寸:320*240

                配置软件:

      基础的驱动可以实现:LCD_Address_Set 和 LCD_WR_DATA的接口可以用软件或硬件spi实现

可实现的基本效果

1.汉字显示(数组形式)

文字显示格式设置

 存放在一个数据结果中:如下

const typFNT_GB16 tfont16[]={
"升",0x80,0x04,0xE0,0x05,0x3C,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0xFF,0x7F,
0x20,0x04,0x20,0x04,0x20,0x04,0x10,0x04,0x10,0x04,0x08,0x04,0x04,0x04,0x02,0x04,/*"升",0*/
/* (16 X 16 , 宋体 )*/

"级",0x08,0x00,0xC8,0x3F,0x04,0x21,0x04,0x11,0x12,0x11,0x1F,0x09,0x08,0x39,0x04,0x21,
0x82,0x22,0x9F,0x22,0x82,0x14,0x80,0x14,0x58,0x08,0x47,0x14,0x22,0x22,0x80,0x41,/*"级",1*/
/* (16 X 16 , 宋体 )*/

"中",0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0x84,0x10,
0x84,0x10,0x84,0x10,0xFC,0x1F,0x84,0x10,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,/*"中",2*/
/* (16 X 16 , 宋体 )*/
}

其中,对汉字显示定义结构体如下:

结构体定义:

typedef struct 
{
    unsigned char Index[2];    //汉字索引号
    unsigned char Msk[32];  //对应汉字的
}typFNT_GB16; 

汉字显示驱动

/******************************************************************************
      函数说明:显示单个16x16汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese16x16(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{
	uint8_t i,j,m=0;
	uint16_t k;
	uint16_t HZnum;//汉字数目
	uint16_t TypefaceNum;//一个字符所占字节大小
	uint16_t x0=x;
  TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
	HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);	//统计汉字数目
	for(k=0;k<HZnum;k++) 
	{
		if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
		{ 	
			LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
			for(i=0;i<TypefaceNum;i++)
			{
				for(j=0;j<8;j++)
				{	
					if(!mode)//非叠加方式
					{
						if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
						else LCD_WR_DATA(bc);
						m++;
						if(m%sizey==0)
						{
							m=0;
							break;
						}
					}
					else//叠加方式
					{
						if(tfont16[k].Msk[i]&(0x01<<j))	LCD_DrawPoint(x,y,fc);//画一个点
						x++;
						if((x-x0)==sizey)
						{
							x=x0;
							y++;
							break;
						}
					}
				}
			}
		}
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
} 

2. 数值和符号assic码定义

const unsigned char ascii_1608[][16]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x18,0x18,0x00,0x00},/*"!",1*/
{0x00,0x48,0x6C,0x24,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x24,0x24,0x24,0x7F,0x12,0x12,0x12,0x7F,0x12,0x12,0x12,0x00,0x00},/*"#",3*/
{0x00,0x00,0x08,0x1C,0x2A,0x2A,0x0A,0x0C,0x18,0x28,0x28,0x2A,0x2A,0x1C,0x08,0x08},/*"$",4*/
{0x00,0x00,0x00,0x22,0x25,0x15,0x15,0x15,0x2A,0x58,0x54,0x54,0x54,0x22,0x00,0x00},/*"%",5*/
{0x00,0x00,0x00,0x0C,0x12,0x12,0x12,0x0A,0x76,0x25,0x29,0x11,0x91,0x6E,0x00,0x00},/*"&",6*/
{0x00,0x06,0x06,0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40,0x00},/*"(",8*/
{0x00,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x04,0x02,0x00},/*")",9*/
{0x00,0x00,0x00,0x00,0x08,0x08,0x6B,0x1C,0x1C,0x6B,0x08,0x08,0x00,0x00,0x00,0x00},/*"*",10*/
{0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x7F,0x08,0x08,0x08,0x08,0x00,0x00,0x00},/*"+",11*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x04,0x03},/*",",12*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00},/*".",14*/
{0x00,0x00,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00},/*"/",15*/
{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"0",16*/
{0x00,0x00,0x00,0x08,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"1",17*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x20,0x20,0x10,0x08,0x04,0x42,0x7E,0x00,0x00},/*"2",18*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x20,0x18,0x20,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0x20,0x30,0x28,0x24,0x24,0x22,0x22,0x7E,0x20,0x20,0x78,0x00,0x00},/*"4",20*/
{0x00,0x00,0x00,0x7E,0x02,0x02,0x02,0x1A,0x26,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"5",21*/
{0x00,0x00,0x00,0x38,0x24,0x02,0x02,0x1A,0x26,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"6",22*/
{0x00,0x00,0x00,0x7E,0x22,0x22,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00},/*"7",23*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},/*"8",24*/
{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x64,0x58,0x40,0x40,0x24,0x1C,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00}/*":",26*/
};

字符和数组的驱动 --- 检索方式:根据字符和空格的间隔进行检索

/******************************************************************************
      函数说明:显示单个字符
      入口数据:x,y显示坐标
                num 要显示的字符
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{
	uint8_t temp,sizex,t,m=0;
	uint16_t i,TypefaceNum;//一个字符所占字节大小
	uint16_t x0=x;
	sizex=sizey/2;
	TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
	num=num-' ';    //得到偏移后的值
	LCD_Address_Set(x,y,x+sizex-1,y+sizey-1);  //设置光标位置 
	for(i=0;i<TypefaceNum;i++)
	{ 
		if(sizey==12)temp=ascii_1206[num][i];		       //调用6x12字体
		else if(sizey==16)temp=ascii_1608[num][i];		 //调用8x16字体
		else if(sizey==24)temp=ascii_2412[num][i];		 //调用12x24字体
		else if(sizey==32)temp=ascii_3216[num][i];		 //调用16x32字体
		else return;
		for(t=0;t<8;t++)
		{
			if(!mode)//非叠加模式
			{
				if(temp&(0x01<<t))LCD_WR_DATA(fc);
				else LCD_WR_DATA(bc);
				m++;
				if(m%sizex==0)
				{
					m=0;
					break;
				}
			}
			else//叠加模式
			{
				if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点
				x++;
				if((x-x0)==sizex)
				{
					x=x0;
					y++;
					break;
				}
			}
		}
	}   	 	  
}


/******************************************************************************
      函数说明:显示字符串
      入口数据:x,y显示坐标
                *p 要显示的字符串
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowString(uint16_t x,uint16_t y,char *p,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{         
	while(*p!='\0')
	{       
		LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
		x+=sizey/2;
		p++;
	}  
}

填充函数:

//局部清屏
void LcdClrRect(INT16 usLeft, INT16 usTop, INT16 usRight, INT16 usBottom, INT32U ucColor)
{
	INT16 i,j;

    LCD_WindowsSet(usLeft,usRight,usTop,usBottom);
	for(i = usTop; i <= usBottom; i++)
	{
		for(j = usLeft; j <= usRight; j++)
		{
			LCD_Write_Data(ucColor);
		}
	}
}

app的代码演示(使用上述的汉字显示和字符显示)

#if TEST_DEMO_HZ
			{
    			u8Process = 50;//升级进度[0:100]
                LcdClrRect(0, 0, 320, 240, BLACK);//黑背景
                LCD_ShowChinese16x16(60,100,"升",WHITE,BLACK,16,1);
                LCD_ShowChinese16x16(80,100,"级",WHITE,BLACK,16,1);
                LCD_ShowChinese16x16(100,100,"中",WHITE,BLACK,16,1);
                LCD_ShowString(180, 100,"50%",WHITE,BACKCOLOR,16,1);

                LcdClrRect(60, 120, 260,140,WHITE);
                LcdClrRect(60, 120, 60+2*u8Process,140,RED);
			}
#endif

效果显示:

优点:不依赖外部flash,根据自己喜欢的汉字裁剪并显示、灵活可控

确定:汉字太少,一旦确定不能改变;汉字一旦多消耗太多的ram或rom;造成负担

3.汉字显示--(汉字 字库显示)

实现的方式:先将汉字字库文件存放在某一个存储器的位置a

然后当要显示某一个汉字的时候,会根据汉字,先将汉字的16进制码(比如汉字“你”对应的16进制为C4 E3),根据根据偏移量计算区码和位码(类似算出在x、y坐标或者类似住的地址-某个区的某个栋);然后计算出该字的具体偏移位置ulOffset;

16进制:
        qm = *(s) - 0xaf;        //区码 -161->A1
        wm = *(s + 1) - 0xa0;//位码 -A1
        ulOffset = (INT32U)((qm-1) * 94 + (wm-1)) * 72;//计算区位码
然后从位置a(汉字字库存储的位置)的偏移ulOffset处读取出该汉字的点阵16进制码
        ExFlash_SeekHzk("HZK.BIN",hzflashbuf,ulOffset,sizeof(hzbuf));
接下来就是显示的情况和数组的显示方式一样:
        memcpy(hzbuf,hzflashbuf,sizeof(hzbuf));

for(y = 0; y < 16; y++)
        {
            for(x = 0; x < 16; x++) 
            {
                k = x % 8;
                if (hzbuf[y * 2 + x / 8]  & (0x80 >> k))
                {
                    xx = x0 + x;
                    LCD_DrawPoint( xx, y + y0, ForeColor);
                }
            }
        }

最终调用画点函数实现具体的点阵点亮操作; 
显示的效果和数组的一模一样;

上述的驱动是16进制,其他进制的,比如24进制的不一样了(主要是计算区码和位码,同一个子需要的点阵数量不一样就要在点阵画点操作有所区别了)

qm = *(s) - 0xaf;    //161->A1
		wm = *(s + 1) - 0xa0;//A1
		ulOffset = (INT32U)((qm-1) * 94 + (wm-1)) * 72;//计算区位码
ExFlash_SeekHzk("HZK.BIN",hzflashbuf,ulOffset,sizeof(hzbuf));
			memcpy(hzbuf,hzflashbuf,sizeof(hzbuf));
 for( i = 0; i < 24; ++i)
        for( j = 0; j < 3; ++j)
        for( k = 0; k < 8; k++)
        if(((hzbuf[i* 3 + j] >> (7 - k)) & 0x1) != NULL)
        {
            current_start_x = x0 + i ;//24*24的是纵向排列的i对应的是x
            current_start_y = y0 + j * 8 + k;
            LCD_DrawPoint( current_start_x,current_start_y , ForeColor);

        }

 附加:汉字字库如何生成(需要软件0点阵字库生成器-自行网上下载,免费的有很多!)

注意:汉字字库文件,存储大小,常用的16号字体,需要260多k,24号字体需要400k左右(提供参考),对空间要求严格者需要慎重!!!

4.双色图(除开背景色-也可以叫单色图)-图像实现

显示双色图--的这个操作--对于图片很多的芯片,相对余全真彩色--节省空间会很有很大助力!
打开软件:安装图中的要求进行设置(图中的要求会对应到后面的驱动和画点函数顺序的操作)

上述的配置对应到驱动如下(驱动不一样--配置也要修改)

/******************************************************************************
      函数说明:在指定位置画点
      入口数据:x,y 画点坐标
                color 点的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color)
{
	LCD_Address_Set(x,y,x,y);//设置光标位置 
	LCD_WR_DATA(color);
} 
/******************************************************************************
      函数说明:显示双色图,比如黑白-图片,或红-绿图-双色图
      入口数据:x,y起点坐标
                length 图片长度
                width  图片宽度
                pic[]  图片数组    
      返回值:  无

    注意:length长度和length宽度,必须是8的整数比如40*40 或 224*40
******************************************************************************/

void LCD_ShowPic4(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[],uint16_t fc,uint16_t bc)
{
	uint16_t i,j,t=0;
	uint16_t h=0;
    if(length>320)
    {
     
        printf("参数错误%d in[%s]",length,__func__);
        length = 320;
    }
    if(width>240)
    {
        printf("参数错误%d in[%s]",width,__func__);
        width = 240;
    }
    
	LCD_Address_Set(x,y,x+length-1,y+width-1);
	for(i=0;i<length;i++)
	{
		for(j=0;j<width;j++)
		{
			h= (i*width + j)/8;
			t= (i*width + j)%8;
				if(pic[h]&(0x01<<t)) 
					LCD_DrawPoint(x+i,y+j,fc);//画一个点
				else 
					LCD_DrawPoint(x+i,y+j,bc);//画一个点
		}
	}			
}

比如:(对一个图片只有两重颜色前景色和后景色--比如下图只有黑和白)

 实现结果

const unsigned char gImage_OutOne[] = { 
#if 1
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0x01,0xE0,
0xFF,0xFF,0xFF,0x07,0xF0,0xFF,0xFF,0xFF,0x0F,0xF0,0x00,0x00,0x00,0x0F,0x78,0x00,
0x00,0x00,0x0E,0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0x00,
0x00,0x1E,0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0x00,0x00,
0x1E,0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0x00,0x00,0x1E,
0x78,0x00,0x00,0x00,0x1E,0x78,0x00,0xFF,0x00,0x1E,0x78,0xC0,0xFF,0x07,0x1E,0x30,
0xE0,0xFF,0x1F,0x1E,0x20,0x78,0xFC,0x0F,0x1E,0x60,0x3C,0x7E,0x00,0x1E,0xF0,0x9F,
0x0F,0x00,0x1E,0xF0,0xCF,0x03,0x00,0x1E,0xF0,0xE7,0x01,0x00,0x1E,0x70,0xF3,0x00,
0x00,0x1E,0x70,0x70,0x00,0x00,0x1E,0x30,0x78,0x00,0x00,0x1E,0x30,0xF8,0x01,0x00,
0x1E,0x38,0xE0,0x03,0x00,0x1E,0x38,0xE0,0x07,0x00,0x1E,0x38,0xFC,0x01,0x00,0x0E,
0x38,0x7F,0xFF,0xFF,0x0F,0xD8,0x0F,0xFF,0xFF,0x07,0xF8,0x03,0xFF,0xFF,0x03,0xFC,
0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"1.bmp",0*/
#endif 
};

实现的项目demo--播放器界面
实际效果  

如下这些图标都是采用这个方式来实现的

具体代码实现(部分)

const unsigned char g_IMAGE_GO_HEAD[] ={
0x00,0x00,0xFC,0x1F,0xF8,0x0F,0xF8,0x0F,0xF0,0x07,0xE0,0x03,0xC0,0x01,0x00,0x00,
0xFC,0x1F,0xFC,0x1F,0xF8,0x0F,0xF0,0x07,0xE0,0x03,0xC0,0x01,0x00,0x00,0x00,0x00,
};
const unsigned char g_IMAGE_PLAY[] ={
#if 1
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x03,0x00,0x00,0xF8,0xFF,0x1F,0x00,0x00,
0xFC,0xFF,0x3F,0x00,0x00,0x3F,0x00,0xFC,0x00,0x80,0x0F,0x00,0xF0,0x01,0xC0,0x07,
0x00,0xE0,0x03,0xE0,0x01,0x00,0x80,0x07,0xF0,0x00,0x00,0x00,0x0F,0x70,0x00,0x00,
0x00,0x0E,0x78,0x00,0x00,0x00,0x1E,0x3C,0x00,0x00,0x00,0x3C,0x1C,0x00,0x00,0x00,
0x38,0x1C,0x00,0x00,0x00,0x38,0x1E,0x00,0x00,0x00,0x78,0x0E,0x00,0x00,0x00,0x70,
0x0E,0xFC,0xFF,0x0F,0x70,0x0E,0xFC,0xFF,0x0F,0x70,0x0E,0xF8,0xFF,0x07,0x70,0x0E,
0xF0,0xFF,0x03,0x70,0x0E,0xF0,0xFF,0x03,0x70,0x0E,0xE0,0xFF,0x01,0x70,0x0E,0xC0,
0xFF,0x00,0x70,0x0E,0x80,0xFF,0x00,0x70,0x0E,0x80,0x7F,0x00,0x70,0x1E,0x00,0x3F,
0x00,0x78,0x1C,0x00,0x1E,0x00,0x38,0x1C,0x00,0x1E,0x00,0x38,0x3C,0x00,0x00,0x00,
0x3C,0x78,0x00,0x00,0x00,0x1E,0x70,0x00,0x00,0x00,0x0E,0xF0,0x00,0x00,0x00,0x0F,
0xE0,0x01,0x00,0x80,0x07,0xC0,0x07,0x00,0xE0,0x03,0x80,0x0F,0x00,0xF0,0x01,0x00,
0x3F,0x00,0xFC,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0xF8,0xFF,0x1F,0x00,0x00,0xC0,
0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
#endif
};
const unsigned char g_IMAGE_STOP[] ={
#if 1
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x03,0x00,0x00,0xF8,0xFF,0x1F,0x00,0x00,
0xFC,0xFF,0x3F,0x00,0x00,0x3F,0x00,0xFC,0x00,0x80,0x0F,0x00,0xF0,0x01,0xC0,0x07,
0x00,0xE0,0x03,0xE0,0x01,0x00,0x80,0x07,0xF0,0x00,0x00,0x00,0x0F,0x70,0x00,0x00,
0x00,0x0E,0x78,0x00,0x00,0x00,0x1E,0x3C,0x00,0x00,0x00,0x3C,0x1C,0x00,0x00,0x00,
0x38,0x1C,0x00,0x00,0x00,0x38,0x1E,0xE0,0xFF,0x07,0x78,0x0E,0xE0,0xFF,0x07,0x70,
0x0E,0xE0,0xFF,0x07,0x70,0x0E,0xE0,0xFF,0x07,0x70,0x0E,0x00,0x00,0x00,0x70,0x0E,
0x00,0x00,0x00,0x70,0x0E,0x00,0x00,0x00,0x70,0x0E,0x00,0x00,0x00,0x70,0x0E,0x00,
0x00,0x00,0x70,0x0E,0xE0,0xFF,0x07,0x70,0x0E,0xE0,0xFF,0x07,0x70,0x1E,0xE0,0xFF,
0x07,0x78,0x1C,0xE0,0xFF,0x07,0x38,0x1C,0x00,0x00,0x00,0x38,0x3C,0x00,0x00,0x00,
0x3C,0x78,0x00,0x00,0x00,0x1E,0x70,0x00,0x00,0x00,0x0E,0xF0,0x00,0x00,0x00,0x0F,
0xE0,0x01,0x00,0x80,0x07,0xC0,0x07,0x00,0xE0,0x03,0x80,0x0F,0x00,0xF0,0x01,0x00,
0x3F,0x00,0xFC,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0xF8,0xFF,0x1F,0x00,0x00,0xC0,
0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
/* (40 X 40 ) */
#endif
};
const unsigned char g_IMAGE_Volumn[] ={ //音量
0xE0,0x0F,0xE0,0x0F,0xE0,0x0F,0xF0,0x0F,0xF8,0x1F,0xFC,0x3F,0xFC,0x3F,0xFC,0x7F,
0x00,0x00,0x30,0x0C,0x70,0x0E,0xF0,0x0F,0xC4,0x63,0x1C,0x78,0xFC,0x3F,0xF0,0x0F,
};
const unsigned char g_IMAGE_Progress[] ={ //进度
0x00,0x00,0x02,0x00,0x02,0x80,0x02,0x80,0x7E,0xFC,0x7E,0xFC,0xE2,0xFE,0xC2,0xFF,
0x82,0xFF,0xC2,0xFF,0xE2,0xFE,0xFE,0xFE,0x7E,0xFC,0x02,0xF0,0x02,0x80,0x02,0x80,
};
//初始化播放页面
void show_play_menu_init()
{
    LCD_Fill(0,22,320,220-1,BACKCOLOR);
    Lcd_Printf(13, 40,WHITE,"录音回放和导出");
    Lcd_Printf(77, 166,WHITE,"后退");
    
    Lcd_Printf(216, 166,WHITE,"前进");
    LCD_ShowPic4(83,133,16,16,g_IMAGE_GO_BACK,WHITE,BACKCOLOR);
    
    LCD_ShowPic4(222,133,16,16,g_IMAGE_GO_HEAD,WHITE,BACKCOLOR);
    LCD_ShowPic4(29,192,16,16,g_IMAGE_Progress,WHITE,BACKCOLOR);
    LCD_ShowPic4(287,194,16,16,g_IMAGE_Volumn,WHITE,BACKCOLOR);

    Lcd_Printf(36,68,WHITE,"正在播放:");
    Lcd_Printf(54,194,WHITE,"播放进度");
    Lcd_Printf(125, 195,WHITE,"00:00:20/00:12:36");
    LCD_Fill(0,220,320,240,BACKCOLOR);
    Lcd_Printf2(20,224,WHITE,"【确认】导出  ←左调 右调→",1,BACKCOLOR); 
}

4.16位真彩色图的实现 推荐两款软件

推荐两款软件。

第一个如下的这个软件Img2Lcd.exe(需要设置驱动的参数--包含头,高低位...等)

软件特色
  Image2Lcd 能把各种来源的图片转换成特定的数据格式以用来匹配单片机系统所需要的显示数据格式
  Image2Lcd支持的输入图像格式包括:BMP, WBMP, JPG, GIF, WMF, EMF, ICO, 等等。           Image2Lcd的输出数据类型包括定制的二进制类型、C语言数组类型和标准的BMP格式、WBMP格式
  Image2Lcd能可视调节输入图象的数据扫描方式、灰度(颜色数)、图像数据排列方式、亮度、对比度、等等
  对于包含了图像头数据保存的图像数据文件,Image2Lcd能重新打开作为输入图像
****支持所有的点阵LCD所需要的特殊显示数据格式。
  可视调节输出图像效果。
  256色模式下支持用户调色板(TIFF格式)。
  支持4096色图像输出。
  以二进制类型和C语言数组类型(文本)两种方式保存数据,方便单片机开发者的不同需要。
  保存的数据支持LSB First/MSB First(很多单片机系统WORD高低字节排列与PC相反)。
  可以保存图像为指定颜色数的BMP格式图像。
  即时图示当前设置的数据格式。
        

第二个软件是bmp2h.exe(规定好了驱动的方式)
                                            

位图变换(bmp2h)是一款可以把bmp格式的图片转化成64K色的数组数据信息

应用:

点一下功能键“添加将一个bmp图片添加进去,随后点一下功能键“变换就会转化成图片数组文档。表明:假如要应用转化成的图片数组数据信息,必须在转化成的c文档开始添加一条句子:#define WIN32

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaoxilang/article/details/127029173

智能推荐

JavaScript学习笔记_curry函数未定义-程序员宅基地

文章浏览阅读343次。五种原始的变量类型1.Undefined--未定义类型 例:var v;2.String -- ' '或" "3.Boolean4.Number5.Null--空类型 例: var v=null;Number中:NaN -- not a number非数本身是一个数字,但是它和任何数字都不相等,代表非数,它和自己都不相等判断是不是NaN不能用=_curry函数未定义

兑换码编码方案实践_优惠券编码规则-程序员宅基地

文章浏览阅读1.2w次,点赞2次,收藏17次。兑换码编码设计当前各个业务系统,只要涉及到产品销售,就离不开大大小小的运营活动需求,其中最普遍的就是兑换码需求,无论是线下活动或者是线上活动,都能起到良好的宣传效果。兑换码:由一系列字符组成,每一个兑换码对应系统中的一组信息,可以是优惠信息(优惠券),也可以是相关奖品信息。在实际的运营活动中,要求兑换码是唯一的,每一个兑换码对应一个优惠信息,而且需求量往往比较大(实际上的需求只有预期_优惠券编码规则

c语言周林答案,C语言程序设计实训教程教学课件作者周林ch04结构化程序设计课件.ppt...-程序员宅基地

文章浏览阅读45次。C语言程序设计实训教程教学课件作者周林ch04结构化程序设计课件.ppt* * 4.1 选择结构程序设计 4.2 循环结构程序设计 4.3 辅助控制语句 第四章 结构化程序设计 4.1 选择结构程序设计 在现实生活中,需要进行判断和选择的情况是很多的: 如果你在家,我去拜访你 如果考试不及格,要补考 如果遇到红灯,要停车等待 第四章 结构化程序设计 在现实生活中,需要进行判断和选择的情况..._在现实生活中遇到过条件判断的问

幻数使用说明_ioctl-number.txt幻数说明-程序员宅基地

文章浏览阅读999次。幻数使用说明 在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事情。 因为设备都是特定的,这里也没法说。关键在于怎样组织命令码,因为在ioctl中命令码是唯一联系用户程序命令和驱动程序支持的途径 。 命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,利_ioctl-number.txt幻数说明

ORB-SLAM3 + VScode:检测到 #include 错误。请更新 includePath。已为此翻译单元禁用波浪曲线_orb-slam3 include <system.h> 报错-程序员宅基地

文章浏览阅读399次。键盘按下“Shift+Ctrl+p” 输入: C++Configurations,选择JSON界面做如下改动:1.首先把 “/usr/include”,放在最前2.查看C++路径,终端输入gcc -v -E -x c++ - /usr/include/c++/5 /usr/include/x86_64-linux-gnu/c++/5 /usr/include/c++/5/backward /usr/lib/gcc/x86_64-linux-gnu/5/include /usr/local/_orb-slam3 include 报错

「Sqlserver」数据分析师有理由爱Sqlserver之十-Sqlserver自动化篇-程序员宅基地

文章浏览阅读129次。本系列的最后一篇,因未有精力写更多的入门教程,上篇已经抛出书单,有兴趣的朋友可阅读好书来成长,此系列主讲有理由爱Sqlserver的论证性文章,希望读者们看完后,可自行做出判断,Sqlserver是否真的合适自己,目的已达成。渴望自动化及使用场景笔者所最能接触到的群体为Excel、PowerBI用户群体,在Excel中,我们知道可以使用VBA、VSTO来给Excel带来自动化操作..._sqlsever 数据分析

随便推点

智慧校园智慧教育大数据平台(教育大脑)项目建设方案PPT_高校智慧大脑-程序员宅基地

文章浏览阅读294次,点赞6次,收藏4次。教育智脑)建立学校的全连接中台,对学校运营过程中的数据进行处理和标准化管理,挖掘数据的价值。能:一、原先孤立的系统聚合到一个统一的平台,实现单点登录,统一身份认证,方便管理;三、数据共享,盘活了教育大数据资源,通过对外提供数。的方式构建教育的通用服务能力平台,支撑教育核心服务能力的沉淀和共享。物联网将学校的各要素(人、机、料、法、环、测)全面互联,数据实时。智慧校园解决方案,赋能教学、管理和服务升级,智慧教育体系,该数据平台具有以下几大功。教育大数据平台底座:教育智脑。教育大数据平台,以中国联通。_高校智慧大脑

编程5大算法总结--概念加实例_算法概念实例-程序员宅基地

文章浏览阅读9.5k次,点赞2次,收藏27次。分治法,动态规划法,贪心算法这三者之间有类似之处,比如都需要将问题划分为一个个子问题,然后通过解决这些子问题来解决最终问题。但其实这三者之间的区别还是蛮大的。贪心是则可看成是链式结构回溯和分支界限为穷举式的搜索,其思想的差异是深度优先和广度优先一:分治算法一、基本概念在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两_算法概念实例

随笔—醒悟篇之考研调剂_考研调剂抑郁-程序员宅基地

文章浏览阅读5.6k次。考研篇emmmmm,这是我随笔篇章的第二更,原本计划是在中秋放假期间写好的,但是放假的时候被安排写一下单例模式,做了俩机试题目,还刷了下PAT的东西,emmmmm,最主要的还是因为我浪的很开心,没空出时间来写写东西。  距离我考研结束已经快两年了,距离今年的考研还有90天左右。  趁着这个机会回忆一下青春,这一篇会写的比较有趣,好玩,纯粹是为了记录一下当年考研中发生的有趣的事。  首先介绍..._考研调剂抑郁

SpringMVC_class org.springframework.web.filter.characterenco-程序员宅基地

文章浏览阅读438次。SpringMVC文章目录SpringMVC1、SpringMVC简介1.1 什么是MVC1.2 什么是SpringMVC1.3 SpringMVC的特点2、HelloWorld2.1 开发环境2.2 创建maven工程a>添加web模块b>打包方式:warc>引入依赖2.3 配置web.xml2.4 创建请求控制器2.5 创建SpringMVC的配置文件2.6 测试Helloworld2.7 总结3、@RequestMapping注解3.1 @RequestMapping注解的功能3._class org.springframework.web.filter.characterencodingfilter is not a jakart

gdb: Don‘t know how to run. Try “help target“._don't know how to run. try "help target".-程序员宅基地

文章浏览阅读4.9k次。gdb 远程调试的一个问题:Don't know how to run. Try "help target".它在抱怨不知道怎么跑,目标是什么. 你需要为它指定target remote 或target extended-remote例如:target extended-remote 192.168.1.136:1234指明target 是某IP的某端口完整示例如下:targ..._don't know how to run. try "help target".

c语言程序设计教程 郭浩志,C语言程序设计教程答案杨路明郭浩志-程序员宅基地

文章浏览阅读85次。习题 11、算法描述主要是用两种基本方法:第一是自然语言描述,第二是使用专用工具进行算法描述2、c 语言程序的结构如下:1、c 语言程序由函数组成,每个程序必须具有一个 main 函数作为程序的主控函数。2、“/*“与“*/“之间的内容构成 c 语言程序的注释部分。3、用预处理命令#include 可以包含有关文件的信息。4、大小写字母在 c 语言中是有区别的。5、除 main 函数和标准库函数以..._c语言语法0x1e