软件编程方法及技巧

本文主要介绍TIMSP430微控制器软件编程设计中的实践经验和应用技巧 。
第一部分讲述基于中断的标准程序流程模式, 适用于大多数的产品应用编程;另外一部分讲述MSP430微控制器编程人员在开发产品时需要注意的一些关键问题、重要方法与注意事项, 如:程序初始化流程, 晶振初始化时的注意事项等, 利用这些方法可以极大程度地减少产品的开发周期和提高产品的稳定性 。
1.MSP430微控制器标准软件设计流程MSP430微控制器软件设计的标准流程均可参考图1 。 该标准的软件流程可将系统整体功耗降至最低 。
 

软件编程方法及技巧

文章插图

图1
图1所描述的软件流程代码是基于中断程序的, 平时MCU处于睡眠状态, 直到有中断产生时MCU被唤醒, 最大程度降低系统功耗, 优化电源效率 。
理解图1所示的中断服务子程序(1SRs)流程, 能更好的掌握MSP430微控制器处理低功耗的模式 。 MSP430微控制器的低功耗模式由状态寄存器SR的控制位控制, 在执行中断服务子程序之前, 状态寄存器SR的低功耗模式控制位可以被优先压栈 。 当中断服务子程序返回时, 主程序调用中断之前的低功耗模式控制位, 从而进入中断之前的低功耗模式状态 。 当然, 如果我们在ISR中断服务子程序返回前修改了保存在SR中的低功耗模式控制位, 那么ISR中断子程序执行完之后, 主程序流程可以转到另一个不同的低功耗工作模式 。
中断唤醒机制作为MSP430微控制器内部低功耗模式的一部分, 允许系统快速唤醒, 响应中断事件 。 例如, 当一中断事件发生之前MSP430微控制器处于低功耗LPM0模式, MCU在执行中断服务子程序之前首先向堆栈保存SR中的低功耗模式控制位值然后清除SR值, 清除SR值使MCU从LPMO模式进入到执行中断活动模式状态 。 在ISR中断服务子程序中, 软件设计者可以写一条语句清除SR中的低功耗模式控制位, 当中断程序完成后, MCU从堆栈中重新装载调用各自寄存器的状态值 。 如果没有修改SR的低功耗模式控制位, 退出中断后系统仍然返回进入LPM0低功耗模式, 若此时已修改SR控制位, 当从ISR中断程序退出后, 系统会工作于活动模式时, 并且按进入中断之前的PC指针所指的地址继续执行程序 。
由于可以在fSR中断服务子程序中改变低功耗模式, 所以设计者可以选择在ISR程序中执行全部任务, 也可以选择在ISR唤醒MCU后在主程序中处理任务 。
在ISR程序中处理时确保能立即响应中断事件, 中断事件发生时即能立刻处理中断任务, 但是, 在处理一个中断事件时, 其它中断将不能被载入, 直到该中断任务完成, 而这样长时间的中断将会降低系统的响应灵敏, 所以设计者须根据不同系统要求选择最佳处理方式 。
图1所示的流程图中主程序需处理两个中断事件, 这两个中断事件所要处理的任务是在主循环中处理的 。 ISRs执行两个不同的事件任务 。 第一个中断, ISRs改变了保存在堆栈中SR的值, 可以使系统退出中断后进入活动工作模式, 中断事件是在主程序中被执行, 中断事件可以是一任意应用事件, 例如定时器、按键处理、AD转换等 。 第二个中断, 在ISR中断服务子程序设置一标志位, 在主程序检测该标志位来判断是否执行相应的任务 。 如果需处理的中断事件能在较短的时间内迅速完成, 这样就能够在中断服务子程序中直接执行, 无需进入主程序处理, 此时ISR中断服务子程序没必要设置标志位或改变SR低功耗控制位退出睡眠模式, 退出ISR中断服务子程序后MCU仍然返回到睡眠模式 。 该流程可以根据系统应用的复杂性来定, 例如, 只有一个中断事一件可唤醒主程序时, 则无需设置系统标志位, 此时, 通过中断唤醒主程序, 然后主程序进行相应的任务操作, 最后MCU重新进入睡眠模式 。
图1中所提到的睡眠模式LPMn是系统所要用到的睡眠低功耗模式, 每种应用所涉及的模式可能会有所不同, 实际的睡眠模式由整个系统所用到的模块(如定时器、AD、串口等)决定, 取决于系统模块在相应的睡眠模式下可否被中断唤醒 。 例如由MCU的定时器负责唤醒CPU, 且该定时器时钟为ACLK时, 则ACLK必须保持活动模式, 则MCU可以工作在LPM3模式;但是如果定时器时钟为DCO时, 则MCU必须工作在LPMO 。
2方案设计技巧2.1看门狗和晶振的配置在任何一款MSP430微控制器中, 看门狗默认开启32ms复位, 所以程序初始化第一步应先进行看门狗WDT的配置 。 如果在初始化中不快速处理WDT的话, 则看门狗可能很快溢出造成芯片程序复位 。 为避免CPU进入复位死循环, 所以看门狗需在程序最开始配置, 通过设置时间、设置控制位或者关闭看门狗 。
MSP430F4xx或MSP430F2xx微控制器中, 使用LFXT1低频率晶振时, 代码运行之前需通过FLL_CTL0寄存器配置晶振相应的负载电容, 否则晶振可能会运行不正常, 该技巧在许多TI的MSP430微控制器应用实例代码中均可见 。
2.2使用TI的标准头文件
TJ为每一款MSP430微控制器均提供~标准头文件, 文件中包含相应芯片型号中的所有寄存器和位常数定义信息, 使用文件中定义的信息能极大地提高程序的可读性, 同时增加系统可移植性, 使其它设计者能快速掌握该程序的设计 。 TI的每~个应用方案和代码实例都可以应用这些头文件 。
2.3运用内部函数处理低功耗模式和其它函数
      MSP430微控制器利用C语言开发软件时, 可以直接调用编译器包含的几个内部函数 。 有时一些关键事件的处理唯一方法就是使用内部函数, 利用内部函数会很大程度地提高任务处理的效率 。
使用内部函数最普通的例子就是进入与退出低功耗模式, 通常用C语言时必须对CPU寄存器中的某些位进行操作, 例如在IAR编译环境中如果需要进入LPM3模式, 则即可直接使用内部函数:
BISSR(LPM3_bits+GIE) 。
其它内部函数有时也具有优化功能, 例如MSP430微控制器转换BCD码的内部指令函数, 如果没有这些指令组合, 则需要一长串C语言代码完成, 且编辑器不能直接将代码转换成MSP430微控制器识别的BCD数学指令 。 使用内部函数使得利用C语言编程的人员最大程度地优化了程序代码, 也降低了系统功耗 。
MSP430微控制器的开发环境编译器包含一系列功能函数, 开发设计时需注意最新版本 。
2.4晶振失效的处理函数
MSP430微控制器具有检查时钟是否失效的功能 。 所有的微控制器系列提供内部DCO和高频频晶振的失效检测功能, MSP430F4xx和MSP430F2xx系列具有全部时钟失效检测的功能, 如:外部32768Hz低频时钟与高频时钟失效检测 。
具体细节可参考用户手册 。
本文主要考虑两种会出现晶振失效的情况以及考虑是否需要做出相应的处理 。
(1)在每一次MCU上电时晶振稳定的过程 。 在这个过程中会造成晶振的失效, 特别对于低频晶振初始化, 时钟稳定需要一定时间, 经常是几千毫秒 。
(2)在程序运行过程中出现晶振失效, 比如某种导体将晶振管脚短路, 因此需要一些特殊的方法处理, 当晶振失效时, DC0时钟模块将继续支持CPU的工作 。
如果时钟源ACLK、SMCLK或者晶振未稳定时, 任何使用这些时钟的外围设备都将受到影响, 唯一方法即是通过软件进行检测与处理 。 当一些对时间敏感的外围(如定时器)以低频晶振为时钟源, 若晶振未振荡稳定时, 将导致初始化失败, 同时若程序代码未等到晶振稳定就开始工作, 则外设输出的结果是不可预知的 。
如果由LFXT1、LT×T2提供系统的MCLK时钟源, 晶振失效了, 则MCLK时钟源会自动切换到内部DCO时钟模块, 由内部的DCO做为MCLK时钟源 。
处理晶振初始化的一个简单方法就是可以不停重复清零、等待检测默认的晶振失效标志位, 直到晶振失效标志不在置位, 可参考用户手册 。 如MSP430F:2xx系列, LF×T1的低频晶振并不能检测晶振是否失败, 此时可调用一延时程序以保证有足够的初始化稳定时间 。 这种方法在一般程序正常操作过程中并不能捕获到晶振是否失效, 但可以通过设置OFIE位在NMI中断服务子程序中处理 。
2.5逐渐增加MCLK频率
大多数MSP430微控制器的MCLK可以配置为8MHz, MSP430F2xx可以达到16MHz, 系统要求VCC电压值随着频率的升高相应有所增加 。 程序运行时, 若设定MCLK频率所需的VCC电压比真正提供给微控制器的电压值高, 则运行过程中将发生不可预知的问题 。
即使MCU实际工作VCC值比工作频率需要的实际工作电压高出很多, 但VCC上升到稳定状态是需要一定时间的, 所以我们要在工作频率升高之前确保芯片电压已经能够支持晶振正常工作 。
如果MCU具备SVS(电压检测模块)模块, 则SVS可以提醒系统的VCC电压达到所需的电压值;若MCU不具备SVS模块, 但是含有可利用的ADC模块, 则ADC模块可以采样VCC电压, 从而判断在提升频率之前芯片电压值是否能满足高频工作要求 。
2.6使用初始化函数
通常在C编译器编写代码时, 程序会自动初始化所有定义的存储器, 并且将代码值插入到main()主程序中 。 如果定义的存储器很多(大量变量), 则将导致看门狗的溢出问题 。 当初始化许多变量时, 占用的时间相应就会很长, 以至于在执行main()主程序第一条语句之前看门狗已经溢出, 那么将导致死循环的产生
。 这种现象一般会发生在微控制器的RAM超过2K的情况 。
为避免上述情况的发生, 最简单、直接的方法就是对不需要最先初始化的变量在最开始时不进行初始化设置 。 例如使用IAR时, 用一句长代码矩阵语句_no_init_intx_arrav[2500]替代一长串的初始化代码, 避免看门狗溢出 。
除上述方法外, 设计者还可以定义初始化函数处理看门狗的溢出问题 。 RAM存储器仍然被初始化, 但是首先配置看门狗 。 在IAR环境中, 我们通常可以在看门狗配置代码中增加一段_low_level_init()代码, 例如:
【软件编程方法及技巧】 void_low_level_init(){WDTCTL=WDTPW+WDTHOLD]
如果上述初始化函数在开发环境中也不可用, 那么可以修改在每一个C程序之前的启动文件 。 当初始化MSP430F4xx系列的大量初始化代码时, 可以在初始化或启动文件中配置LF×T1晶振电容, 这样即可在主程序开始执行之前提供给晶振所需要的更多起振时间, 使晶振稳定, 参考2.1节 。
2.7 支持在线编程(ISP)
如果使用MSP430微控制器的ISP功能对FALSH存储器进行擦写操作, 为确保正确读写正常, 需注意以下几点:
(1)设置正确的FLASH擦写时频率Fftg值, 否则烧写的结果是不可预知的 。
(2)当ISP操作完成后设置FALSH锁定位, 防止意外的程序干扰写入 。
(3)注意FALSH模块的累积编程时间 。
(4)提供足够的VCC电压, FLASH烧写电压VCC值必须比数据手册中最小的烧录/擦除电压大, 比CPU工作电压要求略高 。
在进行FLASH烧录时, 可能在上电过程中会受到电压的干扰, 也可能在供电电池电压不足(但是还可以维持CPU工作时)时受到干扰, 甚至当初始电压足够高, 但是当开始进行FLASH擦写电流消耗较大, 将电压拉下使其小于最小阈值电压 。
VCC电压可以通过SVS或ADC模块校验 。 SVS模块优势在于在操作过程中可以提供连续检测, 在进行FLASH擦写之前如何配置SVS模块监测VCC电压可参考2.5讲述的mclk.c程序 。
2.8使用校验和功能校验Flash的完整性
在一些关键性的应用方案中, 周期性地执行校验和功能可以确保FLASH存储器的完整性 。 根据冗余数据的需要, 校验值可以存储一个或多个存储器内, 同时校验值提供的的校验图表可以作为处理错误发生进行处理的依据 。
3结束语
本文所讲述的MSP430微控制器的编程方法与编程过程中的注意事项是作者多年在MSP430开发产品过程中的一些经验之谈, 遵循这些原则可大大提高产品的可靠性 。