你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 3890|回复: 0

【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十二章 T9拼音输入法实验

[复制链接]

24

主题

12

回帖

2

蝴蝶豆

初级会员

最后登录
2020-2-27
发表于 2013-4-16 22:59:33 | 显示全部楼层 |阅读模式

 
<a name="_Toc342394375">52.1 拼音输入法简介  

在计算机上汉字的输入法有很多种,比如拼音输入法、五笔输入法、笔画输入法、区位输入法等。其中,又以拼音输入法用的最多。拼音输入法又可以分为很多类,比如全拼输入、双拼输入等。
而在手机上,用的最多的应该算是T9拼音输入法了,T9输入法全名为智能输入法,字库容量九千多字,支持十多种语言。T9输入法是由美国特捷通讯(Tegic Communications)软件公司开发的,该输入法解决了小型掌上设备的文字输入问题,已经成为全球手机文字输入的标准之一。
一般,手机拼音输入键盘如图52.1.1所示:

图52.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汉字拼音输入法。
<a name="_Toc342394377">52.3 软件设计
打开上一章的工程,首先在HARDWARE文件夹所在的文件夹下新建一个T9INPUT的文件夹。在该文件夹下面新建pyinput.c、pyinput.h和pymb.h三个文件,然后在工程里面新建一个T9INPUT的组,将pyinput.c加入到该组下面。最后,将T9INPUT文件夹加入头文件包含路径。
    打开pyinput.c,在该文件输入如下代码:
#include "sys.h"
#include "usart.h"
#include "pymb.h"
#include "pyinput.h"
#include "string.h"
//拼音输入法
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;//最佳匹配
       u16 pyindex_len; u16 i;
       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;//最好的匹配.
                     }
              }
       }
       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.c,打开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
       保存pyinput.h。pymb.h里面完全就是我们前面介绍的拼音码表,该文件很大,里面存储了所有我们可以输入的汉字,此部分代码就不贴出来了,请大家参考光盘本例程的源码。
       最后,我们打开test.c,输入代码如下:
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",};//字符表
//加载键盘界面
//x,y:界面起始坐标
void py_load_ui(u16 x,u16 y)
{
       u16 i;
       POINT_COLOR=RED;
       LCD_DrawRectangle(x,y,x+180,y+120);                                          
       LCD_DrawRectangle(x+60,y,x+120,y+120);                                            
       LCD_DrawRectangle(x,y+40,x+180,y+80);
       POINT_COLOR=BLUE;
       for(i=0;i8)return;
       if(sta)LCD_Fill(x+j*60+1,y+i*40+1,x+j*60+59,y+i*40+39,GREEN);
       else LCD_Fill(x+j*60+1,y+i*40+1,x+j*60+59,y+i*40+39,WHITE);
       Show_Str_Mid(x+j*60,y+4+40*i,(u8*)kbd_tbl[keyx],16,60);          
       Show_Str_Mid(x+j*60,y+20+40*i,(u8*)kbs_tbl[keyx],16,60);        
}
//得到触摸屏的输入
//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;ipymb,16,0); //显示对应的汉字
              printf("\r\n拼音:%s\r\n",t9.pymb[index-1]->py);       //串口输出拼音
              printf("结果:%s\r\n",t9.pymb[index-1]->pymb); //串口输出结果
       }
}                                                     
int main(void)
{           
      u8 i=0; u8 key; u8 cur_index;                            
       u8 result_num;
       u8 inputstr[7];               //最大输入6个字符+结束符
       u8 inputlen;                  //输入长度         
      Stm32_Clock_Init(9);    //系统时钟设置
       delay_init(72);                     //延时初始化
       uart_init(72,9600);       //串口1初始化      
       LCD_Init();                  //初始化液晶
       LED_Init();           //LED初始化
       KEY_Init();                  //按键初始化 
       TP_Init();                 //触摸屏初始化
       usmart_dev.init(72);      //usmart初始化    
      mem_init(SRAMIN);     //初始化内部内存池    
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);//清除显示          
       }
      Show_Str(60,5,200,16,"战舰 STM32开发板",16,0);                                  
       Show_Str(60,25,200,16,"拼音输入法实验",16,0);                                      
       Show_Str(60,45,200,16,"正点原子@ALIENTEK",16,0);                                                      
       Show_Str(30,65,200,16,"  KEY2:校准  KEY0:清除",16,0);  
      Show_Str(30,85,200,16,"KEY_UP:上翻  KEY1:下翻",16,0); 
       Show_Str(30,105,200,16,"输入:        匹配:  ",16,0);
      Show_Str(30,125,200,16,"拼音:        当前:  ",16,0);
      Show_Str(30,145,210,32,"结果:",16,0);
       py_load_ui(30,195);
       memset(inputstr,0,7);     //全部清零
       inputlen=0; result_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(inputlen1)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的匹配结果
              }    
              if(result_num) //存在匹配的结果 
              {      
                     key=KEY_Scan(0);
                     switch(key)
                     {
                            case KEY_UP://上翻
                                   if(cur_index1)cur_index--;
                                   else cur_index=result_num;
                                   py_show_result(cur_index);   //显示第cur_index的匹配结果
                                   break;
                            case KEY_RIGHT://清除输入
                                  LCD_Fill(30+40,145,30+200,145+48,WHITE);  //清除之前的显示   
                                   goto RESTART;                           
                            case KEY_LEFT://重新校准
                                   tp_dev.adjust();
                                   LCD_Clear(WHITE);
                                   goto RESTART;                           
                     }           
              }
              if(i==30) {i=0; LED0=!LED0;}  
       }                                                                                                     
}
此部分代码除main函数外还有4个函数。首先,py_load_ui,该函数用于加载输入键盘,在LCD上面显示我们输入拼音数字串的虚拟键盘。py_key_staset,该函数用与设置虚拟键盘某个按键的状态(按下/松开)。py_get_keynum,该函数用于得到触摸屏当前按下的按键键值,通过该函数实现拼音数字串的获取。最后,py_show_result,该函数用于显示输入串的匹配结果,并将结果打印到串口。
在main函数里面,实现了我们在52.2节所说的功能,这里我们并没有实现汉字选择功能,但是有本例程作为基础,再实现汉字选择功能就比较简单了,大家自行实现即可。
最后,我们将test_py函数加入USMART控制,以便大家串口调试。
至此,本实验的软件设计部分结束。
52.4 下载验证
在代码编译成功之后,我们下载代码到ALIENTEK战舰STM32开发板上,得到,如图52.4.1所示:

图52.4.1 汉字输入法界面此时,我们在虚拟键盘上输入拼音数字串,即可实现拼音输入,如图52.4.2所示:

图52.4.2 实现拼音输入如果发现输入错了,可以通过屏幕上的DEL按钮,来退格。如果有多个匹配的情况(匹配值大于1),则可以通过WK_UP和KEY1来选择拼音。通过按下KEY0,可以清楚当前输入,通过按下KEY2,可以实现触摸屏校准。
 我们还可以通过USMART调用test_py来实现输入法调试,如图52.4.3所示:

图52.4.3 USMART调试T9拼音输入法 

《STM32开发指南》第五十二章 T9拼音输入法实验.rar

下载

676.14 KB, 下载次数: 84, 下载积分: ST金币 -1

实验47 拼音输入法实验.rar

下载

991.88 KB, 下载次数: 80, 下载积分: ST金币 -1

回复

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版