完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>
我写了大半天的程序,从像素位置显示字符串函数开始一点点调试改来的,我这里只做了32*32的字体实现,可以参考本程序,实现12,16,24等字体的这个功能,先看一下使用说明:
我封装出来的函数: // x:0-14,y:0-24,单位是每个字32像素的个数,改造成LCD1525这样的屏幕,我的屏幕是480*800,总共显示15x25个汉字(类似带字库的LCD12864屏幕那样的显示方式),支持自动换行,屏幕上下自动循环,字母串自动补充空格实现对齐显示,不然汉字的一半刚好显示在屏幕结尾时候,是会乱码的 void myShow_String_15x25LCD(u8 x,u8 y,u8*str,u32 color) 主函数中这样调用后 显示效果: 可以看到当字符串中字母串是奇数个的时候,我是把它添加了空格的,这样每个汉字始终是在正确的位置上,其次屏幕底部自动换行到屏幕顶部了,实现了我们需要的功能。 所以只要我们给这个函数一个很长很长的字符串,比如在做记事本这类软件时候,从sd卡文本文件里面读取到任意长(里面用的是u16的类型,那么最大读取文本长度可能不能太大,一般而言几千字符没问题,那就一部分一部分的读呗就可以了)的字符串,然后给这个函数就能自动换行,自动上下屏幕循环显示了,不需要我们自己手动去费尽心思考虑显示位置,何时换行,对齐等等问题 核心.c代码我直接贴出来,免得去csdn下载 我是在正点原子的教程汉字显示实验改的,如果需要完整工程可以找我要,也可以自己去原子那儿下载,然后把这个.C和.h文件替换掉即可: text.h text.h #ifndef __TEXT_H__ #define __TEXT_H__ #include "fontupd.h" // //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK STM32H7开发板 //汉字显示 驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //创建日期:2018/8/2 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2014-2024 //All rights reserved // void Get_HzMat(unsigned char *code,unsigned char *mat,u8 size); //得到汉字的点阵码 void Show_Font(u16 x,u16 y,u8 *font,u8 size,u8 mode); //在指定位置显示一个汉字 void Show_Str(u16 x,u16 y,u16 width,u16 height,u8*str,u8 size,u8 mode); //在指定位置显示一个字符串 void Show_Str_Mid(u16 x,u16 y,u8*str,u8 size,u8 len); // x:0-14,y:0-24,单位是每个字32像素的个数,改造成LCD12864这样的屏幕,总共显示15x25个汉字 void myShow_String_15x25LCD(u8 x,u8 y,u8*str,u32 color); #endif text.c #include "sys.h" #include "fontupd.h" #include "w25qxx.h" #include "lcd.h" #include "text.h" #include "string.h" #include "usart.h" #include "malloc.h" // //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK STM32H7开发板 //汉字显示 驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //创建日期:2018/8/2 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2014-2024 //All rights reserved // //code 字符指针开始 //从字库中查找出字模 //code 字符串的开始地址,GBK码 //mat 数据存放地址 (size/8+((size%8)?1:0))*(size) bytes大小 //size:字体大小 void Get_HzMat(unsigned char *code,unsigned char *mat,u8 size) { unsigned char qh,ql; unsigned char i; unsigned long foffset; u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数 qh=*code; ql=*(++code); if(qh<0x81||ql<0x40||ql==0xff||qh==0xff)//非 常用汉字 { for(i=0;i } if(ql<0x7f)ql-=0x40;//注意! else ql-=0x41; qh-=0x81; foffset=((unsigned long)190*qh+ql)*csize; //得到字库中的字节偏移量 switch(size) { case 12: W25QXX_Read(mat,foffset+ftinfo.f12addr,csize); break; case 16: W25QXX_Read(mat,foffset+ftinfo.f16addr,csize); break; case 24: W25QXX_Read(mat,foffset+ftinfo.f24addr,csize); break; case 32: W25QXX_Read(mat,foffset+ftinfo.f32addr,csize); break; } } //显示一个指定大小的汉字 //x,y :汉字的坐标 //font:汉字GBK码 //size:字体大小 //mode:0,正常显示,1,叠加显示 void Show_Font(u16 x,u16 y,u8 *font,u8 size,u8 mode) { u8 temp,t,t1; u16 y0=y; u8 dzk[128]; u8 csize=(size/8+((size%8)?1:0))*(size); //得到字体一个字符对应点阵集所占的字节数 if(size!=12&&size!=16&&size!=24&&size!=32)return; //不支持的size Get_HzMat(font,dzk,size); //得到相应大小的点阵数据 for(t=0;t temp=dzk[t]; //得到点阵数据 for(t1=0;t1<8;t1++) { if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR); else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR); temp<<=1; y++; if((y-y0)==size) { y=y0; x++; break; } } } } u16 myGetLengthOfStr(u8*str) { u16 n=0; while(*str!=0)//数据未结束 { ++str; ++n; } return n; } u16 myGetNumSpaceInsetFromStr(u8*str) { u16 n=0; u16 cntSpace=0; while(*str!=0)//数据未结束 { if(*str>0x80) // 是汉字 { str=str+2; if(n%2==1) // 如果n是奇数个英文字符 { cntSpace++; } n=0; } else { str++; n++; } } return cntSpace; } // 函数作用:把一个字符串里面连续的英文字符变成偶数个,且存放在新的空间,方便后面的液晶显示函数 // 比如"你abc好a它b"->"你abc 好a 它b ",如果本来就是偶数个,那就不需要填充空格了 u8*myStr2StrHaveSpace(u8*str) { u16 nStr=myGetNumSpaceInsetFromStr(str); u8* p=mymalloc(SRAMEX,myGetLengthOfStr(str)+nStr+1);// 最后一个填' ' u8* pTmp=p; u16 n=0; while(*str!=0)//数据未结束 { if(*str>0x80) // 是汉字 { if(n%2==1) // 如果n是奇数个英文字符 { *p=' '; p=p+1; } n=0; *p=*str; // 拷贝字符过去 *(p+1)=*(str+1); str=str+2; p=p+2; } else { *p=*str; // 拷贝字符过去 str++; p++; n++; } } *p=' '; return pTmp; } // 这个函数是我自己写的工具函数,不对外开放,下面的函数自己调用的,用来解决每一行的片段显示功能 void myShow_Str(u16 x,u16 y,u16 width,u16 height,u8*str,u8 size,u8 mode) { u16 a=0; u8 b; a=width/16; b=*(str+a); *(str+a)=' '; Show_Str(x,y,width,height,str,32,0); *(str+a)=b; } // x:0-14,y:0-24,单位是每个字32像素的个数,改造成LCD12864这样的屏幕,总共显示15x25个汉字,支持自动换行 void myShow_String_15x25LCD(u8 x,u8 y,u8*str,u32 color) { u16 cnt = 0; u16 nRow = 0; u16 nC = 0; // 当前行已经显示了多少个字符 u16 nC1 = 0; // 最后一行应该显示多少个字符 u16 i; POINT_COLOR=color; str=myStr2StrHaveSpace(str); cnt=myGetLengthOfStr(str); if((480-32*x) >= (16*cnt)) // 说明当前行就够显示了 { myShow_Str(x*32,y*32,cnt*16,32,str,32,0); } else // 说明需要多行才能显示 { nC = (480-32*x)/16; // 第一行已经显示了多少个字符 nRow = (16*cnt - (480-32*x))/480 + 1; // 计算还需要多少行,加上第一行,总的行数是nRow+1行 nRow=nRow+1; nC1 = cnt-nC-(nRow-2)*30; // 最后一行显示的字符个数,是减去的2(第一行和最后一行),不是1 for(i=0;i if(i==0) // 如果是第一行,肯定不可能超过屏幕底部 { myShow_Str(x*32,y*32,nC*16,32,str,32,0); } else if(i==(nRow-1)) // 如果是最后一行了 { // 这样就实现字符串上下循环屏幕显示效果 // 即(y+i)%25的方式实现y坐标循环 myShow_Str(0,((y+i)%25)*32,nC1*16,32,str+nC+30*(i-1),32,0); } else { myShow_Str(0,((y+i)%25)*32,480,32,str+nC+30*(i-1),32,0); // 30是指每行能显示30个字符 } } } } //在指定位置开始显示一个字符串 //支持自动换行 //(x,y):起始坐标 //width,height:区域 //str :字符串 //size :字体大小 //mode:0,非叠加方式;1,叠加方式 void Show_Str(u16 x,u16 y,u16 width,u16 height,u8*str,u8 size,u8 mode) { u16 x0=x; u16 y0=y; u8 bHz=0; //字符或者中文 while(*str!=0)//数据未结束 { if(!bHz) { if(*str>0x80)bHz=1;//中文 else //字符 { if(x>(x0+width-size/2))//换行 { y+=size; x=x0; } if(y>(y0+height-size))break;//越界返回 if(*str==13)//换行符号 { y+=size; x=x0; str++; } else LCD_ShowChar(x,y,*str,size,mode);//有效部分写入 str++; x+=size/2; //字符,为全字的一半 } }else//中文 { bHz=0;//有汉字库 if(x>(x0+width-size))//换行 { y+=size; x=x0; } if(y>(y0+height-size))break;//越界返回 Show_Font(x,y,str,size,mode); //显示这个汉字,空心显示 str+=2; x+=size;//下一个汉字偏移 } } } //在指定宽度的中间显示字符串 //如果字符长度超过了len,则用Show_Str显示 //len:指定要显示的宽度 void Show_Str_Mid(u16 x,u16 y,u8*str,u8 size,u8 len) { u16 strlenth=0; strlenth=strlen((const char*)str); strlenth*=size/2; if(strlenth>len)Show_Str(x,y,lcddev.width,lcddev.height,str,size,1); else { strlenth=(len-strlenth)/2; Show_Str(strlenth+x,y,lcddev.width,lcddev.height,str,size,1); } } 主函数中这样使用即可:main.c #include "sys.h" #include "delay.h" #include "led.h" #include "usart.h" #include "mpu.h" #include "lcd.h" #include "sdram.h" #include "key.h" #include "malloc.h" #include "nand.h" #include "ftl.h" #include "w25qxx.h" #include "sdmmc_sdcard.h" #include "ff.h" #include "exfuns.h" #include "text.h" //ALIENTEK 阿波罗STM32H7开发板 实验43 //汉字显示 实验 //技术支持:www.openedv.com //广州市星翼电子科技有限公司 int main(void) { Stm32_Clock_Init(160,5,2,4); //设置时钟,400Mhz delay_init(400); //延时初始化 uart_init(100,115200); //串口初始化为115200 LED_Init(); //初始化与LED连接的硬件接口 MPU_Memory_Protection(); //保护相关存储区域 SDRAM_Init(); //初始化SDRAM LCD_Init(); //初始化LCD KEY_Init(); //初始化按键 W25QXX_Init(); //初始化W25Q256 my_mem_init(SRAMIN); //初始化内部内存池(AXI) my_mem_init(SRAMEX); //初始化外部内存池(SDRAM) my_mem_init(SRAM12); //初始化SRAM12内存池(SRAM1+SRAM2) my_mem_init(SRAM4); //初始化SRAM4内存池(SRAM4) my_mem_init(SRAMDTCM); //初始化DTCM内存池(DTCM) my_mem_init(SRAMITCM); //初始化ITCM内存池(ITCM) exfuns_init(); //为fatfs相关变量申请内存 f_mount(fs[0],"0:",1); //挂载SD卡 f_mount(fs[1],"1:",1); //挂载FLASH. font_init(); POINT_COLOR=BLACK; // Show_Str(0,0,200,32,"hello World",32,0); // Show_Str(0,790,100,32,"S你好",32,0); // myShow_String_15x25LCD(0,25,"H你好",BLUE); myShow_String_15x25LCD(0,23," 你好挂载FLASH挂载FLASH为fatfs相关变量申请内存初始化DTCM内存池(DTCM)",BLACK); // LCD_ShowChar(0,785,'A',32,0); // LCD_ShowChar(0,773,'S',32,0); while(1) { } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1198 浏览1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1211 浏览1 评论
620 浏览2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
465 浏览2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1138 浏览2 评论
1676浏览9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
336浏览4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
332浏览3评论
326浏览3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
302浏览3评论
小黑屋|手机版|Archiver|德赢Vwin官网(湘ICP备2023018690号)
GMT+8, 2024-8-31 22:37, Processed in 0.828570 second(s), Total 73, Slave 57 queries .
Powered by德赢Vwin官网 网
© 2015bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号