陕西理工学院毕业设计
由任意数量的字母和数字字符组成,但只有前 32 位是有效的。它可以写在文件中的任何一列上,但必须以字母字符或下划线(_)开头,且标号名后须以冒号(:)来结束。在下面的程序例子中 LABEL1,LABEL2 和 LABEL3 都是全局标号。
局部标号只有在局部区域内定义才有效。正是这种约束才使得局部标号的定义可以安全地重复使用在整个程序各处而不致产生混乱错误。
局部标号应当注意以下几点:
局部标号也像全局标号那样最多可有 32 个字母或数字字符,且必须以字母字符或问号(?)开头。μ'nSP?的汇编器通常规定用问号(?)作为局部标号的前缀或后缀。除此之外,局部标号最好也遵循全局标号的使用规则。
在不同的局部区域里所定义的局部标号都有不同的含义,且标号?a 是不同于标号 a?的。切忌将诸如“+、-、*、/”这类运算符用在局部标号中,伪指令 VAR,SECTION 或 ENDS 是不可以用在局部标号结尾处的。
程序注释与符号规定
程序注释行必须用双斜线(//)或分号(;)起始,它可与程序指令在同一行,或跟在指令后,亦可在指令的前一行或后一行。
μ’nSP?的汇编器规定伪指令不必区分字母的大小写,亦即书写伪指令时既可全用大写,也可全用小写,甚至可以大小写混用。但所有定义的标号包括宏名、结构名、结构变量名、段名及程序名则一律区分其字母的大小写。 5.3.3 C语言程序调试
是否具有对高级语言HLL(High Level Language)的支持已成为衡量微控制器性能的标准之一。显然,在HLL平台上要比在汇编级上的编程具有诸多优势:代码清晰易读、易维护,易形成模块化,便于重复使用从而增加代码的开发效率。
HLL中又因C语言的可移植性最佳而成为首选。因此,支持C语言几乎是所有微控制器设计的一项基本要求。μ'nSP指令结构的设计就着重考虑了对C语音的支持,GCC是一种针对μ’nSP操作平台的ANSI-C编译器。
在μ’nSP的指令系统算逻辑作符与ANSI-C算符大同小异,见表5.9。
表5.9 μ’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位浮点
数
由于C编译器产生的所有标号都以下划线(-)为前缀,而C程序在调用汇编程序名也以下划线为前缀。模块代码间的调用是遵循μ’nSP体系的调用协议。调用协议是指这样一套法则:它使不同的子程序代码之间形成一种握手通讯接口,并完成由一个子程序到另一个子程序的参数传递与控制,以及定义出子程序调用与子程序返回值的常规规则,μ’nSP体
[7]
系的调用协议的内容如下。
参数传递
参数以相反的顺序(从右到左)被压入栈中。必要时所有的参数都被转换成其在函数原型中
第 24 页 共 51 页
陕西理工学院毕业设计
被声明过的数据类型。但如果函数在调用发生在其声明之前,则传递在调用函数里的参数是不会被进行任何数据类型转换的。 堆栈维护及排列
函数调用者应切记在程序返回时将调用程序压入栈中的参数弹出。 返回值
16位的返回值存放在寄存器R1中。32位的返回值存入寄存器对R1、R2中;其中低字在R1中,高字在R2中。若要返回结构则需要在R1中存放一个指向结构的指针。
寄存器数据暂存方式
编译器会产生prolog/epilog过程动作来暂存或者恢复PC、SR及BP寄存器。汇编器则通过“CALL”指令可将PC和SR自动压入栈中,而通过“RETF”或“RETI”指令将其自动弹出栈来。
指针
编译器所认可的指针是16位的。函数的指针实际上并非指向函数的入口地址,而是一个段地址向量_function_entry,在该向量里由两个连续的WORD的数据单元存放的值才是函数的入口地址。
中断
中断是指计算机在执行某一程序的过程中,由于计算机系统内、外的某种原因,而必须终止原程序的执行,转去执行相应的处理程序,待处理结束之后,再回来继续执行被终止的原程序过程。中断技术能实现 CPU 与外部设备的并行工作,提高 CPU 的利用率以及数据的输入/输出效率;中断技术也能对计算机运行过程中突然发生的故障做到及时发现并进行自动处理如:硬件故障、运算错误及程序故障等;中断技术还能使我们通过键盘向计算机发出请求,随时对运行中的计算机进行干预,而不用先停机,然后再重新开机等等。
中断源
中断源是指在计算机系统中向 CPU 发出中断请求的来源,中断源可以人为设定也可以是为响应突发性随机事件而设置。如定时器中断,它的中断源即是定时器。
中断优先级
由于在实际的系统中,往往有多个中断源,且中断申请是随机的,有时可能会有多个中断源同时提出中断申请,但 CPU 一次只能响应一个中断源发出的中断请求,这时 CPU 应响应那个中断请求?这就需要用软件或硬件按中断源工作性质的轻重缓急,给它们安排一个优先顺序,即所谓的优先级排队。中断优先级越高,则响应优先权就越高。当 CPU 正执行中断服务程序时,又有中断优先级更高的中断申请产生,如果 CPU 能够暂停对原来的中断处理程序,转而去处理优先级更高的中断请求,处理完毕后,再回到原低级中断处理程序,这一过程称为中断嵌套。具有这种功能的中断系统称为多级中断系统;没有中断嵌套功能的则称为单级中断系统。 5.3.4中断控制寄存器
SPCE061A 对中断源的开放和屏蔽,以及每个中断源是否被允许中断,都受中断允许寄存器 P_INT_Ctrl 和 P_INT_Clear 及 P_INT_Ctrl_New 控制和一些中断控制指令。
中断控制单元 P_INT_Ctrl(读/写)(7010H) P_INT_Ctrl 控制单元具有可读和可写的属性,其读写时的意义是不同的。当写中断控制单元中的某位为“1”时,即允许该位所代表的中断被开放,并关闭屏蔽中断触发器,此时当有该中断申请时,CPU 会响应。否则如果该位被置 0 则禁止该位所代表的中断。即使有中断申请,CPU 也不会响应。
当读取中断控制单元时,其主要作为中断标志,因为其每一位均代表一个中断,当 CPU 响应某中断时,便将该中断标志置“1”,即将 P_INT_Ctrl 中的某位置“1”,可以通过读取该寄存器来确定 CPU 响应的中断。
清除中断标志控制单元 P_INT_Clear(写)(7011H)清除中断标志控制单元主要用于清除中断控制标志位,当 CPU 响应中断后,会将中断标志置位为“1”,当进入中断服务程序后,要将其控制标志清零,否则 CPU 总是执行该中断。
第 25 页 共 51 页
陕西理工学院毕业设计
因为 P_INT_Clear 寄存器的每一位均对应一个中断,所以如果想清除某个中断状态标志,只要将该寄存器中对应的中断位置 1 即可清除该中断状态标志位。该寄存器只有写的属性,读该寄存器是无任何意义的。
SPCE061A 的结构给出了两种类型的中断:软件中断和事件中断。 (1)软件中断
软件中断是由软件指令 break 产生的中断。软件中断的向量地址为 FFF5H 2)异常中断异常中断表示为非常重要的事件,一旦发生, CPU 必须立即进行处理。目前,SPCE061A 定义的异常中断只有?复位?一种。通常,SPCE061A 系统复位可以由以下三种情况引起:上电、看门狗计数器溢出以及系统电源低于电压低限。不论什么情况引起复位,都会使复位引脚的电位变低,进而使程序指针 PC 指向由一个复位向量(FFF7H)所指的系统复位程序入口地址。
(2)事件中断
事件中断(可简称“中断”,以下提到的“中断”均为事件中断)一般产生于片内设部件或由外设中断输入引脚引入的某个事件。这种中断的开通/禁止,由相应独立使能和相应的 IRQ 或 FIQ 总使能控制。
SPCE061A 的事件中断可采用两种方式:快速中断请求即 FIQ 中断和中断请求即 IRQ 中断。这两种中断都有相应的总使能。
中断向量和中断源
共有 9 个中断向量即 FIQ、IRQ0~IRQ6 及 UART IRQ。这 9 个中断向量共可安置 14 个中断源供用户使用,其中有 3 个中断源可安置在 FIQ 或 IRQ0~IRQ2 中,另有 10 个中断源则可安置在 IRQ3~IRQ6 中。还有一个专门用于通用异步串行口 UART 的中断源,须安置在 UART IRQ 向量中。
中断控制指令 FIQ ON
功能:用来开通 FIQ 中断(FIQ 的总中断允许开),其控制指令不能代替 P_INT_Ctrl,也就是说即使在程序中,写了该代码但是没有在 P_INT_Ctrl 寄存器中 FIQ 处置位 1, CPU 无法响应该中断。FIQ ON 与 FIQ OFF 配对使用的。 FIQ OFF
功能:这个指令用来屏蔽 FIQ 中断。该指令可以屏蔽P_INT_Ctrl控制寄存器打开的 FIQ 中断;
IRQ ON(IRQ 的总中断允许开)功能:
这个指令用来开放 IRQ 中断,该控制指令不能代替P_INT_Ctrl,与FIQ ON 相同。必须通过P_INT_Ctrl来开通中断,其与IRQ OFF是对应使用的。 IRQ OFF
功能:这个指令是用来屏蔽 IRQ 中断。与 FIQ OFF 相同,可以屏蔽 P_INT_Ctrl 开放的中断,并通过 IRQ ON 来打开。 INT
功能:这个指令用来设置允许/禁止 FIQ 和 IRQ 中断。该控制指令与前面的指令相同,只有先通过 P_INT_Ctrl 寄存器来打开中断通道。INT 控制指令还可以以细分为:
INT FIQ 功能:允许 FIQ 中断,关闭IRQ中断。 INT IRQ 功能:允许 IRQ 中断,关闭FIQ中断。
INT FIQ,IRQ 功能:允许 FIQ 中断,允许IRQ中断。 INT OFF 功能:关闭 FIQ 中断,关闭IRQ中断。 在做程序调试之前,首先在计算机中安装凌阳IDE2.0软件,其次将EZ_PROBE下载线一边的五针接头与61板上J11接口(即标有“EZ_PROBE”的插座)连接好,下载线的另一边25针插座与PC后面的并行接口(即打印机接口)相接。用短路跳线把J11接口边上S5跳线端子的2和3端子短接。将电池盒与61板连接好并打开电池盒上的开关。启动IDE2.0软件,
第 26 页 共 51 页
陕西理工学院毕业设计
选择[File]→[NEW] 创建工程,把所调试的程序加载到PROJET,程序加载界面如图5.10所示。
图5.10程序加载界面
语音识别主要分为“录入语音”和“识别语音”两个阶段。录入语音阶段,单片机对采集到的语音样本进行分析处理,从中提取出语音特征信息,建立一个特征模型;在识别阶段,单片机对采集到的语音样本也进行类似的分析处理,提取出语音的特征信息,然后将这个特征信息模型与已有的特征模型进行对比,如果二者达到了一定的匹配度,则输入的语音被识别。在程序编译与链接前设置好项目的相关信息,主要是芯片、下载线、调试器的选择。点击工具栏上的[Select Body]按钮,打开Select Body对话框,按照图5.11所示的选择设置,点击[OK]。
图5.11 Select Body设置图
当程序检测到训练标志位BS_Flag内容为0xffff,就会要求操作者对它进行录入信息操作,录入信息采用两次录入获取结果的方式,以录入名字为例:小车首先会提示:给我取个名字吧,这时你可以告诉它一个名字(比如Jack );然后它会提示:请再说一遍,这时再次告诉它名字(Jack),如果两次的声音差别不大,小车就能够成功的建立模型,名称录入成功;如果没能够成功的建立模型,小车会告知失败的原因并要求重新录入信息。成功录入名称后会给出下一条待录入指令提示音:前进,参照名称录入方式录入前进指令。依次录入小车的名称—前进指令—倒车指令—左转指令—右转指令,全部录入成功,子程序返回,语音录入结束。然后选择[Build]→[Rbuild All]进行源文件的编译与链接,若编译链接中有错误和警告,则会显示在如图5.12所示Output窗口中。
第 27 页 共 51 页
陕西理工学院毕业设计
图5.12 编译链接后OUTPUT窗口显示
最初对芯片的程序编写时,在μ’nSP?软件中编译没有错误之后,当将程序下载到单片机中进行硬件调试时,却发现,当发出“前进”的命令时,语音识别到的信号是“停车”,开始的时候以为是识别的精度误差的原因,但是无论如何发出“前进”的命令,SPCE061A检测到的语音指令始终是“停车”的指令。最后在芯片手册的看到语音识别关键词的顺序要与程序中自己宏定义的标志一致,否则会出现识别混乱的情况。
虽然语音识别混乱的情况已经得到改善,但是,语音识别精度的问题始终是一个不能忽略的问题,在很大程度上,语音识别的精度影响着整个语音识别智能车控制系统的稳定程度。因此,提高SPCE061A的语音识别精度是至关重要的。
修改之前的语音指令如下。
#define DATE_A 10 //数组二维数值 #define DATE_B 20 //数组二维数值 uint8 code sRecog[DATE_A][DATE_B]={ “qianjin”,//前进指令 “houtui”,//后退指令
“zuo”,//左拐指令 “you”,//右拐指令 “tingzhi”,//停止指令 }
修改之后的语音指令如下。
#define DATE_A 25//数组二维数值 #define DATE_B 20 //数组二维数值 uint8 code sRecog[DATE_A][DATE_B]={ “qianjin”,//前进指令 “houtui”,//后退指令
“zuoguai”,//左拐指令 “youguai”,//右拐指令 “tingzhi”,//停止指令
/*下面的关键词为屏蔽的干扰关键词*/
“qian”, “hou”, “zuo”, “you”, “ting”, “zhuan”,
第 28 页 共 51 页