采用MAXQ610评估套件(EV kit)和IAR嵌入式工作台进行设计
摘要:应用笔记介绍怎样面向MAXQ610低功耗RISC微控制器开发、构建并调试应用程序。文章使用了IAR™系统公司提供的IAR Embedded Workbench®工具箱和C编译器。
引言
MAXQ610是Maxim Integrated Products提供的低功耗微控制器,设计用于电池供电的应用,提供低电流工作模式(1MHz时的典型值为1.4mA,12MHz时为3.5mA),以及低电流停止模式(典型值200nA)。微控制器还具有效率非常高的16位单周期RISC处理器核以及灵活的时钟配置,有助于动态控制性能和功耗。MAXQ610适合于需要大量I/O引脚以及对功耗要求比较高的应用。
MAXQ610具有很多重要的特性,包括:
- 1.7V至3.6V的宽范围工作电压
- 64KB应用程序(IAP)闪存
- 2KB数据SRAM
- SPI™和两个USART
- 8kHz低功耗“异或”唤醒定时器
- IR载频发生器和调制
- 扰码功能可防止攻击者下载软件,提供IP保护
- 存储器保护功能隔离了内核库,提供IP保护,防止第三方应用
MAXQ610评估套件(EV)为MAXQ610处理器开发低功耗应用提供成熟可靠的平台。套件包括IR发射器和接收器;两个串口;用于用户输入的8个按键;出于应用目的的4个LED;原型区;以及用于访问MAXQ610所有I/O引脚的插头等。此外,还提供跳线,可以方便地监监MAXQ610处理器在工作时的实际功耗。
设置MAXQ610评估套件
MAXQ610评估套件电路板如图1所示。评估套件含有下面的硬件元件,这些元件用于实现并验证本应用笔记中的演示程序:
更详细的图(PDF, 284kB)
图1. MAXQ610评估套件
MAXQ610评估套件电路板和JTAG电路板都有很多跳线需要进行配置。在本应用笔记中,应按照表1和表2配置这些跳线。
表1. MAXQ610评估套件的电路板跳线配置
Jumper(s) | State | Purpose |
JH1, JH2 | Don't Care | Control RS-232 level shifters FORCEON and active-low FORCEOFF inputs |
JH3, JH4 | Don't Care | Configure RS-232 transmitter inputs |
JH20, JH21 | Don't Care | Connect RS-232 receiver outputs to MAXQ610 signals |
JH18 | Don't Care | Connect RS-232 active-low INVALID input to MAXQ610 control pin |
JH5 | Connect Pins 1 (Square Pad) and 2 | Connects regulated voltage to MAXQ610 supply |
JH22, JH23, JH24, JH25 | Closed | Connects MAXQ610 port pins to LEDs |
JH15, JH16, JH17 | Don't Care | Connect IR circuitry to MAXQ610 pins |
JH26 | Closed | Uses power from JTAG connection to power the MAXQ610 board |
JH14 | Closed | Connects board power to MAXQ610 |
表2. JTAG电路板跳线配置
Jumper(s) | State | Purpose |
JH1, JH2 | Don't Care | External DTR used to control loading the on-board microcontroller. |
JH3 | Closed | Connects JTAG board's 5.0V supply to JTAG connector pin 8 (feeds target board). |
用JTAG电缆连接JTAG电路板和MAXQ610评估套件电路板。电缆上的红条应连接至JTAG电路板上标有引脚9和引脚10的连接器一侧,以及MAXQ610评估套件电路板上标有TDI-GND的连接器一侧。
用9针串行电缆连接PC和JTAG电路板(不要将其连接至MAXQ610评估套件电路板)。最后,将5V电源连接至JTAG电路板的电源连接器。
采用IAR编译器开始设计:blinker
我们不以“Hello World”开始,而是构建一个简单的应用程序,该应用程序使MAXQ610评估套件电路板上的4个LED闪烁(例如,DS1、DS2、DS3和DS4)。我们要使用的工具包是IAR嵌入式工作台,由IAR系统公司提供。本应用笔记的软件采用IAR系统公司2.12版KickStart试验包来编写并进行了测试。
在开始一个新工程之前,需要将一些MAXQ610特殊文件复制到IAR安装目录(通常是C:\Program Files\IAR Systems\Embedded Workbench 4.0,下面将其称为[IAR])中。网上提供本应用笔记的文件(请参考文档最后的了解详细信息一节),评估套件的CD-ROM也提供这些文件。请复制这里提到的这些文件:
- 将
iomaxq610.h
复制到[IAR]\MAXQ\inc
- 将
lnkmaxq610.xcl
复制到[IAR]\MAXQ\config
- 将
maxq610.sfr
复制到[IAR]\MAXQ\config
- 将
maxq610.ddf
复制到[IAR]\MAXQ\config
- 将
maxq610.menu
复制到[IAR]\MAXQ\config\devices
现在启动IAR嵌入式工作台。选择“Create new project in current workspace” (图2)。选择MAXQ®工具链,确定选择了“Empty project” (图3)。单击OK,打开一个文件对话框。在这个例子中,工程文件名为“blinker” (图4)。
图2. 工作台启动
图3. 建立一个空的工程
图4. 如图所示,保存工程“blinker”
工作空间将显示“blinker”工程。现在,建立一个新文件(File New File),将以下文本复制到该文件中。
#include#include void main() { /* * Try to get a 1Hz blink on the LEDs. System clock = 12MHz. * Timer reload = 0x5B8D = 23437. Running at div 256, so we get a timer * interrupt once every 23437*256 cycles = 5,999,872, or roughly 500ms. * We toggle every 500ms, so we get a 1Hz cycle. */ TB0R = 0x5B8D; // reload for timer 0 TB0CN = 0x0416; // timer set to run, enable interrupt, down count, div 256 PD3 = 0x0f; // set port 2 lower nibble to output IC_bit.IGE = 1; // set global interrupt enable while (1) { } }
在这个简单的应用程序中,采用一个定时器中断来启动使评估套件LED不断接通和关断的代码。要重新装入的值在定时器寄存器中断时自动装入该寄存器,大约每500ms周期性中断一次。设置定时器运行之后,将连接LED的端口引脚配置为输出,然后,全局使能中断。应用程序进入无限while循环。中断服务例程(ISR)代码完成应用程序(请参见下面图5)。
单击save,将文件命名为main.c
(确定代码保存目录与您建立新工程的目录相同)。在工作窗口下,右键单击“blinker”,选择Add Add main.c
。
下一步,将另外两个文件从软件分配源复制到您的工程目录中:isr.c
和clib.r66
。C文件含有中断部分,编译器需要利用它来编译程序。r66文件含有应用程序运行需要的启动代码和标准库代码。每次开始新的MAXQ610工程时,都需要重复这一复制步骤。
再次右键单击工作窗口中的“blinker”行,找到Add Add Files,选择isr.c
。
现在,需要配置工程选项。选择Project Options,打开选项窗口。请按照以下步骤进行:
- 在General选项下:Target,选择MAXQ610。
- 在General选项下:Library Configuration,从下拉菜单中选择Custom CLIB。浏览Library File文本区,选择刚刚复制到工程目录中的
clib.r66
文件。 - 在Debugger下:Setup,从driver下拉菜单中选择JTAG。
- 在JTAG下:输入您将使用的连接JTAG电路板的串口。
现在,构建应用程序就非常简单了。按下F7或者选择Project Make。您首先会被询问保存工作空间。对此,请输入“gettingstarted”。工程应该被正确构建。
如果您希望在此处运行应用程序(例如,Project Debug,然后单击右箭头按钮),电路板上不会有任何事情发生。这是因为应用程序代码试图使用定时器中断来确定LED什么时候应该改变,而定时器的ISR中没有代码。因此,必须为定时器(ISR)编写代码。
打开文件isr.c
,找到函数isr6(void)
,在它旁边应该有注释//timers
。在函数中输入以下代码:
TB0CN = TB0CN & 0xFF7F; // clear timer 0 interrupt PO3 = PO3 ^ 0x0f; // toggle lower nibble
这些代码首先清除定时器中断标志(必须由软件清除中断标志,否则,将导致中断矢量不断启动)。第二行触发所有4个LED,这些LED连接到端口引脚P3.0至P3.3。
现在开始构建工程,进行调试(Project Debug把您带到执行C代码的第一行,如图5所示)。代码第一行下面高亮显示,左侧空白区有一个箭头,指示程序在此暂停。现在,单击Run按钮(图6)。该按钮使程序运行至结束(或者到下一个断点)。当程序执行无限循环时,LED块在一直闪烁。
图5. 程序在代码第一行暂停
图6. 程序Run按钮
使用IAR嵌入式工作台调试应用程序
现在,我们看一下MAXQ610和嵌入式工作台工具的调试功能。MAXQ610处理器有内置JTAG引擎,支持在实际芯片中进行调试。这一特性还避免了使用昂贵的vwin
器或者有可能出错的仿真器。
返回到最初的blinker应用程序,开始上面介绍的调试过程。第一行高亮显示后,点击Go按钮,继续执行。您将看到LED接通500ms,然后关断500ms。
单击Break按钮,或者选择Debug Break,暂停执行(图7)。程序应暂停在while(1)
声明上,这是因为该声明占用了无限循环的大部分运行时间,而中断矢量只占用了很少的时间(每500ms只有几个周期)。
图7. Break按钮
在检查一些处理器寄存器中的数值时,打开寄存器窗口(View Register)。此处,从下拉菜单中选择Timer 0,您将看到与定时器控制闪烁LED相关的寄存器(图8)。这里显示的Timer 0寄存器包括重装寄存器(TB0R),控制寄存器(TB0CN),计数寄存器(TB0C)和数值寄存器(TB0V)。
图8. Register窗口显示Timer 0寄存器
作为演示,我们将执行几行代码,观察这些定时器寄存器会有什么变化。按下Step Over按钮几次(图9),或者选择Debug Step Over。观察TB0V中的数值。Step Over按钮执行一行C代码,但是不会进入任何函数调用。该按钮按下时,您将看到TB0V中的数值变化范围很大,这是因为调试引擎执行时,定时器在不断运行。您还将看到,TB0CN寄存器随着定时器中断出现和结束的变化。
图9. Step Over按钮
寄存器窗口不但显示了寄存器内容,而且,在调试进程中,还可以向其写入数值。程序暂停时,双击TB0R寄存器中的数值。将寄存器改为0x2DC6
(这是0x5B8C/2
),然后,单击Go按钮。LED现在闪烁应比以前快两倍,这是因为定时器重新装入的计数值减小了,从而减小了定时器中断之间的时间。
在另一个演示中,我们把光闪烁模式由全通/全关(1111 0000 1111
)改为交替模式(1010 0101 1010
)。而这种改变并不需要重新编译程序。首先,我们必须加入一个断点。程序运行时,打开isr.c
文件,找到定时器中断矢量。双击代码第一行左侧的灰色区,将出现一个红色X。这一X表示加入了一个断点。当程序执行到这一行代码时,程序将停止,其屏幕显示如图10所示。绿色箭头和高亮显示的代码表示已经到达断点,程序暂停在这里。
图10. 断点设置和到达断点
在寄存器窗口中,从下拉列表中选择Port I/O。注意,代码使用了XOR (^)运算符来触发端口3 (P3)最下面的4个引脚,而这些引脚从未明确设置。为改变这一操作,单击PO3中的数值,输入新值0x05
。输入后,您将看到,按照0101的模式,2个LED接通,2个LED关断。现在,单击Run。程序开始运行,直至到达断点而再次停止,LED将转换状态,因此,处理器现在输出1010
模式。双击红色X,清除断点,然后,单击Go。程序将以交替LED模式不断运行。
在IAR嵌入式工作台中,您可以按照与寄存器一样的方法来观察并改变变量值。对此进行演示时,单击Stop或者选择Debug Stop Debugging,停止应用程序。现在,修改代码,在主函数中加入变量x,在while循环中嵌入延时循环。如下所示,输入对程序的一些修改。注意,在代码中故意设置了错误,稍后对它进行讨论。
void main() { /* * Try to get a 1Hz blink on the LEDs. System clock = 12MHz. * Timer reload = 0x5B8D = 23437. Running at div 256, so we get a timer * interrupt once every 23437*256 cycles = 5,999,872, or roughly 500ms. * We toggle every 500ms, so we get a 1Hz cycle. */ long int x; TB0R = 0x5B8D; // reload for timer 0 TB0CN = 0x0416; // timer set to run, enable interrupt, down count, div 256 PD3 = 0x0f; // set port 2 lower nibble to output IC_bit.IGE = 1; // set global interrupt enable while (1) { for (x=0;x<100000;x++) { if (x==100000) PO3 = PO3 ^ 0x01; } } }
这些改变用于偶尔触发端口3最下面一个引脚,因此,3个LED同步闪烁,而1个将独立闪烁。延时循环间隔并不重要,但是必须提供足够的延时才能观察到结果。运行该应用程序(开始调试,然后,运行),您将很快看到和最初的应用程序并没有什么不同;所有LED以1秒的间隔同时接通和关断。暂停应用程序,打开本地变量观察窗口(View Locals)。如果程序停在主应用程序的while循环(很有可能)中,窗口中将显示变量x (图11)。
前面曾提到上面的代码中有错误。现在,按下Step Over按钮几次,您将看到执行从循环对比(x<100000
)跳到条件测试“if”声明(x ==100000
),直到递增(x++
),然后是本地窗口中x值的变化。在PO3 = PO3 ^ 0x01
99999
,单击Step Over几次。您将注意到,由于x=0
部分被执行,“for”循环终止,然后再次开始。问题很明显—x值永远不会到达“for”循环中的100000,这是因为进行了“less than”测试。停止程序,将“if”声明中的对比值改为99999
。重新编译程序,启动调试器,单击Go。LED开始闪烁,LED DS1自己独立闪烁。
图11. 本地变量窗口
评论
查看更多