语音控制小车
——音控三级调速
文摘 本文主要介绍了凌阳单片机SPCE
关键词 SPCE
自单片机出现至今,单片机技术已走过了近20年的发展路程。纵观20年来单片机发展里程可以看出,单片机技术的发展以微处理器(MPU)技术及超大规模集成电路技术的发展为先导,以广泛的应用领域拉动,表现出较微处理器更具个性的发展趋势。
现在可以说单片机是百花齐放,百家争鸣的时期,世界上各大芯片制造公司都推出了自己的单片机,从8位、16位到32位,数不胜数,应有尽有,有与主流C51系列兼容的,也有不兼容的,但它们各具特色,互成互补,为单片机的应用提供广阔的天地。
纵观单片机的发展过程,可以预示单片机的发展趋势,大致有:低功耗CMOS化、微型单片化、主流与多品种共存。
单片机的种类繁多,目前常用的系列有:MOTOROLA单片机、Microchip单片机、Scenix单片机、NEC单片机、东芝单片机、富士通单片机、8051单片机、Epson单片机、Zilog单片机、NS单片机、三星单片机、华邦单片机等。由于单片机的开发手段目前仍以仿真器为主,公司能否提供廉价的仿真器,提供方便的技术服务与培训,较之能否提供高性能、低价位的单片机有着同等重要性。由于单片机对各行各业都有用,这种电子技术的进步导致各行各业的进步,也带动了人类文明的进步。凌阳公司推出的SPCE
本设计需要达到的目的是语音控制小车的启动、停止、返回,可进行前行和倒退,三级调速,自动记录行驶往返距离,在整个行程中如果遇到障碍物小车能自动绕开障碍物而继续前行。
1 方案设计与论证
本系统为典型的实时控制系统,易用单片机控制来实现,这里以凌阳SPCE
方案一:采用凌阳SPCE
方案二:此方案也采用凌阳SPCE
方案三:此方案也采用凌阳SPCE
各自的优缺点:
方案一:凌阳SPCE
方案二:由于小车采用的是双驱动,每侧的轮子均为连动的。小车的速度控制通过按键(KEY1、KEY2、KEY3)进行控制。单片机上的(KEY1、KEY2、KEY3)键较小,所以在运动的小车上按键控制速度不能达到理想的效果,但控制相对简单。
方案三:SPCE
这里考虑到大众化设计及小车的易控性,采用第一个方案。以下均根据方案一进行设计。
2 SPCEO
随着单片机功能集成化的发展,其应用领域也逐渐地由传统的控制,扩展为控制处理、数据处理以及数字信号处理(DSP,Digital Signal Processing)等领域。凌阳的16位单片机就是为适应这种发展而设计的。它的CPU内核采用凌阳最新推出的μ’nSP™(Microcontroller and Signal Processor)16位微处理器芯片(以下简称μ’nSP™)。围绕μ’nSP™所形成的16位μ’nSP™系列单片机(以下简称μ’nSP™家族)采用的是模块式集成结构,它以μ’nSP™内核为中心集成不同规模的ROM、RAM和功能丰富的各种外设接口部件,如1图所示。
μ’nSP™内核是一个通用的核结构。除此之外的其它功能模块均为可选结构,亦即这种结构可大可小或可有可无。借助这种通用结构附加可选结构的积木式的构成,便可形成各种不同系列派生产品,以适合不同的应用场合。这样做无疑会使每一种派生产品具有更强的功能和更低的成本。
μ’nSP™家族有以下特点:
⑴ 体积小、集成度高、可靠性好且易于扩展
μ’nSP™家族把各功能部件模块化地集成在一个芯片里,内部采用总线结构,因而减少了各功能部件之间的连线,提高了其可靠性和抗干扰能力。另外,模块化的结构易于系统扩展,以适应不同用户的需求。
⑵ 具有较强的中断处理能力
μ’nSP™家族的中断系统支持10个中断向量及10余个中断源,适合实时应用领域。
图 1 μ’nSP™家族的模块式结构
⑶ 高性能价格比
μ’nSP™家族片内带有高寻址能力的ROM、静态RAM和多功能的I/O口。另外,μ’nSP™的指令系统提供具有较高运算速度的16位×16位的乘法运算指令和内积运算指令,为其应用增添了DSP功能,使得μ’nSP™家族运用在复杂的数字信号处理方面既很便利,又比专用的DSP芯片廉价。
⑷ 功能强、效率高的指令系统
μ’nSP™指令系统的指令格式紧凑,执行迅速,并且其指令结构提供了对高级语言的支持,这可以大大缩短产品的开发时间。
⑸ 低功耗、低电压
μ’nSP™家族采用CMOS制造工艺,同时增加了软件激发的弱振方式、空闲方式和掉电方式,极大地降低了其功耗。
另外,μ’nSP™家族的工作电压范围大,能在低电压供电时正常工作,且能用电池供电。这对于其在野外作业等领域中的应用具有特殊的意义。
3 SPCE
3.1 总述
SPCE
3.2 性能
16位μ’nSP微处理器;
工作电压:VDD为2.4~3.6V(cpu), VDDH为2.4~5.5V(I/O);
CPU时钟: 32768Hz~49.152MHz ;
内置2K字SRAM、内置32K FLASH;
可编程音频处理;
32位通用可编程输入/输出端口;
32768Hz实时时钟,锁相环PLL振荡器提供系统时钟信号;
2个16位可编程定时器/计数器(可自动预置初始计数值);
2个10位DAC(数-模转换)输出通道;
7通道10位电压模-数转换器(ADC)和单通道语音模-数转换器;
声音模-数转换器输入通道内置麦克风放大器自动增益控制(AGC)功能;
系统处于备用状态下(时钟处于停止状态)耗电小于2μA@3.6V;
14个中断源:定时器A / B,2个外部时钟源输入,时基,键唤醒等;
具备触键唤醒的功能;
使用凌阳音频编码SACM_S240方式(2.4K位/秒),能容纳210秒的语音数据;
具备异步、同步串行设备接口;
具有低电压复位(LVR)功能和低电压监测(LVD)功能;
内置在线仿真电路接口ICE(In- Circuit Emulator);
具有保密能力;
具有WatchDog功能(由具体型号决定)。
3.3 结构概览
SPCE
图2包括单片机的各个部分,16位微控制器+ICE、FLASH、RAM、锁相环震荡器、CPU时钟实时时钟、低电压监测/低电压复位、双16位定时器/计数器、时基、中断控制、7通道10位DAC、单通道ADC+AGC、双通道10位DAC、串行输入输出接口、32管脚通道输入输出端口。其中32管脚通道输入输出端口包括A口(A0~A15)和B口(B0~B15),当端口处于不同的状态时,作用也不相同,共32口可以满足我们不同的需求,两个口的每一位都可通过编程单独定义成输入或输出口。
A口的IOA0~IOA7具有特殊的功能,当它用作输入口时具有唤醒功能。详细介绍见后面。
μ’nSP™的内核由总线、算术逻辑运算单元、寄存器组(通用型寄存器R1~R4、堆栈指针寄存器SP、基址指针寄存器BP、段寄存器SR程序计数器PC)、中断系统及堆栈等部分组成。
图 2 SPCE
3.4 应用领域
嵌入式计算机系统(ECS,Embedded Computer System)是指专门用于某一应用系统或设备并隐藏于其中的起关键支配作用的计算机应用系统。ECS与通用计算机系统相比有以下一些特征:专用性、可封装性、外来性、实时性及可靠性。所谓外来性一般是指ECS自成一个子系统,与目标系统的其它子系统保持一定的独立性。
在不同的应用领域中对ECS有各自特殊的要求。例如:
(1) 小型应用系统,一般不需大量的数据处理,只需较强的实时控制功能,且要求体积小、功耗低等。这类系统如计算机智能化仪表、家电产品的自动控制等。
(2) 简单的工业控制系统,要求有相当强的实时数据处理能力和控制能力。如步进电机的驱动控制、数据采集、智能测量、汽车工业等。
(3) 比较复杂的系统中若采用分布式多机系统,在某些节点要配置智能I/O处理机对现场信息进行实时测量和控制。由于现场情况复杂,环境恶劣,故要求高可靠性和抗干扰能力等。如航空航天、尖端武器以及机器人系统等。
对于上述应用领域,第一类通常用8位机,如凌阳公司的SPL系列微处理器即可满足要求。而对于第二类则用具有定点DSP运算功能的µ’nSP™系列的16位微处理器实现较为合适。至于第三类则可根据需要选用若干个8位机或若干个8位机与µ’nSP™系列的16位机组合形成分布式多机系统。
有语音功能的仪器仪表;
语音功能的家电产品;
有语音功能的自动售货机;
智能语音交互式玩具;
高级亦教亦乐类玩具;
儿童电子故事书类产品;
通用语音合成器类产品;
需较长语音持续时间类产品。
4 SPCE
从SPCE
4.1 SPCE
SPCE
SPCE
堆栈是在内存RAM区专门开辟出来的按照“先进后出”原则进行数据存取的一种工作方式如图4,主要用于子程序调用及返回和中断处理断点的保护及返回。堆栈的最大容量范围限制在2K字RAM内,即其地址范围从0X07FF到0X0000的存储器范围中。值得注意的是堆栈的生长方向,SPCE
2K RSAM 保留空间 I/O端口 系统端口 32K FLASH ROM 中断向量 0X0000 0X07FF 0X0800 0X6FFF 0X7000 0X7FFF 0X8000 0XFFF5 0XFFF6 0XFFFF
图 3 SPCE061内存映射表
栈底 栈顶 PUSH后SP减1 POP后SP加1 0X07FF 0X0000 堆栈伸长方向
图 4 堆栈
SPCE
用户必须通过向P_Flash_Ctrl (写) ($7555H)单元写入0xAAAA,来激活闪存的存取功能,从而访问闪存。然后,向P_Flash_Ctrl (写) ($7555H)单元写入0x5511,来擦除页的内容。写入0x5533,对闪存编程。这些指令不能被任何其他的操作包括中断、ICE的单步跟踪动作打断。这是因为闪存控制器必须保证闪存处于编程状态。如果一些其它的进程插入到当前的执行队列里,闪存的状态将发生改变,擦除页和编程的操作不能再继续进行。
此外,为保证程序的正确编写,用户必须在编程之前擦除页的内容。页大小为0x100。第一页地址范围:0x8000~0x80FF,最后一页的地址范围:0xFF00~0xFFFF。0xFC00~0xFFFF范围内的地址由系统保留,用户最好不要用本范围内的地址。
32K字的内嵌式闪存被划分为128个页(每个页存储容量为256个字),它们在CPU正常运行状态下均可通过程序擦除或写入。全部32K字闪存均可在ICE工作方式下被编程写入或被擦除。
4.2 SPCE
输入/输出接口(也可简称为I/O口)是单片机与外设交换信息的通道。输入端口负责从外界接收检测信号、键盘信号等各种开关量信号。输出端口负责向外界输送由内部电路产生的处理结果、显示信息、控制命令、驱动信号等。μ’nSP™内有并行和串行两种方式的I/O口。并行口线路成本较高,但是传输速率也很高;与并行口相比,串行口的传输速率较低但可以节省大量的线路成本。SPCE
A口的IOA0~IOA7用作输入口时具有唤醒功能,即具有输入电平变化引起CPU中断功能。在那些用电池供电、追求低能耗的应用场合,可以应用CPU的睡眠模式(通过软件设置)以降低功耗,需要时以按键来唤醒CPU,使其进入工作状态。例如:手持遥控器、电子字典、PDA、计算器、移动电话等。
表1 I/O端口的组合控制设置
Direction |
Attribution |
Data |
功能 |
是否带唤醒功能 |
功能描述 |
0 |
0 |
0 |
下拉* |
是** |
带下拉电阻的输入管脚 |
0 |
0 |
1 |
上拉 |
是** |
带上拉电阻的输入管脚 |
0 |
1 |
0 |
悬浮 |
是** |
悬浮式输入管脚 |
0 |
1 |
1 |
悬浮 |
否 |
悬浮式输入管脚** |
1 |
0 |
0 |
高电平输出 (带数据反相器) |
否 |
带数据反相器的高电平输出 (向数据位写入0时输出1) |
1 |
0 |
1 |
低电平输出 (带数据反相器) |
否 |
带数据反相器的低电平输出 (向数据位写入1时输出0) |
1 |
1 |
0 |
低电平输出 |
否 |
带数据缓存器的低电平输出 (无数据反相功能) |
|
1 |
1 |
高电平输出 |
否 |
带数据缓存器的高电平输出 (无数据反相功能) |
SPCE
A口和B口的Data、Attribution和Direction的设定值均在不同的寄存器里,用户在进行I/O口设置时要特别注意这一点。I/O端口的组合控制设置如表1所示.
注:
口位默认为带下拉电阻的输入管脚;只有当IOA[7~0]内为的控制字为000,001和010时,相应为在具有唤醒的功能;此种悬浮输入作为ADC IOA[6~0]。
P_IOA/B_Buffer(读) P_IOA/B_Data(写) 数据寄存器 和 控制逻辑 P_IOA/B_Buffer(写) P_IOA/B_Dir(读/写) P_IOA/B_Attrib(读/写) P_IOA/B_Data(读)
图 5 I/O结构
⑴ P_IOA_Data(读/写)(7000H)
A口的数据单元,用于向A口写入或从A口读出数据。当A口处于输入状态时,读出是读A口管脚电平状态;写入是将数据写入A口的数据寄存器。当A口处于输出状态时,写入输出数据到A口的数据寄存器。
⑵ P_IOA_Buffer (读/写) (7001H)
A口的数据向量单元,用于向数据向量寄存器写入或从该寄存器读出数据。当A口处于输入状态时,写入是将A口的数据向量写入A口的数据寄存器;读出则是从A口数据寄存器内读其数值。当A口处于输出状态时,写入输出数据到A口的数据寄存器。
对输出而言,P_IOA_Data与P_IOA_Buffer是一样的.但对输入而言,P_IOA_Data读的是IO的值,P_IOA_Buffer读的是buffer内的值。假设IOA[0]作为输出,并去接LED阳极(LED阴极接地)。若P_IOA_Data的IOA[0]为1。在某些需要较大驱动能力的LED而言,LED会亮,但IOA[0]会被拉到一个很低的值。此时从P_IOA_Data读回为0,但P_IOA_Buffer则为1。至于读回的意义是做什么,是方便做其它的IO运算。
⑶ P_IOA_Dir(读/写)(7002H)
A口的方向向量单元,用于用来设置A口是输入还是输出,该方向控制向量寄存器可以写入或从该寄存器内读出方向控制向量。Dir位决定了口位的输入/输出方向:即‘
⑷ P_IOA_Attrib(读/写)(7003H)
A口的属性向量单元,用于A口属性向量的设置。
⑸ P_IOA_Latch(读)(7004H)
读该单元以锁存A口上的输入数据,用于进入睡眠状态前的触键唤醒功能的启动
并行I/O口的组合控制
方向向量_Dir、属性向量_Attrib和数据向量_Data分别代表三个控制口。这三个口中每个对应的位组合在一起,形成一个控制字,来定义相应I/O口位的输入/输出状态和方式。
表1具体表示了如何通过对I/O口位的方向向量位_Dir、属性向量位_Attrib以及数据向量位_Data进行编程,来设定口位的输入/输出状态和方式。
由表1可以得出以下一些结论:
_Dir位决定了口位的输入/输出方向:即‘
_Attrib位决定了在口位的输入状态下是为悬浮式输入还是非悬浮式输入:即‘
_Data位在口位的输入状态下被写入时,与_Attrib位组合在一起形成输入方式的控制字‘
例如,假设要把A口的B0定义成下拉电阻式的输入口,则A口_Dir、_Attrib和_Data向量的三个相应的B0应组合设为‘000’。如果想把A口的B1定义成悬浮式并具有唤醒功能的输入口,只需将_Dir、_Attrib和_Data向量中相应的B1组合设置为‘010’即可。
A口的IOA0~IOA7作为唤醒源,常用于键盘输入。要激活IOA0~IOA7的唤醒功能,必须读P_IOA_Latch单元,以此来锁存IOA0~IOA7管脚上的键状态。随后,系统才可通过指令进入低功耗的睡眠状态。当有键按下时,IOA0~IOA7的输入状态将不同于其在进入睡眠前被锁存时的状态,从而引起系统的唤醒。
⑹ P_IOB_Data(读/写)(7005H)
B口的数据单元,用于向B口写入或从B口读出数据。当B口处于输入状态时,读出是读B口管脚电平状态;写入是将数据写入B口的数据寄存器。当B口处于输出状态时,写入输出数据到B口的数据寄存器。
⑺ P_IOB_Buffer(读/写)(7006H)
B口的数据向量单元,用于向数据寄存器写入或从该寄存器内读出数据。当B口处于输入状态时,写入是将数据写入B口的数据寄存器;读出则是从B口数据寄存器里读其数值。当B口处于输出状态时,写入数据到B口的数据寄存器。
⑻ P_IOB_Dir(读/写)(7007H)
B口的方向向量单元,用于设置IOB口的状态。‘
⑼ P_IOB_Attrib(读/写)(7008H)
B口的属性向量单元,用于设置IOB口的属性。
⑽ P_FeedBack(写)(7009H)
B口工作方式的控制单元,用于控制B口的IOB2 (IOB3)和IOB4 (IOB5)用作普通I/O口,或作为特殊功能口。其特殊功能包括以下两个部分:① 单个IOB2或IOB3口可设置为外部中断的输入口。②设置P_FeedBack单元, 再将IOB2(IOB3)和IOB4(IOB5)之间连接一个电阻和电容形成反馈电路以产生振荡信号,此信号可作为外部中断源输入EXT1或EXT2。当然此时所得到的中断频率与RC振荡器的频率是一致的。由于该频率较高,所以通常情况下都是通过(1)获得外部中断信号。此特殊功能仅运用于:当外部电路需要用到一定频率的振荡信号时,可以在IOB2(IOB3)端获得。
IOB8和IOB10的控制向量由TAON、TXPinEn设置;
IOB8和IOB10的应用由控制向量TAON和TXPinEn来控制。
5 硬件电路设计
5.1电子设计基本知识
英文是diode。二极管的正.负二个端子,(如图6)正端A称为阳极,负端K 称为阴极。电流只能从阳极向阴极方向移动。一些初学者容易产生这样一种错误认识:“半导体的一‘半’是一半的‘半’;面二极管也是只有一‘半’电流流动(这是错误的),所有二极管就是半导体 ”。其实二极管与半导体是完全不同的东西。我们只能说二极管是由半导体组成的器件。半导体无论那个方向都能流动电流。
图 6 二极管示意图
电阻在电路中用“R”加数字表示,如:R1表示编号为1的电阻。电阻在电路中的主要作用为
分流、限流、分压、偏置等。
⑴ 参数识别:电阻的单位为欧姆(Ω),倍率单位有:千欧(KΩ),兆欧(MΩ)等。
换算方法是:1兆欧=1000千欧=1000000欧
电阻的参数标注方法有3种,即直标法、色标法和数标法。
a、数标法主要用于贴片等小体积的电路,如:
472 表示 47×100Ω(即4.7K); 104则表示100K
b、色环标注法使用最多,现举例如下:
四色环电阻 五色环电阻(精密电阻)
⑵ 电阻的色标位置和倍率关系如下表2所示:
表2 电阻的色标位置和倍率关系表
颜色 |
有效数字 |
倍率 |
允许偏差(%) |
银色 |
/ |
x0.01 |
±10 |
金色 |
/ |
x0.1 |
±5 |
黑色 |
0 |
+0 |
/ |
棕色 |
1 |
x10 |
±1 |
红色 |
2 |
x100 |
±2 |
橙色 |
3 |
x1000 |
/ |
黄色 |
4 |
x10000 |
/ |
绿色 |
5 |
x100000 |
±0.5 |
蓝色 |
6 |
x1000000 |
±0.2 |
紫色 |
7 |
x10000000 |
±0.1 |
灰色 |
8 |
x100000000 |
/ |
白色 |
9 |
x1000000000 |
/ |
⑴ 已知型号和管脚排列的三极管,可按下述方法来判断其性能好坏
①?测量极间电阻。将万用表置于R×100或R×1k挡,按照红、黑表笔的六种不同接法进行测试。其中,发射结和集电结的正向电阻值比较低,其他四种接法测得的电阻值都很高,约为几百千欧至无穷大。但不管是低阻还是高阻,硅材料三极管的极间电阻要比锗材料三极管的极间电阻大得多。
②?三极管的穿透电流ICEO的数值近似等于管子的倍数β和集电结的反向电流ICBO的乘积。ICBO随着环境温度的升高而增长很快,ICBO的增加必然造成ICEO的增大。而ICEO的增大将直接影响管子工作的稳定性,所以在使用中应尽量选用ICEO小的管子。
通过用万用表电阻直接测量三极管e-c极之间的电阻方法,可间接估计ICEO的大小,具体方法如下:
万用表电阻的量程一般选用R×100或R×1k挡,对于PNP管,黑表管接e极,红表笔接c极,对于NPN型三极管,黑表笔接c极,红表笔接e极。要求测得的电阻越大越好。e-c间的阻值越大,说明管子的ICEO越小;反之,所测阻值越小,说明被测管的ICEO越大。一般说来,中、小功率硅管、锗材料低频管,其阻值应分别在几百千欧、几十千欧及十几千欧以上,如果阻值很小或测试时万用表指针来回晃动,则表明ICEO很大,管子的性能不稳定。
③ 测量放大能力(β)。目前有些型号的万用表具有测量三极管hFE的刻度线及其测试插座,可以很方便地测量三极管的放大倍数。先将万用表功能开关拨至?挡,量程开关拨到ADJ位置,把红、黑表笔短接,调整调零旋钮,使万用表指针指示为零,然后将量程开关拨到hFE位置,并使两短接的表笔分开,把被测三极管插入测试插座,即可从hFE刻度线上读出管子的放大倍数。
另外:有此型号的中、小功率三极管,生产厂家直接在其管壳顶部标示出不同色点来表明管子的放大倍数β值,其颜色和β值的对应关系如表所示,但要注意,各厂家所用色标并不一定完全相同。
①判定基极。用万用表R×100或R×1k挡测量三极管三个电极中每两个极之间的正、反向电阻值。当用第一根表笔接某一电极,而第二表笔先后接触另外两个电极均测得低阻值时,则第一根表笔所接的那个电极即为基极b。这时,要注意万用表表笔的极性,如果红表笔接的是基极b。黑表笔分别接在其他两极时,测得的阻值都较小,则可判定被测三极管为PNP型管;如果黑表笔接的是基极b,红表笔分别接触其他两极时,测得的阻值较小,则被测三极管为NPN型管。
②判定集电极c和发射极e。(以PNP为例)将万用表置于R×100或R×1k挡,红表笔基极b,用黑表笔分别接触另外两个管脚时,所测得的两个电阻值会是一个大一些,一个小一些。在阻值小的一次测量中,黑表笔所接管脚为集电极;在阻值较大的一次测量中,黑表笔所接管脚为发射极。
⑶ 判别高频管与低频管
高频管的截止频率大于3MHz,而低频管的截止频率则小于3MHz,一般情况下,二者是不能互换的。
⑷ 在路电压检测判断法
在实际应用中、小功率三极管多直接焊接在印刷电路板上,由于元件的安装密度大,拆卸比较麻烦,所以在检测时常常通过用万用表直流电压挡,去测量被测三极管各引脚的电压值,来推断其工作是否正常,进而判断其好坏。
5.2 电路方框图及说明
右 凌阳 SPCEA061 单片机 左 中 LED显示电路 光电检测障碍物 光电检测障碍物 霍尔元件检测轮子转数用来计算速度 音频放大电路语音输 出 主控电路正反向和加减速控制电路 无线接收模块 MIC N MIC P
图 7 电路方框图
系统原理框图如图7所示。主控元件采用凌阳SPCE
5.3 各部分电路设计
在当今信息化时代发展过程中,各种信息的感知、采集、转换、传输和处理的功能器件-传感器,已经成为各个应用领域,特别是自动检测、自动控制系统中不可缺少的重要技术工具。
传感器是信息采集系统的首要部件,是实现现代化测量和自动控制(包括遥感、遥测、遥控)的主要环节,是现代信息产业的源头,又是信息社会赖以存在和发展的物质基础与技术基础。
⑵ 传感器的定义
传感器(Transducer或sensor)有时亦被称为换能器、变换器、变送器或探测器。主要特征是能感知和检测某一形态的信息,并将其转换成另一形态信息。因此传感器是指那些对被测对象的某一确定的信息具有感受(或响应)与检出功能,并使之按照一定规律转换成与之对应的有用输出信号的元器件或装置。
传感器一般是利用物理、化学和生物等学科的某些效应或机理按照一定的工艺和结构研制出来的。因此,传感器的主成的细节有较大差异,但是,总的来说,传感器应由敏感元件、转换元件和其他辅助部件主成,如图8所示。敏感元件是指传感器中能直接感受(或响应)与检出被测对象的待测信息(非电量)的部分,转换元件是指传感器中能将错误的、链接无效的信息直接转换成电信号的部分。
图 8 传感器组成框图
⑶ 传感器分类
传感器是一门知识密集型技术,传感器的原理各种各样,它与许多学科有关,种类繁多,分类方法也很多,目前广泛采用的分类方法有如下几种。(1)按照传感器的工作原理,可分为物理型、化学型、生物型等。(2)按构成原理,可分为结构型和物性型传感器两大类,结构型传感器是利用物理学中场的定律构成的,包括力场的运动定律,电磁场的电磁定律等,这类传感器的特点是传感器的性能与它的结构材料没有多大关系,如差动变压器。物性型传感器是利用物质定律构成的,如欧姆定律等,物性型传感器的性能随材料的不同而异,如光电管、半导体传感器等。(3)按传感器的能量转换情况,可分为能量控制传感器和能量转换传感器。能量控制传感器在信息变换过程中,其能量需外电源供给,如电阻、电感、电容等电路参量传感器都属于这一类传感器;能量转换型传感器主要是由能量变换元件构成,它不需要外电源,如基于压电效应、热电效应、光电效应、霍尔效应等原理构成的传感器属于此类传感器。(4)按照物理原理分类,可分为电参量式传感器(电阻式、电感式、电容式)、磁电传感器(磁电感应式、霍尔式、磁栅式)、压电式传感器、光电式传感器、气电式传感器、波式传感器(超声波式、微波式)、射线式传感器、半导体传感器、其他原理的传感器(振弦式、振筒式传感器)。(5)按照传感器的使用方法分类,可分为位移传感器、压力传感器、振动传感器、温度传感器等。
⑷ 光电传感器及应用
光电检测器是以光电器件为检测元件的传感器,它先将被测非电量转换成光量的变化,然后通过充电器件将相应的光量转换成电量。它是一种将光量的变化转换为电量变化的传感器。它的物理基础就是光电效应。光电效应分为外光电效应和内光电效应。
光电检测器的工作原理:当外加电压一定时,当电流的大小和入射光的强度成正比例,这样光电检测器能把强弱变换的光转换成强弱变换的电流。在本系统中,为了确定障碍物,加入障碍物检测的光电传感器,根据小车所处的位置改变行驶状态,所使用的光电传感器为市场上普通的光电传感器,在没检测到障碍物时Uo输出为低电平,在检测到障碍物时Uo将与传感器内部电路断开,因而加一个上拉电阻,此时将输出高电平。在检测障碍物的过程中采用查询方式(即随着小车的运行轨迹,光电传感器便检测小车前方有无障碍物,直到检测到障碍物时就发出指令,使小车避开障碍物,随后继续检测直到小车停止)。如图9所示
图 9 光电检测器接图
在小车的左、中、右各自安装一个光电检测器,当发现有障碍物时,输出高电平,控制小车进行转向而绕开障碍物,具体控制程序可以用下图10来描述:
⑸ 霍尔传感器及应用
霍尔传感器是利用霍尔效应实现磁电转换的一种传感器,它具有灵敏度高、线形度好、稳定性高、体积小和耐高温等特性,它已经广泛应用于非电量测量、自动控制、计算机装置和现代军事技术等各个领域。
霍尔效应是半导体中自由电荷受磁场中洛仑兹力作用而产生的。
设霍尔元件为N型半导体,当它通以电流I时,半导体中的自由电荷即载流子受到磁场中洛仑兹力
式中v为电子速度,B为垂直于霍尔元件表面的磁感应强度。使电子向垂直于B和自由电子运动方向偏移,其方向符合右手螺旋定律,即电子有向某一端积聚的显现,使半导体一端面产生负电荷积聚,另一端面则为正电荷积聚。由于电荷积聚,产生静电场,即为霍尔电场。该静电场对电子的作用力
式中
⑹ 红外探测器
红外探测器是红外检测系统中最重要的器件之一,按工作原理可分为“热探测器”和“光子探测器”两类。
① 热探测器
热探测器在吸收红外辐射能后温度升高,引起某种物理性质的变化,这种变换与吸收的红外辐射能成一定的关系。常用的物理现象有温差热电现象、金属或半导体电阻阻值变化现象、热湿电现象、气体压强变化现象、金属热膨胀现象、液体薄膜蒸发现象。因此只要检测出上述变化,即可确定被吸收的收红外辐射能大小,从而得到被测非电量值。热电探测器主要有热敏电阻型、热电偶型、高莱气动型和热湿电型。
热湿电型探测器:热湿电型探测器是一种具有极化现象的热晶体或称“铁电体”。铁电体的极化强度(单位面积上的电荷)与温度有关。当红外辐射照射到已经极化的铁电体薄片表面上时,引起薄片温度升高,使其极化强度降底,表面电荷减少,这相当于释放一部分电荷,所以叫热湿电型探测器。
② 光子探测器
光子探测器是利用某些半导体材料在入射光的照射下,产生光子效应,使材料电学性质发生变化。通过对电学性质变化的探测,可以了解红外辐射的强弱。利用光子效应所制成的红外探测器,统称光子探测器。其主要特点是灵敏度高,响应速度快,具有较高的响应频率。但它一般需在底温下工作,探测波段较窄。按照光子探测器的工作原理,一般可分为内光探测器和外光探测器两种,前者又分为光电导探测器、光电伏特器和光磁电探测器三种。在障碍物的探测也可运用红外探测器,本论文采用光电传感器
开始 初始设置 无限循环 传感器显示 是否停止 左传感器检测到 中传感器检测到 右传感器检测到 左转 右前进 右转 Y Y Y Y
图 10 小车控制转向示意图
由于单片机I/O口提供的电流太小,不能直接驱动继电器。在这里采用8050来提供一个开关电压,实现I/O口对继电器的驱动,用IN4007去掉继电器断开时线圈产生的反向电流,保护8050,如图11。
8050NPN 控制信号
图 11 驱动电路的设计
轮驱移动小车是移动机器人的一种,对于此类移动机器人的控制方式有两种:一种是通过控制小车前轮的速度和方向来控制其运动的速度和方向;另一种是通过控制后两个轮子的转速(及转速比)来控制小车的运动速度和方向,由于我们所用小车为双驱动(左驱动和右驱动)。可以对两个驱动分别进行控制,整个小车的行使状态由两个电机控制,每一个电机控制一边的两个轮子,要转弯时控制一个电机正转一个电机反转的即可。电机连接及控制端口如图12。
如图13所示为行使状态控制电路,整个小车的行驶状态由两个电机来控制,MOTOR B控制前进和倒退以及三档速度,MOTOR A控制前进、倒退以及三挡速度,MOTOR A和MOTOR B共同控制小车的左右转向。具体控制如表4所示。
图 12 电机连接及控制端口
图13 行使状态控制电路
注:图中的两个电机的应用完全相同,这样能更好地保持小车的稳定性,在前进上两个电机能在加减速度上完全达到同步,不会走S路线,如果考虑用一个电机控制转向,而另外一个控制加减速度和返回的话,由于控制转向的电机电路未接入分压电阻,而另外一个则速度上三级可调,当速度不处于最快速度时,小车前进不能走直线,而是向一边偏,导致路线不对。
表3 小车控制状态表
行驶状态 |
IOB08 |
IOB09 |
IOB10 |
IOB11 |
IOB12 |
IOB13 |
IOB14 |
全速前进 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
中速前进 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
慢速前进 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
左拐 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
右拐 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
全速倒退 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
中速倒退 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
慢速倒退 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
在我们生活中有一种普通防盗的设备,此设备的原理是在一方安装激光信号发送器,另一方安装激光信号接收器。正常情况下,一束看不见激光与发送器和接收器两点之间,如果有人或物挡住了这样一束激光。信号端产生一个计量脉冲。接收信号中断,进入报警状态。而此设计所用到的是当接收信号中断时,进入计程状态和计时状态。
光电传感器是安装在小车的左、中、右边的,为了控制容易实现,将它们分别接在IOB04、IOB05、IOB06上,由于传感器在此使用相当于小车的眼睛,遇到障碍物输出高电平返回到控制电路上,由控制程序作出相应的命令,让小车避开障碍物能正确的行驶。可定义小车在传感器返回相应信号对应作出的命令及端口号如下表4所示:
表4 传感器返回相应信号对应作出的命令及端口号表
|
IOB04 |
IOB05 |
IOB06 |
IOB07(接地) |
描述 |
作出命令 |
状态1 |
0 |
0 |
1 |
0 |
右障碍 |
左拐 |
状态2 |
0 |
1 |
0 |
0 |
中间小障碍 |
后退、右拐 |
状态3 |
0 |
1 |
1 |
0 |
中右均有障碍 |
后退、左拐 |
状态4 |
1 |
0 |
0 |
0 |
左障碍 |
右拐 |
状态5 |
1 |
0 |
1 |
0 |
夹缝,不能过车 |
后退、右拐 |
状态6 |
1 |
1 |
0 |
0 |
左中障碍 |
右拐 |
状态7 |
1 |
1 |
1 |
0 |
前面全挡住 |
后退 |
以上的定义将用于程序中,对应的控制状态也将由传感器返回的组合状态,具体程序控制部分见后面。
(1) 车轮的测量
方法一:在车轮的轮面上任意选择一点,在轮上点上很少的一滴墨水,把小车放到一张白纸上,推动小车正向前进一小段,测量白纸上留下的比较清晰的两点间的距离即车轮的周长。
方法二:用直尺直截测量小车的直径为
(2) 计程设计
通过检测车轮转过的转数乘上车轮的周长来计算路程,霍尔元件就是一种很好的可用于车轮转数计数的元件。在普通转盘计数的仪表中加装霍尔元件和磁铁,即可构成基于磁电转换技术的传感器。霍尔元件固定安装在计数转盘附近,永磁铁安装在计数盘位上,当转盘每转一圈,永磁铁经过霍尔元件一次即在信号端产生一个计量脉冲。由于霍尔电压很微弱(mV级),需用霍尔集成电路进行处理,如图14所示。无论信号转子的哪个叶片通过空气间隙时,霍尔信号发生器都将产生一个电位由高到低的脉冲信号直接送IOB3作外部中断源,信号转子通过霍尔元件将产生一个中断,此中断的个数即为车轮转过的转数。我们将中断信号作为SPCE061AD的输入信号,通过程序进行计数,然后通过8个输入口输出译码器CC4055上,再将译码后的数据接入到小功率管LED上。由于该计程显示范围为:0~
霍尔元件
图 14 霍尔元件接图
采用共阴极数码管LED
图 15 显示电路连接图
图 16 MIC原理图
麦克风电路如图16所示。凌阳的SPCE
无线接收模块 MIC N MIC P R2 C3 C1 C2 R1 R3 R4 SPCE V MIN MIC OUT OPI
图 17 无线模块接入图
声学模式训练 复杂声学、言语条件下的语音输入 语音匹配 语音模式训练 语音模型 识别结果、理解结果 语音处理 语言模型
图 18 语音识别原理图
图18是简化的语音识别原理图,其中实线部分成为训练模块,虚线部分为识别模块。辨认特定的使用者即特定语者(Speaker Dependent,SD)模式,使用者可针对特定语者辨认词汇(可由使用者自行定义,如人名声控拨号),即在启动小车前,系统将会提示输入语音命令作简单快速的训练纪录,在这里输入“启动”“停止”“返回”和“模式切换”四个语音命令,通过使用者的声音特性来加以辨认。随着技术的成熟,进入语音适应阶段SA(speaker adaptation),使用者只要对于语音辨识核心,经过一段时间的口音训练后,即可拥有不错的辨识率。
音频部分的原理图如下所示,在图19中可以看到两个跳线,其作用在于可以测量DAC的输出波形;另外拔掉跳线,可以断开DAC到喇叭放大的通路,使得DAC通道处于开路状态。这样便于用DAC做其他用途,用户可以用过这个跳线来加入自己的外围电路。
凌阳音频压缩算法根据不同的压缩比分为以下几种:
SACM-A2000:压缩比为8:1,8:1.25,8:1.5
SACM-S480: 压缩比为80:3,80:4.5
SACM-S240: 压缩比为80:1.5
按音质排序:A2000>S480>S240
用凌阳Compress Tool事先把所需要的语音信号录制好,本系统共包括十多个语音资源,整个语音信号经凌阳SACM_S480压缩算法压缩只占有13.2K存储空间,SPCE
包括语音命令训练程序、NAME子程序、前进子程序、倒车子程序、左转子程序、右转子程序。系统采用实时监控的控制策略,当程序运行时首先进行语音命令训练。训练成功后根据录入的语音命令,判断是否执行NAME子程序;执行NAME子程序后可以根据录入的语音命令再次判断执行哪个功能模块,在执行功能模块的同时,系统实时监控是否有新的语音命令输入,如果有则立即转入相应子程序,进而达到实时控制电机转动的目的。
图 19 音频放大电路
6 软件设计
6.1 软件流程图及设计思路(如图20)
6.2 模块设计
SPCE061单片机有两个外部中断,分别为EXT1和EXT2,两个外部输入脚分别为B口的IOB2和IOB3的复用脚。EXT1(IOB2)和EXT2(IOB3)两条外部中断请求输入线,用于输入两个外部中断源的中断请求信号,并允许外部中断以负跳沿触发方式来输入中断请求信号。EXT1(IOB2)为黑线检测,确定小车位置,可作为扩展功能应用。EXT2(IOB3)为轮子转数检测用于计算路程。IRQ4用做整个行程的时间计数。如图21。
⑴ 关于语音识别的介绍
我们所说的音频是指频率在20 Hz~20 kHz的声音信号,分为:波形声音、语音和音乐三种,其中波形声音就是自然界中所有的声音,是声音数字化的基础。语音也可以表示为波形声音,但波形声音表示不出语言、语音学的内涵。语音是对讲话声音的一次抽象。是语言的载体,是人类社会特有的一种信息系统,是社会交际工具的符号。音乐与语音相比更规范一些,是符号化了的声音。但音乐不能对所有的声音进行符号化。乐谱是符号化声音的符号组,表示比单个符号更复杂的声音信息内容。
数字音频的采样和量化:
将模拟的(连续的)声音波形数字元化(离散化),以便利数字计算机进行处理的过程,主要包括采样和量化两个方面。数字音频的质量取决于:采样频率和量化位数这两个重要参数。此外,声道的数目、相应的音频设备也是影响音频质量的原因。
开始 语音切换命令 语音命令训练 语音启动训练 扫描IOB4、IOB5和IOB6 等待语音命令 进行转向处理
图 20 软件流程图及设计思路
⑵ 音频文件通常分为两类:声音文件和MIDI文件
① 声音文件:指的是通过声音录入设备录制的原始声音,直接记录了真实声音的二进制采样数据,通常文件较大;
② MIDI文件:它是一种音乐演奏指令序列,相当于乐谱,可以利用声音输出设备或与计算机相连的电子乐器进行演奏,由于不包含声音数据,其文件尺寸较小。
⑶ 压缩编码的目的:
众所周知,嵌入式语音识别最大难点在于如何在硬件资源相对有限(相对与PC机而言)的情况下实现大量数据处理的语音识别算法。特别的,SPCE
开IRQ3和IRQ4 寄存器组出栈 清中断标志位 清中断标志位 寄存器压栈保护 中断返回 是IRQ3中断吗 IRQ3_EXT1中断吗 清中断标志位 IRQ3_EXT2中断吗 车轮转速加
图 21 中断服务流程图
语音压缩编码中的数据量是指:数据量=(采样频率×量化位数)/8(字节数) ×声道数目。
通过对资料的压缩,达到高效率存储和转换资料的结果,即在保证一定声音质量的条件下,以最小的资料率来表达和传送声音信息。
⑷ 压缩编码的必要性:
实际应用中,未经压缩编码的音频资料量很大,进行传输或存储是不现实的。所以要通过对信号趋势的预测和冗余信息处理,进行资料的压缩,这样就可以使我们用较少的资源建立更多的信息。
⑸ 常见的几种音频压缩编码及特点:
① 波形编码:将时间域信号直接变换为数字代码,力图使重建语音波形保持原语音信号的波形形状。波形编码的基本原理是在时间轴上对模拟语音按一定的速率抽样,然后将幅度样本分层量化,并用代码表示。译码是其反过程,将收到的数字序列经过译码和滤波恢复成模拟信号。
如:脉冲编码调制(Pulse Code Modulation,PCM)、差分脉冲编码调制(DPCM)、增量调制(DM)以及它们的各种改进型,如自适应差分脉冲编码调制(ADPCM)、自适应增量调制(ADM)、自适应传输编码(Adaptive Transfer Coding,ATC)和子带编码(SBC)等都属于波形编码技术。
波形编码特点:高话音质量、高码率,适于高保真音乐及语音。
② 参数编码:参数编码又称为声源编码,是将信源信号在频率域或其它正交变换域提取特征参数,并将其变换成数字代码进行传输。译码为其反过程,将收到的数字序列经变换恢复特征参量,再根据特征参量重建语音信号。具体说,参数编码是通过对语音信号特征参数的提取和编码,力图使重建语音信号具有尽可能高的准确性,但重建信号的波形同原语音信号的波形可能会有相当大的差别。
如:线性预测编码(LPC)及其它各种改进型都属于参数编码。该编码比特率可压缩到2Kbit/s-4.8Kbit/s,甚至更低,但语音质量只能达到中等,特别是自然度较低。
参数编码特点:压缩比大,计算量大,音质不高,廉价!
③ 混合编码:混合编码使用参数编码技术和波形编码技术,计算机的发展为语音编码技术的研究提供了强有力的工具,大规模、超大规模集成电路的出现,则为语音编码的实现提供了基础。80年代以来,语音编码技术有了实质性的进展,产生了新一代的编码算法,这就是混合编码。它将波形编码和参数编码组合起来,克服了原有波形编码和参数编码的弱点,结合各自的长处,力图保持波形编码的高质量和参数编码的低速率。
如:多脉冲激励线性预测编码(MPLPC),规划脉冲激励线性预测编码(KPELPC),码本激励线性预测编码(CELP)等都是属于混合编码技术。其数据率和音质介于参数和波形编码之间。
总之,音频压缩技术之趋势有两个:
1)降低资料率,提高压缩比,用于廉价、低保真场合(如:电话)。
2)追求高保真度,复杂的压缩技术(如:CD)。
在这里我们用的是SPCE061的特定语者辨识SD(Speaker Dependent),SD即语音样板由单个人训练,也只能识别训练某人的语音命令,而他人的命令识别率较低或几乎不能识别。
可利用计算机进行录音,选择录音效果一般的MIC比较好,因为小车跑动时要受环境的影响,效果一般的MIC录制的音更加接近凌阳单片机上的MIC所录制的。录制语音可为:“yeah”,“烦不烦”,“加速前进”,“中速前进”,“慢速前进”,“拐就拐”,“快速倒退”,“中速倒退”,“慢速倒退”。分别保存名称为:yeah.wav、jsqj.wav、zsqj.wav、msqj.wav、zg.wav、yg.wav、kd.wav、zd.wav、md.wav、tz.wav.
语音录制时,注意录制属性设置,最好选择为8Khz, 16位,单声道。语音录制好后,保存格式为“.wav”,利用凌阳单片机光盘内目录“\TOOLS\a2000\”下的工具进行语音压缩后放在程序目录“\voice”下边,经过压缩后的文件格式对应以上为:yeah.16k、jsqj.16k、zsqj.16k、msqj.16k、zg.16k、yg.16k、kd.16k、zd.16k、md.16k、tz.16k.然后修改配置文件“Makefile”中的OBJFILES的值以及对应的语音文件的目录地址值和“clean”的值 ,并且配置值顺序必须对应于语音训练的过程。
(1) 编写代码:
第一步: 新建项目文件,项目文件名称为SACM2000;
第二步: 新建C文件,文件名称为main;
第三步: 编写主函数代码;
第四步: 新建汇编文件,汇编文件名称为isr;
(2) 添加语音资源文件(即通过压缩工具压缩后的文件):
第一步:点击Watch窗口的页签Resource View,进入 Resource View窗口;
第二步:点击“SACM2000 resource”,右击鼠标,会弹出下拉菜单,选择“Add Files to Folder”;
第三步:弹出窗口,选择压缩后的语音文件,点击“打开”,则语音文件添加到资源文件中
(3) 添加hardware.asm文件:
方法:在FileView窗口中,点击Source Files右击,选择添加文件,会弹出添加文件窗口。Hardware.asm在IDE182/inlcude文件夹中,打开。
(4) 拷贝库文件和头文件到a2000项目文件中:
代码中用到库文件为:sacmV25.lib。
库文件所在地路径为:IDE182/library
代码中用到的头文件:a2000.h;a2000.inc;hardware.inc
头文件所在路径为:IDE182/include
(5) 连接库文件:
方法:点击 Project/setting/link
方法:点击library modules 的浏览按钮,到SACM2000项目文件路径下,找到SACMV25.lib.打开,点击OK,连接库结束
(6) 编译:
编译时输出窗口会有错误提示,缺少A2000SPEECH表,添加SPEECH表
方法:双击resource.asm文件,会弹出该文件窗口,操作如下:在“end table”后添加:
.public T_SACM_A2000_SpeechTable
T_SACM_A2000_SpeechTable:
.dw _RES_CC_24K_SA //0
注释:
1、 _RES_CC_24K_SA,是用户添加的资源文件,在resource.asm文件中已经有声明。
2、//0; 0表示的是Speech_Index.如果表中添加其他资源文件地址声明,顺序向上累加,1、2、。。。。
再次编译,编译通过。
(7) 下载:
选择EZ probe。
方法:点击工具栏中的
点击工具栏中的
该程序模块包括三部分:训练样本、识别、语音提示。具体程序的请见附录。
图22是语音辨识的一个整体框图:
初始化BSR_DeleteSDGroup(0) 启动实时监控BSR_EnableCPUIndicator() 调用训练模块TrainWord(intWordID, intRespondID) 初始化识别器BSR_InitRecognizer(BSR_MIC) 辨识处理BSR_GetResult()
图 22 语音辨识的整体框图
在程序中我们通过十条语句的训练演示特定人连续音识别,其中第一条语句为触发名称。另外九条为命令,训练完毕开始辨识当识别出触发名称后,开始发布命令,则会听到自己设置的应答,具体流程图如图23。
7 小车使用说明
7.1 语音的训练:
说“yeah”时训练小车的名字,听到“烦不烦”时训练成功;
说“加速前进”时训练“加速前进”;
说“中速前进”时训练“中速前进”;
说“慢速前进”时训练“慢速前进”;
说“拐就拐”时训练“左拐”;
说“烦不烦”时训练“右拐”;
说“快速倒退”时训练“快速倒退”;
说“中速倒退”时训练“中速倒退”;
说“慢速倒退”时训练“慢速倒退”;
说“停止”时训练“停止”。
听到两声“Yeah”后进入辨识状态,想重新训练,只要按键三,并复位即可,也可重新下载。经实验,语音训练时说话要清楚,每个语音训练两次,必须完全一样,否则不可辨识。选择比较安静的地方进行语音的训练较为合适。
7.2 小车的组装及注意事项
电路板制作好后,根据凌阳小车的安装方法安装上,驱动小车需要四节五号电池,为了能正常工作,请用1.5V的标准电池,安装在小车低部的电池盒内。待组装好后,检查是否有数据线掉地。用后请即时更换电池,以免腐蚀连接线。由于小车行驶速度较快,请将单片机和外置喇叭固定在小车上,可使用胶布进行固定。
8 系统测试及整机指标
小车的测试:
将小车按连接图连接好后,配置好程序,先编译,通过编译后下载到小车上的存储芯片上。模拟现场选择一块比较大而且较平的地方,找来五块砖头和一碇粉笔,在地上画一个长宽分别为
由于我设计的音控智能小车的控制电路与学校提供的有所不同,也没有条件自行制作,所以未能做成实物。如果将设计的小车做成实物,小车的控制将更加容易实现。凌阳小车的速度控制必须通过按键(KEY1、KEY2、KEY3)实现,在运动的小车上对单片机进行按键控制是不容易实现的,极不方便,而我设计的小车只需通过语音即能实现三级调速。通过对凌阳公司的小车的实验,如果条件成熟,我设计的小车也能完成任务。
整机指标为根据语音小车能顺利完成加速前进、中速前进、慢速前进、左拐、右拐、加速倒退、中速倒退、慢速倒退、停止。在遇上障碍物时,小车自动判别障碍物并能根据障碍物的位置采取拐向而绕开它。
初始化 定义存储器为BSR_DeleteSDGroup 调用第一条提示音播放 PlayRespond(RSP_INTR) 训练名称 TrainWord(NAME_ID,0) 成功否? 训练第一条命令 TrainWord(CONMAMD_ONE_ID,1) 成功否? 训练第二条命令 TrainWord(CONMAMD_ONE_ID,2) 成功否? 训练第九条命令 TrainWord(CONMAMD_ONE_ID,9) 成功否? 开始识别 辨别器初始化 BSR_InitRecognizer(BSR_MIC) 启动实时监控 BSR_EnableCPUIndicator() 调用提示语音放 PlayRespond(RSP_STAR) 获取语音数据 BSR_GetRessult() 辨识主循环 . . . . . 训练命令
图 23 语音辨识流程图
通过此次毕业设计,使我更深地了解了单片机,完成了本次设计的内容。达到了如何运用语音命令控制小车的进退及转向,和自动避开障碍物的功能。我相信随着技术的进步,单片机应用的不断推广,智能化的提高会促进我们生活质量的不断提高,带给人们更多的快乐和幸福。
1 李竟皎·嵌入式语音技术及凌阳16位单片机应用·北京:北京航空航天大学出版社,2003
2 范立南,李雪飞,尹授远·单片微型计算机控制系统设计·北京:人民邮电出版社,2004
3 侯丽华·基于单片机控制的自动往返电动小汽车微计算机信息· 20,2004(3):36-37
4 谭浩强·C程序设计(第二版)· 北京:清华大学出版社,2001
Pronunciation Control Car
——The sound controls three levels of velocity modulation
Kang Youbing Electric information engineering institute of
Panzhihua 617000
Abstract:
This article mainly introduced insults positive monolithic integrated circuit SPCE
Key word:SPCE
致谢:
在毕业设计期间,在郭老师的指导下,我对毕业设计的时间进行了周密的安排。在看完凌阳公司出品的光盘教程后,到实验室找到陈老师将小车借了回来。在结合实物的情况下很快就把前没看懂的内容理解了。考虑到凌阳的小车是已经做好了的,我们当代大学生应当发扬创新精神,在郭新年老师的指导下,我自己设计了音控小车的控制部分,并在原有的基础上增添了语音的命令,实现小车语音进行三级调速。在此,我要感谢郭新年老师的指导及郑会军、吴鹏松老师的意见及关心,使我能在规定时间内完成毕业设计。
在此我要感谢大学四年辛勤教育我们的教师, 在你们的悉心指导下,我在大学里学到了很多知识.还有我身边的同学们,在设计过程中李必军、熊杰、陈鹏、乌江等同学给了我很多的意见和建议,对他们表示感谢!
#define P_IOA_Data (volatile unsigned int *)0x7000
#define P_IOA_Buffer (volatile unsigned int *)0x7001
#define P_IOA_Dir (volatile unsigned int *)0x7002
#define P_IOA_Attrib (volatile unsigned int *)0x7003
#define P_IOA_Latch (volatile unsigned int *)0x7004
#define P_IOB_Data (volatile unsigned int *)0x7005
#define P_IOB_Buffer (volatile unsigned int *)0x7006
#define P_IOB_Dir (volatile unsigned int *)0x7007
#define P_IOB_Attrib (volatile unsigned int *)0x7008
#define P_Watchdog_Clear (volatile unsigned int *)0x7012
#define P_SystemClock (volatile unsigned int *)0x7013
#include "bsrsd.h"
#include "hardware.h"
#define NAME_ID 0x100//小车名字
#define COMMAND_ONE_ID 0x101//加速前进
#define COMMAND_TWO_ID 0x102//中速前进
#define COMMAND_THREE_ID 0x103//慢速前进
#define COMMAND_FORE_ID 0x104//左拐
#define COMMAND_FIVE_ID 0x105//右拐
#define COMMAND_SIX_ID 0x106//快速倒退
#define COMMAND_SEVEN_ID 0x107//中速倒退
#define COMMAND_EIGHT_ID 0X108//慢速倒退
#define COMMAND_NINE_ID 0X109//停止
//定义变量
#define RSP_INTR 0
#define RSP_NAME 1
#define RSP_FIRE 2
#define RSP_GUARD 3
#define RSP_AGAIN 4
#define RSP_NOVOICE 5
#define RSP_NAMEDIFF 6
#define RSP_CMDDIFF 7
#define RSP_STAR 8
#define RSP_MASTER 9
#define RSP_HERE 10
#define RSP_GUNSHOT 0
#define RSP_PATROL 11
#define RSP_READY 12
#define RSP_COPY 13
#define RSP_NOISY 14
extern unsigned int BSR_SDModel[100];
unsigned int commandID;
unsigned int g_Ret;
//..................全程变量....................
int gActivated = 0; //该变量用于检测是否有触发命令,当有识别出语句为触发名称则该位置1
int gTriggerRespond[] = {RSP_MASTER, RSP_HERE, RSP_MASTER};
int gComm2Respond[] = {RSP_PATROL, RSP_READY, RSP_COPY};
extern void ClearWatchDog();
int PlayFlag = 0;
unsigned int uiSpeed=0;
//unsigned int *ClearWatchdog = 0x7012;
void PlayRespond(int Result)
{
BSR_StopRecognizer();
//【API格式】void BSR_StopRecognizer(void);
//【功能说明】停止辨识。
//【备注】该函数是用于停止识别,当调用此函数时,FIQ_TMA中断将关闭。
SACM_A2000_Initial(1);
//【API格式】void SACM_A2000_Initial(int Init_Index)
//【功能说明】SACM_A2000语音播放之前的初始化。
//【参数】Init_Index=0 表示手动方式;Init_Index=1 则表示自动方式。
//【返回值】无
//【备注】该函数用于对定时器、中断和DAC等的初始化。
SACM_A2000_Play(Result, 3, 3);
//【API格式】void SACM_A2000_Play(int Speech_Index, int Channel, int Ramp_Set);
//【功能说明】播放资源中SACM_A2000语音或乐曲。
//【参数】Speech _Index:表示语音索引号。
//Channel: 1.通过DAC1通道播放;2.通过DAC2通道播放;3.通过DAC1和DAC2双通//道播放。
//Ramp_Set:0.禁止音量增/减调节;1.仅允许音量增调节;2.仅允许音量减调节;3.允许音//量增/减调节。
//【API格式】unsigned int SACM_A2000_Status(void);
//【功能说明】获取SACM_A2000语音播放的状态。
//【参数】无。
//【返回值】当R1的bit0=0,表示语音播放结束;bit0=1,表示语音在播放中
while((SACM_A2000_Status()&0x0001) != 0)//当播放的状态为1是,继续执行
{
SACM_A2000_ServiceLoop();
//【API格式】void SACM_A2000_ServiceLoop(void)
//【功能说明】从资源中获取SACM_A2000语音资料,并将其填入译码队列中。
//【参数】无。
//【返回值】无。
ClearWatchDog();//在InitIO.asm中定义
}
SACM_A2000_Stop();
BSR_InitRecognizer(BSR_MIC);
//【API格式】_BSR_InitRecognizer
//【功能说明】在中断中调用,并通过中断将语音信号送DAC通道播放。
//【参数】无。
//【返回值】无。
//【备注】
//① 该函数在中断FIQ_TMA中调用
//② 当主程序调用BSR_InitRecognizer时,辨识器便打开8K采样率的FIQ_TMA中断并开始将采样的语音数// 据填入辨识器的数据队列中。
//③ 应用程序需要设置一下程序段在FIQ_TMA中:
BSR_EnableCPUIndicator();// 启动实时监控
}int TrainWord(int WordID, int RespondID)
{
int res;
PlayRespond(RespondID);
while(1)
{
res = BSR_Train(WordID,BSR_TRAIN_TWICE);
if(res == 0) break;
switch(res)
{
case -1: //没有检测出声音
PlayRespond(5);
return -1;
case -2: //需要重新训练一遍
PlayRespond(4);
break;
case -3: //环境太吵
PlayRespond(5);
return -1;
case -4: //数据库满
return -1;
case -5: //检测出声音不同
if(WordID == NAME_ID) PlayRespond(5); //两次输入名称不同
else PlayRespond(5); //两次输入命令不同
return -1;
case -6: //序号错误
return -1;
}
}
return 0;
}
void F_GoAheadCtr1(int n) //加速前进
{
int i,j ;
for(j=0;j<n;j++)
{
ClearWatchDog();
i=i&0x0002;
i=i|0x00D8;
*P_IOB_Data=i;
F_Delay(150);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_GoAheadCtr2(int n) //中速前进
{
int i,j ;
for(j=0;j<n;j++)
{
ClearWatchDog();
i=i&0x0002;
i=i|0x0090;
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_GoAheadCtr3(int n) //慢速前进
{
int i,j ;
for(j=0;j<n;j++)
{
ClearWatchDog();
i=i&0x0002;
i=i|0x0000;
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_BackUpCtr1(int n) //加速倒退
{
int i,j ;
ClearWatchDog();
for(j=0;j<n;j++)
{
i=i&0x0002;
i=i|0x00FE;
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_BackUpCtr2(int n) //中速倒退
{
int i,j ;
ClearWatchDog();
for(j=0;j<n;j++)
{
i=i&0x0002;
i=i|0x00BA;
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_BackUpCtr3(int n) //慢速倒退
{
int i,j ;
ClearWatchDog();
for(j=0;j<n;j++)
{
i=i&0x0002;
i=i|0x0024;
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_TurnLeftCtr(int n) //左转
{
int i,j ;
ClearWatchDog();
for(j=0;j<n;j++)
{
i=i&0x0002;
i=i|0x
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_TurnRightCtr(int n) //右转
{
int i,j ;
ClearWatchDog();
for(j=0;j<n;j++)
{
i=i&0x0002;
i=i|0x00DE;
*P_IOB_Data=i;
F_Delay(90);
i=i&0x0002;
*P_IOB_Data=i;
F_Delay(60);
}
}
void F_StopCtr() //停止
{
int i,j ;
ClearWatchDog();
i=i&0x0002;
}
void F_ShunCtr() //壁障
{
int i;
i=*P_IOB_Data;
i=i&0x00D8;
switch(i)
{
case 0x00D8://前方无障碍
F_GoAheadCtr1(150);
break;
case 0x0200://右方有障碍
F_TurnLeftCtr(200);
break;
case 0x0400://中间有小障碍
F_BackUpCtr(100);
F_TurnRightCtr(200);
break;
case 0x0800://左方有障碍
F_TurnRightCtr(200);
break;
case 0x
F_BackUpCtr(150);
F_TurnRightCtr(200);
break;
case 0x
F_BackUpCtr(100);
F_TurnRightCtr(200);
break;
case 0x0E00://前面全部挡住
F_BackUpCtr(300);
F_TurnRightCtr(60);
F_TurnLeftCtr(20);
F_GoAheadCtr1(50);
break;
}
}
int main()//主程序
{
int res,jk,k, timeCnt=0, random_no=0,iMoveFlag=0xffff,BS_Flag=0,iMoveFlagBS=0,iCarState=0,iCarSpeed=14;
int uiIOB,i,ulAddr,Ret,free,*p,ss;
// unsigned int *p;
p=0xef00;
BS_Flag=*p;
ClearWatchDog();
SP_Init_IOB(0xff00,0x0000,0xff00);
SP_Init_IOA(0x0000,0x0000,0x0000);
BSR_DeleteSDGroup(0); // 初始化存储器RAM
if(BS_Flag==0xffff)
{
PlayRespond(0); //播放开始训练的提示音
//..........训练名称..............................
while(TrainWord(NAME_ID,0) != 0) ;
//..........训练第一条命令.......................
while(TrainWord(COMMAND_ONE_ID,1) != 0) ;
//..........训练第二条命令.......................
while(TrainWord(COMMAND_TWO_ID,2) != 0) ;
//..........训练第三条命令.......................
while(TrainWord(COMMAND_THREE_ID,3) != 0) ;
//..........训练第四条命令.......................
while(TrainWord(COMMAND_FORE_ID,4) != 0) ;
//..........训练第五条命令.......................
while(TrainWord(COMMAND_FIVE_ID,5) != 0) ;
//..........训练第六条命令.......................
while(TrainWord(COMMAND_SIX_ID,6) != 0) ;
//..........训练第七条命令.......................
while(TrainWord(COMMAND_SEVEN_ID,7) != 0) ;
//..........训练第八条命令.......................
while(TrainWord(COMMAND_EIGHT_ID,8) != 0) ;
//..........训练第九条命令.......................
while(TrainWord(COMMAND_NINE_ID,9) != 0) ;
BS_Flag=0xaaaa;
F_FlashWrite1Word(0xef00,0xaaaa);
F_FlashErase(0xe000);
F_FlashErase(0xe100);
F_FlashErase(0xe200);
ulAddr=0xe000;//********
for(commandID=0x100;commandID<0x109;commandID++)//存储训练的十条语音命令
{
g_Ret=BSR_ExportSDWord(commandID);
while(g_Ret!=0)
g_Ret=BSR_ExportSDWord(commandID);//
for(i=0;i<100;i++)
{
F_FlashWrite1Word(ulAddr,BSR_SDModel[i]);
ulAddr+=1;
}
} //***********************
}
if(BS_Flag==0xaaaa)
{
BSR_DeleteSDGroup(0);
p=0xe000;
for(jk=0;jk<5;jk++)
{
for(k=0;k<100;k++)
{
Ret=*p;
BSR_SDModel[k]=Ret;
p+=1;
}
g_Ret=BSR_ImportSDWord();
while(g_Ret!=0)
g_Ret=BSR_ImportSDWord();
}
}
//..........开始识别命令.........................
BSR_InitRecognizer(BSR_MIC); //辨识器初始化
//BSR_EnableCPUIndicator();
PlayRespond(0); // 播放开始辨识的提示音
PlayRespond(0);
//Interrupt();
iMoveFlag=0;
while(1)
{
// ClearWatchdog = 0x0001;
random_no ++;
if(random_no >= 3) random_no = 0;
res = BSR_GetResult();
if(res > 0) //识别出命令
{
if(gActivated)
{
timeCnt = 0;
switch(res)
{
case NAME_ID:
PlayFlag = 0;
ClearWatchDog();
F_StopCtr();
iMoveFlag=1;
iMoveFlagBS=0;
break;
case COMMAND_ONE_ID://加速前进
PlayRespond(1);
ClearWatchDog();
F_GoAheadCtr1(600);
iMoveFlag=0;
iMoveFlagBS=0;
gActivated = 0;
F_StopCtr();
iCarState=0x00D8;
break;
case COMMAND_TWO_ID://中速前进
PlayRespond(2);
ClearWatchDog();
F_GoAheadCtr2(600);
iMoveFlag=0;
iMoveFlagBS=0;
gActivated = 0;
F_StopCtr();
iCarState=0x0090;
break;
case COMMAND_THREE_ID://慢速前进
PlayRespond(3);
ClearWatchDog();
F_GoAheadCtr3(600);
iMoveFlag=0;
iMoveFlagBS=0;
gActivated = 0;
F_StopCtr();
iCarState=0x0000;
break;
case COMMAND_FORE_ID://左转
PlayRespond(4);
F_TurnLeftCtr(450);
F_GoAheadCtr1(100);
F_TurnLeftCtr(350);
F_GoAheadCtr1(100);
F_TurnLeftCtr(350);
F_GoAheadCtr1(100);
F_TurnLeftCtr(350);
F_GoAheadCtr1(100);
iMoveFlag=0;
iMoveFlagBS=0;
iCarState=0x
ClearWatchDog();
gActivated = 0;
F_StopCtr();
break;
case COMMAND_FIVE_ID://右转
PlayRespond(5);
F_TurnRightCtr(450);
F_GoAheadCtr1(100);
F_TurnRightCtr(350);
F_GoAheadCtr1(100);
F_TurnRightCtr(350);
F_GoAheadCtr1(100);
F_TurnRightCtr(350);
F_GoAheadCtr1(100);
iMoveFlag=0;
iMoveFlagBS=0;
iCarState=0x00DE;
ClearWatchDog();
gActivated = 0;
F_StopCtr();
break;
case COMMAND_SEX_ID://快速倒退
PlayRespond(6);
ClearWatchDog();
F_BackUpCtr1(650);
PlayFlag = 0;
iMoveFlag=0;
iCarState=0x00FE;
iMoveFlagBS=0;
ClearWatchDog();
gActivated = 0;
F_StopCtr();
break;
case COMMAND_SEVEN_ID://中速倒退
PlayRespond(7);
ClearWatchDog();
F_BackUpCtr2(650);
PlayFlag = 0;
iMoveFlag=0;
iCarState=0x00BA;
iMoveFlagBS=0;
ClearWatchDog();
gActivated = 0;
F_StopCtr();
break;
case COMMAND_EIGHT_ID://慢速倒退
PlayRespond(8);
ClearWatchDog();
F_BackUpCtr3(650);
PlayFlag = 0;
iMoveFlag=0;
iCarState=0x0024;
iMoveFlagBS=0;
ClearWatchDog();
gActivated = 0;
F_StopCtr();
break;
case COMMAND_NINE_ID://停止
PlayRespond(9);
ClearWatchDog();
F_StopCtr();
break;
}
}
else
{
// gActivated = 1;
if(res == NAME_ID)//语音为小车名字
{
ClearWatchDog();
PlayRespond(0);//播放提示音
iMoveFlag=1;//小车移动标志为1
iMoveFlagBS=0;//目前移动状态为停止
gActivated = 1;
timeCnt = 0;
}
}
}
else if (gActivated)
{
if (++timeCnt > 450) //超出定时
{
ClearWatchDog();
gActivated = 0;
timeCnt = 0;
}
}
if(iMoveFlagBS==13&&iMoveFlag==0)
{
i=*P_IOB_Data;//**
i=i&0x0002;//**
ClearWatchDog();
if(i==0x00D8||i==0x0200||i==0x0400||i==0x0800||i==0x
else
{
i=i&0x0002;
i=i|iCarState;
//*P_IOB_Data=i;
ClearWatchDog();
}
}
if(iMoveFlagBS==iCarSpeed&&iMoveFlag==0)
{
i=i&0x0002;
i=i|0x0000;//小车慢速前进
*P_IOB_Data=i;
iMoveFlagBS=0;
ClearWatchDog();
}
while(*P_IOB_Data!=0x0002)
{
if(iMoveFlagBS=0&&(*P_IOB_Data&0x1000!=0))
ss+=1
}
ss=int(ss*16.3);
*P_IOA_Data=ss&0xff00;
iMoveFlagBS++;
i=*P_IOA_Data;//**
i=i&0x0007;//**
}
}