<font color=#0000FF>Stellaris系列单片机在晶振被拔去后能够自动切换到内部振荡器,继续工作,不会死机!</font><br /><br /> Luminary公司的Stellaris系列单片机拥有3个时钟验证电路,该电路使用定时器通过一个慢速时钟来检验快速时钟:<br /> ● 主振荡器检验PLL<br /> ● 主振荡器检验内部振荡器<br /> ● 内部振荡器除以64检验主振荡器<br /><br /> 其中,PLL和内部振荡器都在芯片内部,是完全可靠的,实际上没有必要对其进行检测。但是主振荡器外接的晶体可能会偶然失效。时钟验证电路能够自动检测出晶体失效,会使系统时钟自动切换到工作时钟,并向控制器发出中断。在中断里可以采取某种对策。<br /><br /> 以下是一个演示程序。<br /><br /> 在程序运行后,配置为主振荡器MOSC+外部6MHz晶体,并使能MOSC失效检测功能,在主循环里工作指示灯WORK_LED慢速闪烁。<br /> 当拔去晶体时,会自动检测到MOSC失效,并触发中断。在中断里,系统时钟改为内部12MHz的振荡器IOSC,并点亮错误指示灯ERROR_LED,随后退出中断。<br /> 在退出中断后,我们发现LED快速闪烁,速度大约是原来的2倍。<br /><br /> 由此可见,<font color=#0000FF>在Stellaris系列单片机里,正在工作的晶体即使被突然拔去,也不会造成死机,芯片可以自动切换到内部振荡器继续工作!</font><br /><br /><br />#include "hw_types.h"<br />#include "hw_memmap.h"<br />#include "hw_ints.h"<br />#include "hw_sysctl.h"<br />#include "hw_gpio.h"<br />#include "src/interrupt.h"<br />#include "src/sysctl.h"<br />#include "src/gpio.h"<br /><br />// 将较长的标识符定义为较短的形式<br />#define SysCtlPeriphEn SysCtlPeripheralEnable<br />#define SysCtlMOSCVeriSet SysCtlMOSCVerificationSet<br />#define GPIOPinTypeIn GPIOPinTypeGPIOInput<br />#define GPIOPinTypeOut GPIOPinTypeGPIOOutput<br /><br />// 定义LED指示灯,均为低电平点亮<br />#define WORK_LED GPIO_PORTB_BASE, GPIO_PIN_0<br />#define ERROR_LED GPIO_PORTB_BASE, GPIO_PIN_1<br /><br />// 定义LED操作宏<br />#define WorkLedOn() GPIOPinWrite(WORK_LED, 0x00)<br />#define WorkLedOff() GPIOPinWrite(WORK_LED, 0x01)<br />#define ErrorLedOn() GPIOPinWrite(ERROR_LED, 0x00)<br />#define ErrorLedOff() GPIOPinWrite(ERROR_LED, 0x02)<br /><br />// LED初始化<br />void LedInit(void)<br />{<br /> SysCtlPeriphEn(SYSCTL_PERIPH_GPIOB); // 使能GPIOB端口<br /> GPIOPinTypeOut(WORK_LED); // 设置WORK_LED所在管脚为输出<br /> GPIOPinTypeOut(ERROR_LED); // 设置WORK_LED在管脚为输出<br /> WorkLedOff(); // 初始化时熄灭WORK_LED<br /> ErrorLedOff(); // 初始化时熄灭ERROR_LED<br />}<br /><br />// 时钟初始化<br />void ClockInit(void)<br />{<br /> SysCtlClockSet(SYSCTL_USE_OSC | // 采用MOSC+6MHz晶体<br /> SYSCTL_OSC_MAIN |<br /> SYSCTL_XTAL_6MHZ);<br /> SysCtlMOSCVeriSet(true); // 使能IOSC/64验证MOSC功能<br /> SysCtlIntEnable(SYSCTL_INT_MOSC_FAIL); // 使能MOSC失效中断<br /> IntEnable(INT_SYSCTL); // 使能系统控制中断<br /> IntMasterEnable(); // 使能处理器中断<br />}<br /><br />// 延时<br />void TimeDelay(unsigned long ulVal)<br />{<br /> do {<br /> } while ( --ulVal != 0 );<br />}<br /><br />// 主函数<br />int main(void)<br />{<br /> // 初始化<br /> LedInit();<br /> ClockInit();<br /><br /> // 在6MHz晶体下LED闪烁发光,若拔去晶体,自动改用12MHz的IOSC,闪烁加快<br /> for (;;) {<br /> WorkLedOn();<br /> TimeDelay(400000UL);<br /> WorkLedOff();<br /> TimeDelay(400000UL);<br /> }<br />}<br /><br />// 系统控制中断服务函数<br />void System_Control_ISR(void)<br />{<br /> SysCtlClockSet(SYSCTL_USE_OSC | SYSCTL_OSC_INT); // 改用IOSC<br /> SysCtlMOSCVeriSet(false); // 禁止IOSC/64验证MOSC功能<br /> SysCtlIntClear(SYSCTL_INT_MOSC_FAIL); // 清除MOSC失效中断<br /> ErrorLedOn(); // 点亮错误指示灯<br />}<br /> |
|