DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1053|回复: 0
打印 上一主题 下一主题

[待整理] 混合信号嵌入式设计实验指南-数字实验之:实验2—中断

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-10 07:20:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
目标:本实验专门用于介绍PSoC CPU 的中断句柄。注意这个实验分成7 个部分:LAB2A 到LAB 2G 。在继续下一个实验前,要成功地完成每一个部分。
         
        完成这个实验后,读者应能做到:
        用C 语言写控制程序;
        理解如何处理一个发布的中断;
        理解如何处理一个未处理的中断;
        将CPU 设置在休眠模式,然后用休眠定时器未处理的中断唤醒它;
        使用汇编语言编写的中断句柄,来操作在C 程序里声明的一个全局变量;
        使用C 语言编写的中断句柄,来操作在C 程序里声明的一个全局变量;
        在中断向量表空间中,放置一个小的中断服务程序ISR。
         
        假设:
        所有先前实验的假设;
        使能编译器用于开发系统。
         
        要求的材料:
        CY3210 PSoCEval1 板子;
        面包板线。
         
        要求的设备:
         无。
         
        相关的参考资料
        所有前面实验的参考资料;
        Cypress C 语言编译器用户指南。
         
        中断控制器为PSoC 混合信号阵列内的不同硬件资源提供了一种机制,可以将程序的执行改变到新的地址,而不需要考虑当前正在执行的任务。图1.13 给出了中断处理的方块图。
         
        对于CPU,要识别一个特殊资源的中断,下面必须是真(有效)的:
        必须设置它的中断使能屏蔽;
       

        图1.13 中断处理

        它必须是所有未处理中断中,级别最高的;必须设置全局中断使能。CPU 通过下面响应这个请求:将当前程序计数器的值保存起来;将当前标志寄存器的值保存起来。跳转到指定的中断向量地址。对于27x 系列的器件,有18 个不同的中断源。
         
        表1.2 从最高优先级到最低优先级,给出了每个中断源和它的向量地址。
         
        表1.2 中断向量表
                               
                                        中断源

                       
                               
                                        向量位置

                       
                               
                                        硬件复位

                       
                               
                                        0x0000

                       
                               
                                        供电监视器

                       
                               
                                        0x0004

                       
                               
                                        模拟列0

                       
                               
                                        0x0008

                       
                               
                                        模拟列1

                       
                               
                                        0x000c

                       
                               
                                        模拟列2

                       
                               
                                        0x0010

                       
                               
                                        模拟列3

                       
                               
                                        0x0014

                       
                               
                                        VC3

                       
                               
                                        时钟

                       
                               
                                        GPIO

                       
                               
                                        0x001c

                       
                               
                                        数字块00

                       
                               
                                        0x0020

                       
                               
                                        数字块01

                       
                               
                                        0x0024

                       
                               
                                        数字块02

                       
                               
                                        0x0028

                       
                               
                                        数字块03

                       
                               
                                        0x002c

                       
                               
                                        数字块10

                       
                               
                                        0x0030

                       
                               
                                        数字块11

                       
                               
                                        0x0034

                       
                               
                                        数字块12

                       
                               
                                        0x0038

                       
                               
                                        数字块13

                       
                               
                                        0x003c

                       
                               
                                        I2C

                       
                               
                                        0x0060

                       
                               
                                        休眠定时器

                       
                               
                                        0x0064

                       
         
        在中断服务程序的末尾,先前程序计数器和标志寄存器的值被恢复到它们原来的值,原先的程序从离开它的地方继续。
         
        练习2A-1 :假设正确的使能全局中断和中断屏蔽,可能永远不能服务较低优先级的中断。这是为什么?
         
        1.2.1 实验2A—发布中断
        使用INT_CLRx 寄存器访问发布的中断。通过INT_CLR0 寄存器的第6 比特位来控制休眠定时器发布中断。当该位的值为“1”时,将发布一个定时器的中断。将该位设置为“0”时,将清除所发布的中断。
         
        步骤1:创建新的工程。
        工程名字为Lab2A
        —选择C 选项;
        —用于器件类型及其设置的标准实验设置;
        —转到互联界面,将全局参数Sleep_Timer 设置为1Hz (这将使得休眠定时器每一秒钟产生一个等待处理的中断);
        —按表1.3 设置四个端口引脚。
         
        表1.3 端口驱动设置
                                                                        名字(Name)
                       
                                                                        端口(Port)
                       
                                                                        选择(Select)
                       
                                                                        驱动(Drive)
                       
                                                                        LedOut1
                       
                                                                        P1[0]
                       
                                                                        StdCPU
                       
                                                                        Strong
                       
                                                                        LedOut2
                       
                                                                        P1[1]
                       
                                                                        StdCPU
                       
                                                                        Strong
                       
                                                                        LedOut3
                       
                                                                        P1[2]
                       
                                                                        StdCPU
                       
                                                                        Strong
                       
                                                                        LedOut4
                       
                                                                        P1[3]
                       
                                                                        StdCPU
                       
                                                                        Strong
                       
         
        步骤2:在Eval1 板子上添加跳线。
        使用跳线进行下面的连接—P10 到LED1 —P11 到LED2 —P12 到LED3
        P13 到LED4 。生成应用。步骤3:写软件。转到应用程序编辑器,打开如图1.14 所示的main.c 文件。如图1.15 所示,添加代码。该程序应注意:bShadow 定义成一个全局单字节变量。INT_CLR0 寄存器用来监视和清除休眠定时器已经发布的中断。
       

        图1.14 main.c 原型

         
       

        图1.15 Lab2A 控制软件

         

        练习2A-2 :这段代码的作用是什么?
         
        步骤4:下载并运行。建立工程,并验证工程没有错误;下载程序到Eval1,并且运行;用LED 的输出来验证操作。练习2A-3:LED 的操作和练习2 中预测的一样吗? 返回互联视图,将休眠定时器参数改为8Hz 。练习2A-4 :当休眠定时器的参数为8Hz 时,对LED 的输出有什么影响? 重新生成应用,重新建立工程,下载到Eval1 板子,并且运行。
         
        练习2A-5 :观察结果是否确认了练习2A-4 的预测?
         
        1.2.2 实验2B—待处理的中断
        步骤1:复制Lab2A。打开Lab2A。将工程保存为Lab2B。打开这个新的工程,并转到布局视图。保持当前Eval1 板上的跳线状态。重新生成应用。CPU_SCR0 是一个寄存器,当第3 位设置为高时,系统处于低功耗休眠模式。在这个模式下,禁止系统时钟。为了唤醒时钟,必须清除该位的设置。因为CPU 没有操作,因此通过定义CPU 不能清除该位。只有出现任何待处理的中断时,才能清除该位。在其中的一个INT_MSKx 寄存器中,对合适的位进行设置,将使能一个待处理的中断。当INT_MSK0 寄存器的第6 位设置为高时,使能休眠定时器中断。
         
        对于更多可读的代码,系统定义了M8C_Sleep 为(CPU_SCR0|=0x08)。这将引起系统进入休眠模式。步骤2:修改代码。转到应用程序编辑器,打开main.c 。进行下面的修改。
        —使用INT_MSK0 ,使能休眠定时器中断。
        —使用休眠命令代替代码中用于等待一个已发布中断的部分。重新建立工程,下载到Eval1 板子,并且运行。验证程序正确的工作。
         
        练习2B-1:为什么你想使用休眠模式来代替轮询已发布的休眠定时器中断?练习2B-2:为什么你想轮询,而不是将系统进入到休眠模式?
         
        1.2.3 实验2C—全局中断
        步骤1:创建新的工程。
        复制Lab2B,将其命名为Lab2C。
        所有参数和跳线连接保持一样。
        重新生成应用。
         
        可以使用两种不同的方法清除已经发布的中断。正如以前给出的那样,通过清除INT_CLR0 的第6 比特位来强迫清除。另一个方法是服务中断。最小的中断服务例程被放置在中断向量地址的“reti” 。所有这个例程将CPU 的操作返回到原来的程序。用于这个中断服务程序的术语称为“stub” (存根)。
         
        打开boot.asm ,并且验证在休眠定时器向量位置存在一个存根。
        练习2C-1:在这个向量位置有多少代码空间可以使用?
        练习2C-2:假设需要更多的空间,你将如何做?
         
        设置标志“F”寄存器的第0 比特位,使能全局中断。相反清除该位将禁止全局中断。对于更多的可读代码,系统定义了M8C_EnableGInt 为asm“or F,01h”。它使能全局中断。“asm() ”是一个函数,其允许在C 程序中嵌入汇编命令。
         
        步骤2:修改代码。
        转到应用程序编辑器中,打开main.c 。
        进行下面的修改。
        —添加代码使能全局中断。
        —删除用于清除休眠定时器中断的代码。
         
        重新建立工程,下载到Eval1,并运行。
        像前面一样验证程序。
         
        下面给出了代码的例子(也可用于Lab2C)
        #include <m8c.h> // part specific constants and macros
         #include "PSoCAPI.h" // PSoC API definitions for all User Modules
        extern unsigned char bShadow=0; void main(void)
        {
        PRT1DR=0;
        INT_MSK0|=0x40;
        M8C_EnableGInt;
        while(1)
        {
         M8C_Sleep; //sleep commandbShadow++; PRT1DR=bShadow;
        }
        }
         
        1.2.4 实验2D—汇编器中断服务例程
        步骤1:创建新的工程。复制Lab2C,将其命名为Lab2D。
         
        所有参数和跳线连接保持一样。重新生成应用。
        步骤2:修改代码。创建新的名字为SleepTimerRoutines.asm 的汇编文件。打开该文件,并按照图1.16 所示添加代码。
       

        图1.16 SleepTimer 中断服务程序

         
        需要注意这个工程中的一些条目:
         
        保存累加器的值,以后从堆栈中恢复。中断硬件只保护程序计数器和标志寄存器,这是一个中断服务程序的最小要求。其他主程序使用的寄存器也需要保护。这通常是通过将它们暂存在堆栈中实现的。
         
        bShadow 是一个在main.c 中声明的全局变量。当使用汇编语言时,必须在这个变量前加一个下划线。反之,任何一个在汇编文件中定义的全局变量,必须以下划线开头,为了让C 例程能找到它。
         
        例程以reti 结尾。—打开boot.asm 文件,在休眠定时器向量位置放置如下代码:ljmp SleepTimerISR 练习2D-1 :这个指令要求多少个字节?
        重新生成工程。
        打开boot.asm ,并且验证刚才输入的代码消失了,这是因为当每次重新生成工程时,每次都重写boot.asm 。对于这个地方的代码,必须输入到用于生成boot.asm 的模板文件。
        打开boot.tpl ,将下面的代码放到休眠定时器向量位置。
        ljmp SleepTimerISR
         
        重新生成工程。
        打开boot.asm ,验证代码现在驻留在正确的向量位置。
        打开main.c 文件,删除控制循环内的所有代码。程序始终处于这个循环,一直等到在休眠定时器中断服务程序中为休眠定时器服务为止。
        重新建立工程,下载到Eval1 板子,并运行。
        像前面一样验证程序。
         
        1.2.5 实验2E—C 语言中断服务例程
        步骤1:创建新的工程。
        复制Lab2D,将其命名为Lab2E。
        所有参数和跳线连接保持一样。
        重新生成应用。
         
        步骤2:修改代码。
        删除名字为SleepTimerRoutines.asm 的汇编文件。
        打开main.c 文件,并按照图1.17 所示添加代码。
       

        图1.17 Lab2C 控制软件

         
        需要注意这个工程中的一些条目:
         
        Pragma 允许一个函数被用做一个中断句柄。编译器将自动添加必要的代码来保护它所使用的任何寄存器。它被用做一个也添加reti。当然,这样一个函数不能接受参数和返回一个结果。
        练习2E-1:为什么?
         
        将必要的代码添加到该函数中,实现前面的汇编中断服务程序。打开boot.tpl ,转到休眠定时器向量,在SleepTimerISR 前面添加下划线。注意:对于在C 中声明的函数和变量,添加下划线。如果在C 中声明了一个变量
        CVar ,则在汇编例程中作为_iCVar 使用,在C 中作为iCVar 使用。如果_iAsmVar 在汇编语言中声明为一个变量,则它在汇编例程中作为_iASmVar 使用,在C 例程中作为iCVar 使用。iAsmVar 是一个在汇编语言中声明的变量,它可以在汇编例程中作为iASmVar 使用,但在C 中不可使用。
         
        重新生成应用,重新建立工程,下载到Eval1 板子,运行;像前面一样验证程序。
         
        1.2.6 实验2F—强迫一个中断
        步骤1:创建新的工程。复制Lab2E,将其命名为Lab2F。所有参数和跳线连接保持一样。重新生成应用。有时候,通过软件强迫产生一个中断是非常有利的。通过设置中断的INT_CLRx
        寄存器能实现这个功能。对于休眠定时器,这是INT_CLR0 的第6 位。为了保证该位不是偶然设置的,必须设置使能软件中断位(ENSWINT),该位为INT_MSK3 寄存器的第7 位。表1.4 给出了操作INT_CLRx 位的可能结果。
         
        表1.4 INT_CLRx ENSWINT 行为/结果表
                               
                                                               
                                                                        行为

                                                       
                                                               
                                                                        结果

                                                       
                                                               
                                                                        从INT_CLRx

                                                       
                                                               
                                                                        位读一个0

                                                       
                                                               
                                                                        从INT_CLRx

                                                       
                                                               
                                                                        位读一个1

                                                       
                                                               
                                                                        当ENSWINT=0,写0

                                                       
                                                               
                                                                        到INT_CLRx

                                                       
                                                               
                                                                        当ENSWINT=0,写1

                                                       
                                                               
                                                                        到INT_CLRx

                                                       
                                                               
                                                                        当ENSWINT=1,写0

                                                       
                                                               
                                                                        到INT_CLRx

                                                       
                                                               
                                                                        当ENSWINT=1,写1

                                                       
                                                               
                                                                        到INT_CLRx

                                                       
                                                                         
                       
         
        练习2F-1:在前面的实验中,没有通过添加代码设置ENSWINT 为0 来清除已经发布的中断,为什么这样做?
         
        步骤2:修改代码。
        添加代码使能ENSWINT。添加控制循环代码强制休眠定时器发布一个中断。
         
        练习2F-2:现在,这个程序如何工作?重新生成工程,重新建立工程,下载到Eval1 板子,运行。练习2F-3:现在操作是否和你的预测一样?
         
        1.2.7 实验2G—创建非常小的中断服务例程
        步骤1:创建新的工程。
        复制Lab2F,将其命名为Lab2G。设置Sleep_Timer 全局参数为64Hz 。
        所有其他参数和跳线连接保持一样。有时候,中断服务程序是很小的,这样它就能驻留在用于它的输入向量的4 个字节空间。
         
        步骤2:修改代码。删除main.c 中的中断句柄。创建全局单字节变量bCount 。删除使能ENSWINT 的代码。
        删除强制一个中断的代码。
        打开boot.tpl ,添加汇编代码到休眠定时器中断向量位置,用于减这个新的变量
        (确保保留reti)。练习2G-1 :这个中断句柄占用多少个字节?
         
        在控制循环中添加代码:
        — 打开所有的四个灯。
        —设置bCount 为255 。
        —等待bCount 为0。
        —关闭LED4 。
        —设置bCount 为192 。
        —等待bCount 为0。
        —关闭LED3 。
        —设置bCount 为128 。
        —等待bCount 为0。
        —关闭LED2 。
        —设置bCount 为64。
        —等待bCount 为0。
        —关闭LED1 。
        —设置bCount 为32。
        —等待bCount 为0。练习2G-2 :输出行为将如何?重新生成应用程序,重新建立工程,下载到Eval1 板子,并运行。练习2G-3 :真正的操作和预测的一样吗?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2024-11-23 21:16 , 耗时 0.096091 秒, 18 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表