拼音表大全图_阿波罗 STM32F767 开发板资料连载第五十九章 T9 拼音输入法实验

1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子

0e2dddc96be9bb0718a7f2286ebf6084.png

第五十九章 T9 拼音输入法实验

上一章,我们在 ALIENTEK 阿波罗 STM32 开发板上实现了手写识别输入,但是该方法只

能输入数字或者字母,不能输入汉字。本章,我们将给大家介绍如何在ALIENTEK阿波罗 STM32

开发板上实现一个简单的 T9 中文拼音输入法。本章分为如下几个部:

59.1 拼音输入法简介

59.2 硬件设计

59.3 软件设计

59.4 下载验证

59.1 拼音输入法简介

在计算机上汉字的输入法有很多种,比如拼音输入法、五笔输入法、笔画输入法、区位输

入法等。其中,又以拼音输入法用的最多。拼音输入法又可以分为很多类,比如全拼输入、双

拼输入等。

而在手机上,用的最多的应该算是 T9 拼音输入法了,T9 输入法全名为智能输入法,字库

容量九千多字,支持十多种语言。T9 输入法是由美国特捷通讯(Tegic Communications)软件

公司开发的,该输入法解决了小型掌上设备的文字输入问题,已经成为全球手机文字输入的标

准之一。

一般,手机拼音输入键盘如图 59.1.1 所示:

870f812ad2f13c522cb8af4cdcde1d0d.png

图 59.1.1 手机拼音输入键盘

在这个键盘上,我们对比下传统的输入法和 T9 输入法,输入“中国”两个字需要的按键

次数。传统的方法,先按 4 次 9,输入字母 z,再按 2 次 4,输入字母 h,再按 3 次 6,输入字

母 o,再按 2 次 6,输入字母 n,最后按 1 次 4,输入字母 g。这样,输入“中”字,要按键 12

次,接着同样的方法,输入“国”字,需要按 6 次,总共就是 18 次按键。

如果是 T9,我们输入“中”字,只需要输入:9、4、6、6、4,即可实现输入“中”字,

在选择中字之后,T9 会联想出一系列同中字组合的词,如:文、国、断、山等。这样输入“国”

字,我们直接选择即可,所以输入“国”字按键 0 次,这样 T9 总共只需要 5 次按键。

这就是 T9 智能输入法的优越之处。正因为 T9 输入法高效便捷的输入方式得到了众多手机

厂商的采用,以至于 T9 成为了使用频率最高知名度最大的手机输入法。

本章,我们实现的 T9 拼音输入法,没有真正的 T9 那么强大,我们这里仅实现输入部分,

不支持词组联想。

本章,我们主要通过一个和数字串对应的拼音索引表来实现 T9 拼音输入,我们先将汉语

拼音所有可能的组合全部列出来,如下所示:

const u8 PY_mb_space []={""};const u8 PY_mb_a []={"啊阿腌吖锕厑嗄錒呵腌"};const u8 PY_mb_ai []={"爱埃挨哎唉哀皑癌蔼矮艾碍隘捱嗳嗌嫒瑷暧砹锿霭"};const u8 PY_mb_an []={"安俺按暗岸案鞍氨谙胺埯揞犴庵桉铵鹌黯"};……此处省略 N 多组合const u8 PY_mb_zu []={"足租祖诅阻组卒族俎菹镞"};const u8 PY_mb_zuan []={"钻攥纂缵躜"};const u8 PY_mb_zui []={"最罪嘴醉蕞觜"};const u8 PY_mb_zun []={"尊遵樽鳟撙"};const u8 PY_mb_zuo []={"左佐做作坐座昨撮唑柞阼琢嘬怍胙祚砟酢"};

这里我们只列出了部分组合,我们将这些组合称之为码表,然后将这些码表和其对应的数

字串对应起来,组成一个拼音索引表,如下所示:

const py_index py_index3[]={{"" ,"",(u8*)PY_mb_space},{"2","a",(u8*)PY_mb_a},{"3","e",(u8*)PY_mb_e},{"6","o",(u8*)PY_mb_o},{"24","ai",(u8*)PY_mb_ai},{"26","an",(u8*)PY_mb_an},……此处省略 N 多组合{"94664","zhong",(u8*)PY_mb_zhong},{"94824","zhuai",(u8*)PY_mb_zhuai},{"94826","zhuan",(u8*)PY_mb_zhuan},{"248264","chuang",(u8*)PY_mb_chuang},{"748264","shuang",(u8*)PY_mb_shuang},{"948264","zhuang",(u8*)PY_mb_zhuang},}

其中 py_index 是一个结构体,定义如下:

typedef struct

{

u8 *py_input;

//输入的字符串

u8 *py;

//对应的拼音

u8 *pymb; //码表

}py_index;

其中 py_input,即与拼音对应的数字串,比如“94824”。py,即与 py_input 数字串对应的

拼音,如果 py_input=“94824”,那么 py 就是“zhuai”。最后 pymb,就是我们前面说到的码表。

注意,一个数字串可以对应多个拼音,也可以对应多个码表。

在有了这个拼音索引表(py_index3)之后,我们只需要将输入的数字串和 py_index3 索引

表里面所有成员的 py_input 对比,将所有完全匹配的情况记录下来,用户要输入的汉字就被确

定了,然后由用户选择可能的拼音组成(假设有多个匹配的项目),再选择对应的汉字,即完成

一次汉字输入。

当然还可能是找遍了索引表,也没有发现一个完全符合要求的成员,那么我们会统计匹配

数最多的情况,作为最佳结果,反馈给用户。比如,用户输入“323”,找不到完全匹配的情况,

那么我们就将能和“32”匹配的结果返回给用户。这样,用户还是可以得到输入结果,同时还

可以知道输入有问题,提示用户需要检查输入是否正确。

以上,就是我们的 T9 拼音输入法原理,关于拼音输入法,我们就介绍到这里。

最后,我们看看一个完整的 T9 拼音输入步骤(过程):

1) 输入拼音数字串

本章,我们用到的 T9 拼音输入法的核心思想就是对比用户输入的拼音数字串,所以必

须先由用户输入拼音数字串。

2) 在拼音索引表里面查找和输入字符串匹配的项,并记录

在得到用户输入的拼音数字串之后,在拼音索引表里面查找所有匹配的项目,如果有

完全匹配的项目,就全部记录下来,如果没有完全匹配的项目,则记录匹配情况最好的一

个项目。

3) 显示匹配清单里面所有可能的汉字,供用户选择.

将匹配项目的拼音和对应的汉字显示出来,供用户选择。如果有多个匹配项(一个数

字串对应多个拼音的情况),则用户还可以选择拼音。

4) 用户选择匹配项,并选择对应的汉字.

用户对匹配的拼音和汉字进行选择,选中其真正想输入的拼音和汉字,实现一次拼音

输入。

以上 4 个步骤,就可以实现一个简单的 T9 汉字拼音输入法。

59.2 硬件设计

本章实验功能简介:开机的时候先检测字库,然后显示提示信息和绘制拼音输入表,之后

进入等待输入状态。此时用户可以通过屏幕上的拼音输入表输入拼音数字串(通过 DEL 可以实

现退格),然后程序自动检测与之对应的拼音和汉字,并显示在屏幕上(同时输出到串口)。

如果有多个匹配的拼音,则通过 KEY_UP 和 KEY1 进行选择。按键 KEY0 用于清除一次输入,

按键 KEY2 用于触摸屏校准。

本实验用到的资源如下:

1) 指示灯 DS0

2) 四个按键(KEY0/KEY1/KEY2/KEY_UP)

3) 串口

4) LCD 模块(含触摸屏)

5) SPI FLASH

这些用到的硬件,我们在之前都已经介绍过,这里就不再介绍了。

59.3 软件设计

打开本章实验工程可以看到,我们在根目录文件夹下新建了一个 T9INPUT 的文件夹。在

该文件夹下面新建了 pyinput.c、pyinput.h 和 pymb.h 三个文件,然后在工程里面新建一个

T9INPUT 的组,将 pyinput.c 加入到该组下面。最后,将 T9INPUT 文件夹加入头文件包含路径。

打开 pyinput.c,代码如下:

//拼音输入法pyinput t9={get_pymb,   0,};//比较两个字符串的匹配情况//返回值:0xff,表示完全匹配.// 其他,匹配的字符数u8 str_match(u8*str1,u8*str2){u8 i=0;while(1){if(*str1!=*str2)break; //部分匹配if(*str1=='0'){i=0XFF;break;} //完全匹配i++; str1++; str2++;}return i;//两个字符串相等}//获取匹配的拼音码表//*strin,输入的字符串,形如:"726"//**matchlist,输出的匹配表.//返回值:[7],0,表示完全匹配;1,表示部分匹配(仅在没有完全匹配的时候才会出现)// [6:0],完全匹配的时候,表示完全匹配的拼音个数// 部分匹配的时候,表示有效匹配的位数 u8 get_matched_pymb(u8 *strin,py_index **matchlist){py_index *bestmatch=0;//最佳匹配u16 pyindex_len=0;u16 i=0;u8 temp,mcnt=0,bmcnt=0;bestmatch=(py_index*)&py_index3[0];//默认为 a 的匹配pyindex_len=sizeof(py_index3)/sizeof(py_index3[0]);//得到 py 索引表的大小.for(i=0;ibmcnt)//找最佳匹配{bmcnt=temp; bestmatch=(py_index*)&py_index3[i];//最好的匹配. } }}  if(mcnt==0&&bmcnt)//没有完全匹配的结果,但是有部分匹配的结果{matchlist[0]=bestmatch;mcnt=bmcnt|0X80; //返回部分匹配的有效位数}return mcnt;//返回匹配的个数}//得到拼音码表.//str:输入字符串//返回值:匹配个数.u8 get_pymb(u8* str){return get_matched_pymb(str,t9.pymb);}//串口测试用void test_py(u8 *inputstr){……代码省略}

这里总共就 4 个函数,其中 get_matched_pymb,是核心,该函数实现将用户输入拼音数字

串同拼音索引表里面的各个项对比,找出匹配结果,并将完全匹配的项目存放在 matchlist里面,

同时记录匹配数。对于那些没有完全匹配的输入串,则查找与其最佳匹配的项目,并将匹配的

长度返回。函数 test_py(代码省略)用于给 usmart 调用,实现串口测试,该函数可有可无,只

是在串口测试的时候才用到,如果不使用的话,可以去掉,本章,我们将其加入 usmart 控制,

大家可以通过该函数实现串口调试拼音输入法。

其他两个函数,也比较简单了,我们这里就不细说了。打开 pyinput.h,代码如下:

#ifndef __PYINPUT_H#define __PYINPUT_H#include "sys.h"//拼音码表与拼音的对应表typedef struct{ u8 *py_input;//输入的字符串 u8 *py; //对应的拼音 u8 *pymb; //码表}py_index;#define MAX_MATCH_PYMB 10 //最大匹配数//拼音输入法typedef struct{ u8(*getpymb)(u8 *instr); //字符串到码表获取函数 py_index *pymb[MAX_MATCH_PYMB]; //码表存放位置}pyinput;extern pyinput t9;u8 str_match(u8*str1,u8*str2);u8 get_matched_pymb(u8 *strin,py_index **matchlist);u8 get_pymb(u8* str);void test_py(u8 *inputstr); #endif

pymb.h 里面完全就是我们前面介绍的拼音码表,该文件很大,里面存储了所有我们可以输

入的汉字,此部分代码就不贴出来了,请大家参考光盘本例程的源码。

最后,我们看看主函数代码:

const u8* kbd_tbl[9]={"←","2","3","4","5","6","7","8","9",};//数字表const u8* kbs_tbl[9]={"DEL","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz",};//字符表u16 kbdxsize; //虚拟键盘按键宽度u16 kbdysize; //虚拟键盘按键高度//加载键盘界面//x,y:界面起始坐标void py_load_ui(u16 x,u16 y){……//此处省略部分代码 }//按键状态设置//x,y:键盘坐标//key:键值(0~8)//sta:状态,0,松开;1,按下;void py_key_staset(u16 x,u16 y,u8 keyx,u8 sta){ u16 i=keyx/3,j=keyx%3;if(keyx>8)return;if(sta)LCD_Fill(x+j*kbdxsize+1,y+i*kbdysize+1,x+j*kbdxsize+kbdxsize-1,y+i*kbdysize+kbdysize-1,GREEN);else LCD_Fill(x+j*kbdxsize+1,y+i*kbdysize+1,x+j*kbdxsize+kbdxsize-1,y+i*kbdysize+kbdysize-1,WHITE); Show_Str_Mid(x+j*kbdxsize,y+4+kbdysize*i,(u8*)kbd_tbl[keyx],16,kbdxsize);Show_Str_Mid(x+j*kbdxsize,y+kbdysize/2+kbdysize*i,(u8*)kbs_tbl[keyx],16,kbdxsize);}//得到触摸屏的输入//x,y:键盘坐标//返回值:按键键值(1~9 有效;0,无效)u8 py_get_keynum(u16 x,u16 y){u16 i,j; u8 key=0;static u8 key_x=0;//0,没有任何按键按下;1~9,1~9 号按键按下tp_dev.scan(0); if(tp_dev.sta&TP_PRES_DOWN) //触摸屏被按下  {for(i=0;i<3;i++){for(j=0;j<3;j++){if(tp_dev.x[0](x+j*kbdxsize)&&tp_dev.y[0](y+i*kbdysize)){key=i*3+j+1; break;}}if(key){ if(key_x==key)key=0;else {py_key_staset(x,y,key_x-1,0);key_x=key;py_key_staset(x,y,key_x-1,1);}break;}} }else if(key_x){ py_key_staset(x,y,key_x-1,0); key_x=0;} return key; } //显示结果.//index:0,表示没有一个匹配的结果.清空之前的显示// 其他,索引号void py_show_result(u8 index){LCD_ShowNum(30+144,125,index,1,16); //显示当前的索引LCD_Fill(30+40,125,30+40+48,130+16,WHITE); //清除之前的显示LCD_Fill(30+40,145,lcddev.width,145+48,WHITE); //清除之前的显示 if(index){Show_Str(30+40,125,200,16,t9.pymb[index-1]->py,16,0); //显示拼音Show_Str(30+40,145,lcddev.width-70,48,t9.pymb[index-1]->pymb,16,0);//显示汉字printf(" 拼音:%s",t9.pymb[index-1]->py); //串口输出拼音printf("结果:%s",t9.pymb[index-1]->pymb); //串口输出结果} }int main(void){ u8 i=0,result_num,cur_index,key,inputstr[7];//最大输入 6 个字符+结束符u8 inputlen; //输入长度  Cache_Enable(); //打开 L1-Cache HAL_Init(); //初始化 HAL 库 Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz  delay_init(216); //延时初始化uart_init(115200); //串口初始化usmart_dev.init(108); //初始化 USMART LED_Init(); //初始化 LED KEY_Init(); //初始化按键 SDRAM_Init(); //初始化 SDRAM LCD_Init(); //初始化 LCD W25QXX_Init(); //初始化 W25Q256 tp_dev.init(); //初始化触摸屏 my_mem_init(SRAMIN); //初始化内部内存池 my_mem_init(SRAMEX); //初始化外部 SDRAM 内存池 my_mem_init(SRAMDTCM); //初始化内部 DTCM 内存池 RESTART:POINT_COLOR=RED; while(font_init()) //检查字库{ LCD_ShowString(60,50,200,16,16,"Font Error!");delay_ms(200); LCD_Fill(60,50,240,66,WHITE);//清除显示 } ……//此处省略部分代码if(lcddev.id==0X5310){kbdxsize=86;kbdysize=43;}//根据 LCD 分辨率设置按键大小else if(lcddev.id==0X5510){kbdxsize=140;kbdysize=70;}else {kbdxsize=60;kbdysize=40;}py_load_ui(30,195);memset(inputstr,0,7); //全部清零inputlen=0; //输入长度为 0result_num=0; //总匹配数清零cur_index=0;while(1){i++;delay_ms(10);key=py_get_keynum(30,195);if(key){if(key==1)//删除  {if(inputlen)inputlen--;inputstr[inputlen]='0';//添加结束符}else {inputstr[inputlen]=key+'0';//输入字符if(inputlen<7)inputlen++;}if(inputstr[0]!=NULL){key=t9.getpymb(inputstr); //得到匹配的结果数if(key)//有部分匹配/完全匹配的结果{result_num=key&0X7F; //总匹配结果cur_index=1; //当前为第一个索引if(key&0X80) //是部分匹配{inputlen=key&0X7F; //有效匹配位数inputstr[inputlen]='0';//不匹配的位数去掉if(inputlen>1)result_num=t9.getpymb(inputstr);//重新获取完全匹配字符数} }else //没有任何匹配{ inputlen--;inputstr[inputlen]='0';}}else{cur_index=0;result_num=0;}LCD_Fill(30+40,105,30+40+48,110+16,WHITE); //清除之前的显示LCD_ShowNum(30+144,105,result_num,1,16); //显示匹配的结果数Show_Str(30+40,105,200,16,inputstr,16,0); //显示有效的数字串py_show_result(cur_index); //显示第 cur_index 的匹配结果}key=KEY_Scan(0);if(key==KEY2_PRES&&tp_dev.touchtype==0)//KEY2 按下,且是电阻屏{ tp_dev.adjust();LCD_Clear(WHITE);goto RESTART;  }if(result_num) //存在匹配的结果{switch(key){case WKUP_PRES://上翻if(cur_index1)cur_index--;else cur_index=result_num;py_show_result(cur_index); //显示第 cur_index 的匹配结果break;case KEY0_PRES://清除输入LCD_Fill(30+40,145,lcddev.width-1,145+48,WHITE);//清除之前显示 goto RESTART; } }if(i==30){i=0;LED0_Toggle;} } }

此部分代码除 main 函数外还有 4 个函数。首先,py_load_ui,该函数用于加载输入键盘,

在 LCD 上面显示我们输入拼音数字串的虚拟键盘。py_key_staset,该函数用与设置虚拟键盘某

个按键的状态(按下/松开)。py_get_keynum,该函数用于得到触摸屏当前按下的按键键值,通

过该函数实现拼音数字串的获取。最后,py_show_result,该函数用于显示输入串的匹配结果,

并将结果打印到串口。

在 main 函数里面,实现了我们在 59.2 节所说的功能,这里我们并没有实现汉字选择功能,

但是有本例程作为基础,再实现汉字选择功能就比较简单了,大家自行实现即可。注意:kbdxsize

和 kbdysize 代表虚拟键盘按键宽度和高度,程序根据 LCD 分辨率不同而自动设置这两个参数,

以达到较好的输入效果。

最后,我们将 test_py 函数加入 USMART 控制,以便大家串口调试。

至此,本实验的软件设计部分结束。

59.4 下载验证

在代码编译成功之后,我们下载代码到 ALIENTEK 阿波罗 STM32 开发板上,得到,如图

59.4.1 所示:

86f4605ff309d83c015b42390f5849b7.png

图 59.4.1 汉字输入法界面

此时,我们在虚拟键盘上输入拼音数字串,即可实现拼音输入,如图 59.4.2 所示:

1f1f4827800dc632830b5b5d116c822b.png

图 59.4.2 实现拼音输入

如果发现输入错了,可以通过屏幕上的 DEL 按钮,来退格。如果有多个匹配的情况(匹配

值大于 1),则可以通过 KEY_UP 和 KEY1 来选择拼音。通过按下 KEY0,可以清除当前输入,

通过按下 KEY2,可以实现触摸屏校准(仅限电阻屏,电容屏无需校准)。

我们还可以通过 USMART 调用 test_py 来实现输入法调试,如图 59.4.3 所示:

093aff1f9b4158db9eada894fc3ad34a.png

图 59.4.3 USMART 调试 T9 拼音输入法

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值