陕西理工学院毕业设计
SUB1 SUB2 SUB3
主 程 序
CALL SUB1 CALL SUB2 CALL SUB3
继续执行 主程序
RETF RETFF
图4.6 三重程序嵌套过程
4.3 C语言程序设计
是否具有对高级语言HLL(High Level Language)的支持已成为衡量微控制器性能的标准之一。显然,在HLL平台上要比在汇编级上的编程具有诸多优势:代码清晰易读、易维护,易形成模块化,便于重复使用从而增加代码的开发效率。
HLL中又因C语言的可移植性最佳而成为首选。因此,支持C语言几乎是所有微控制器设计的一项基本要求。μ'nSP指令结构的设计就着重考虑了对C语音的支持,GCC是一种针对μ’nSP操作平台的ANSI-C编译器。
在μ’nSP的指令系统算逻辑作符与ANSI-C算符大同小异,见表4.7。
表4.7μ'nSP指令的算逻辑操作符
数据类型 Char Short Int Long int Unsigned char Unsigned short Unsigned int Unsigned long int
Float Double
数据长度(位数)
16 16 16 32 32 16 16 32 32 64
值域 -32768~32767 -32767~32767 -32767~32767 -2147483648~2147483647
0~65535 0~65535 0~65535 0~4294967295
以IEEE格式表示的32位浮点
数
以IEEE格式表示的32位浮点
数
4.3.1程序调用协议
由于C编译器产生的所有标号都以下划线(-)为前缀,而C程序在调用汇编程序名也以下划线为前缀。模块代码间的调用是遵循μ'nSP体系的调用协议。调用协议是指这样一套法则:它使不同的子程序代码之间形成一种握手通讯接口,并完成由一个子程序到另一个子程序的参数传递与控制,以及定义出子程序调用与子程序返回值的常规规则,μ'nSP体系
[7]
的调用协议的内容如下。
参数传递
参数以相反的顺序(从右到左)被压入栈中。必要时所有的参数都被转换成其在函数原型中
第 14 页 共 51 页
陕西理工学院毕业设计
被声明过的数据类型。但如果函数在调用发生在其声明之前,则传递在调用函数里的参数是不会被进行任何数据类型转换的。 堆栈维护及排列
函数调用者应切记在程序返回时将调用程序压入栈中的参数弹出。 返回值
16位的返回值存放在寄存器R1中。32位的返回值存入寄存器对R1、R2中;其中低字在R1中,高字在R2中。若要返回结构则需要在R1中存放一个指向结构的指针。
寄存器数据暂存方式
编译器会产生prolog/epilog过程动作来暂存或者恢复PC、SR及BP寄存器。汇编器则通过“CALL”指令可将PC和SR自动压入栈中,而通过“RETF”或“RETI”指令将其自动弹出栈来。
指针
编译器所认可的指针是16位的。函数的指针实际上并非指向函数的入口地址,而是一个段地址向量_function_entry,在该向量里由两个连续的WORD的数据单元存放的值才是函数的入口地址。
4.3.2语音识别程序设计
语音识别主要分为“录入语音”和“识别语音”两个阶段。录入语音阶段,单片机对采集到的语音样本进行分析处理,从中提取出语音特征信息,建立一个特征模型;在识别阶段,单片机对采集到的语音样本也进行类似的分析处理,提取出语音的特征信息,然后将这个特征信息模型与已有的特征模型进行对比,如果二者达到了一定的匹配度,则输入的语音被识
[15]
别。训练过程流程图如图4.8所示,语音识别的具体流程如图4.9所示。
开始 初始化RAM 采集语音信 执行训练,获取训练结果 识别出语音指令
N 获取识别初始化识别器 开始
N 训练成功 Y 执行对应动作 Y 返回 返回 图4.8 训练过程流程图 图4.9 语音识别流程图
4.3.3语音录入子程序
当程序检测到训练标志位BS_Flag内容为0xffff,就会要求操作者对它进行录入信息
第 15 页 共 51 页
陕西理工学院毕业设计
操作,录入信息采用两次录入获取结果的方式,以录入名字为例:小车首先会提示:给我取个名字吧,这时你可以告诉它一个名字(比如Jack );然后它会提示:请再说一遍,这时再次告诉它名字(Jack),如果两次的声音差别不大,小车就能够成功的建立模型,名称录入成功;如果没能够成功的建立模型,小车会告知失败的原因并要求重新录入信息。成功录入名称后会给出下一条待录入指令提示音:前进,参照名称录入方式录入前进指令。依次录入小车的名称—前进指令—倒车指令—左转指令—右转指令,全部录入成功,子程序返回,
[16]
语音录入结束。语音录入小车总流程如图4.10所示。
图4.10 语音录入小车总流程
4.3.4语音控制小车子程序
动作子程序包括:前进、后退、左拐、右拐子序。
前进:由小车的结构原理和驱动电路分析知:只要IOB8 为高电平,IOB9,IOB10,IOB11 全部为低电平即可实现小车的前进。前进子程序包括语音提示、置端口数据、启动定时器操作。
倒车:由小车的结构原理分析和驱动电路分析知:只要IOB9 为高电平,IOB8,IOB10,IOB11 全部为低电平即可实现小车的倒退。倒退子程序包括语音提示、置端口数据、启动定时器操作。
左转:由小车的结构原理分析和驱动电路分析知,小车左转需要两个条件:前轮左偏,后轮前进。这时对应的 I/O 状态为:IOB8、IOB10 为高电平,IOB9、IOB11 为低电平。左转子程序包括语音提示、置端口数据、启动定时器操作。
右转:由小车的结构原理分析和驱动电路分析知,小车右转需要两个条件:前轮右偏;后轮前进。这时对应的 I/O 状态为:IOB8、IOB11 为高电平,IOB9、IOB10 为低电平。右
第 16 页 共 51 页
陕西理工学院毕业设计
转子程序包括语音提示、置端口数据、启动定时器操作。
注:在转弯之前首先让前轮朝目标方向的反方向偏转,然后再让前轮朝目标方向偏转,这样前轮的摆动范围更大,惯性更大,摆幅也最大,能更好实现转弯[17]。
语音控制小车总流程图如图4.11所示。
开始
初始化
输入语音指令 Y
小车前进 是否为前进指令 N Y
小车后退 是否为后退指令 N Y
小车左拐 是否为左拐指令
N Y
是否为右拐指令 小车右拐
N
返回
图4.11语音控制小车总流程图
4.3.5中断子程序
中断是为处理器对外界异步事件具有处理能力而设置的,中断技术的引入把计算机的发展和应用大大地推进一步。因此中断功能的强弱已成为衡量一台计算机性能的重要指标。
SPCE061A 系列单片机中断系统,是凌阳 16 位单片机中中断功能较强的一种,它可以提供 14 个中断源,具有两个中断优先级,可实现两级中断嵌套功能。用户可以用关中断指令(或复位)屏蔽所有的中断请求,也可以用开中断指令使 CPU 接受中断申请。每一个中断源可以用软件独立控制为开或关中断状态;但中断级别不可用软件设置。
SPCE061A 的中断类型:
SPCE061A 的结构给出了三种类型的中断:软件中断和事件中断。 软件中断
软件中断是由软件指令 break 产生的中断。软件中断的向量地址为 FFF5H 2)异常中断异常中断表示为非常重要的事件,一旦发生, CPU 必须立即进行处理。目前,SPCE061A
第 17 页 共 51 页
陕西理工学院毕业设计
定义的异常中断只有?复位?一种。通常,SPCE061A 系统复位可以由以下三种情况引起:上电、看门狗计数器溢出以及系统电源低于电压低限。不论什么情况引起复位,都会使复位引脚的电位变低,进而使程序指针 PC 指向由一个复位向量(FFF7H)所指的系统复位程序入口地址。
事件中断
事件中断(可简称“中断”,以下提到的“中断”均为事件中断)一般产生于片内设部件或由外设中断输入引脚引入的某个事件。这种中断的开通/禁止,由相应独立使能和相应的 IRQ 或 FIQ 总使能控制。
SPCE061A 的事件中断可采用两种方式:快速中断请求即 FIQ 中断和中断请求即 IRQ 中断。这两种中断都有相应的总使能。
中断向量和中断源:
共有 9 个中断向量即 FIQ、IRQ0~IRQ6 及 UART IRQ。这 9 个中断向量共可安置 14 个中断源供用户使用,其中有 3 个中断源可安置在 FIQ 或 IRQ0~IRQ2 中,另有 10 个中断源则可安置在 IRQ3~IRQ6 中。还有一个专门用于通用异步串行口 UART 的中断源,须安置在 UART IRQ 向量中。
虽然已经有了前进、后退以及停车 (通过直接呼叫小车的名字使其停车)等语音控制指令,但是考虑环境的干扰因素,小车运行时的噪音影响和有效距离的限制,小车运行后可能接收不到语音指令而一直运行。为了防止出现这种情况,加入了时间控制,在启动小车运行的同时启动定时器,定时器时间到停止小车的运行,该定时器借助于 2Hz 时基中断完成。可以在程序中修改uiTimeset 参数来控制运行时间,当uiTimeset=2 时,运行时间为 1s,以此类推。图4.12为该程序的流程图。
开始
定时计数器加1
Y
N 定时到4.5s
N 停车待命
中断返回 图4.12 2HZ中断子函数
4.4程序中需要说明的几个问题
在程序中有几个地方不易理解,需要特别说明一下: 有没有被训练过是怎么知道的? 在这里利用了一个特殊的Flash单元,语音模型存储区首单元(该示例程序中为0xe000单元)。当Flash在初始化以后,或者在擦除后为0xffff,在成功训练并存储后为0x0055
第 18 页 共 51 页