[ZLG-MCU] Stellaris系列单片机在晶振被拔去后还能工作,不会死机!

[复制链接]
 楼主| zlgmcu 发表于 2007-12-26 17:21 | 显示全部楼层 |阅读模式
<font color=#0000FF>Stellaris系列单片机在晶振被拔去后能够自动切换到内部振荡器,继续工作,不会死机!</font><br /><br />  Luminary公司的Stellaris系列单片机拥有3个时钟验证电路,该电路使用定时器通过一个慢速时钟来检验快速时钟:<br />    ●&nbsp;主振荡器检验PLL<br />    ●&nbsp;主振荡器检验内部振荡器<br />    ●&nbsp;内部振荡器除以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&nbsp;&nbsp;&quot;hw_types.h&quot;<br />#include&nbsp;&nbsp;&quot;hw_memmap.h&quot;<br />#include&nbsp;&nbsp;&quot;hw_ints.h&quot;<br />#include&nbsp;&nbsp;&quot;hw_sysctl.h&quot;<br />#include&nbsp;&nbsp;&quot;hw_gpio.h&quot;<br />#include&nbsp;&nbsp;&quot;src/interrupt.h&quot;<br />#include&nbsp;&nbsp;&quot;src/sysctl.h&quot;<br />#include&nbsp;&nbsp;&quot;src/gpio.h&quot;<br /><br />//&nbsp;将较长的标识符定义为较短的形式<br />#define&nbsp;&nbsp;SysCtlPeriphEn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SysCtlPeripheralEnable<br />#define&nbsp;&nbsp;SysCtlMOSCVeriSet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SysCtlMOSCVerificationSet<br />#define&nbsp;&nbsp;GPIOPinTypeIn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinTypeGPIOInput<br />#define&nbsp;&nbsp;GPIOPinTypeOut&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinTypeGPIOOutput<br /><br />//&nbsp;定义LED指示灯,均为低电平点亮<br />#define&nbsp;&nbsp;WORK_LED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIO_PORTB_BASE,&nbsp;GPIO_PIN_0<br />#define&nbsp;&nbsp;ERROR_LED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIO_PORTB_BASE,&nbsp;GPIO_PIN_1<br /><br />//&nbsp;定义LED操作宏<br />#define&nbsp;&nbsp;WorkLedOn()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinWrite(WORK_LED,&nbsp;0x00)<br />#define&nbsp;&nbsp;WorkLedOff()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinWrite(WORK_LED,&nbsp;0x01)<br />#define&nbsp;&nbsp;ErrorLedOn()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinWrite(ERROR_LED,&nbsp;0x00)<br />#define&nbsp;&nbsp;ErrorLedOff()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinWrite(ERROR_LED,&nbsp;0x02)<br /><br />//&nbsp;LED初始化<br />void&nbsp;&nbsp;LedInit(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlPeriphEn(SYSCTL_PERIPH_GPIOB);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;使能GPIOB端口<br />&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinTypeOut(WORK_LED);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置WORK_LED所在管脚为输出<br />&nbsp;&nbsp;&nbsp;&nbsp;GPIOPinTypeOut(ERROR_LED);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;设置WORK_LED在管脚为输出<br />&nbsp;&nbsp;&nbsp;&nbsp;WorkLedOff();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;初始化时熄灭WORK_LED<br />&nbsp;&nbsp;&nbsp;&nbsp;ErrorLedOff();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;初始化时熄灭ERROR_LED<br />}<br /><br />//&nbsp;时钟初始化<br />void&nbsp;&nbsp;ClockInit(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlClockSet(SYSCTL_USE_OSC&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;采用MOSC+6MHz晶体<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYSCTL_OSC_MAIN&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYSCTL_XTAL_6MHZ);<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlMOSCVeriSet(true);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;使能IOSC/64验证MOSC功能<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlIntEnable(SYSCTL_INT_MOSC_FAIL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;使能MOSC失效中断<br />&nbsp;&nbsp;&nbsp;&nbsp;IntEnable(INT_SYSCTL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;使能系统控制中断<br />&nbsp;&nbsp;&nbsp;&nbsp;IntMasterEnable();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;使能处理器中断<br />}<br /><br />//&nbsp;延时<br />void&nbsp;&nbsp;TimeDelay(unsigned&nbsp;long&nbsp;&nbsp;ulVal)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;do&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;while&nbsp;(&nbsp;--ulVal&nbsp;!=&nbsp;0&nbsp;);<br />}<br /><br />//&nbsp;主函数<br />int&nbsp;&nbsp;main(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;初始化<br />&nbsp;&nbsp;&nbsp;&nbsp;LedInit();<br />&nbsp;&nbsp;&nbsp;&nbsp;ClockInit();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;在6MHz晶体下LED闪烁发光,若拔去晶体,自动改用12MHz的IOSC,闪烁加快<br />&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(;;)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkLedOn();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeDelay(400000UL);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkLedOff();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeDelay(400000UL);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />//&nbsp;系统控制中断服务函数<br />void&nbsp;&nbsp;System_Control_ISR(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlClockSet(SYSCTL_USE_OSC&nbsp;|&nbsp;SYSCTL_OSC_INT);&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;改用IOSC<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlMOSCVeriSet(false);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;禁止IOSC/64验证MOSC功能<br />&nbsp;&nbsp;&nbsp;&nbsp;SysCtlIntClear(SYSCTL_INT_MOSC_FAIL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;清除MOSC失效中断<br />&nbsp;&nbsp;&nbsp;&nbsp;ErrorLedOn();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;点亮错误指示灯<br />}<br />
s99060 发表于 2007-12-26 17:34 | 显示全部楼层

可惜,指示Stellaris系列才有

  
hotpower 发表于 2007-12-26 18:45 | 显示全部楼层

不错~~~不过在外部晶振坏时应该给出提示,否则串行通讯可能

  
boy123 发表于 2007-12-26 19:11 | 显示全部楼层

时序要求严的地方呢?

  
AIRWILL 发表于 2007-12-27 00:36 | 显示全部楼层

可惜

才上电,不能用内部振荡器启动
 楼主| zlgmcu 发表于 2007-12-27 08:35 | 显示全部楼层

hotpower:您好!在例程里,晶振失效时会点亮ERROR_LED报警

  
 楼主| zlgmcu 发表于 2007-12-27 08:37 | 显示全部楼层

AIRWILL:您好!早期型号上电采用晶振,后续型号都是内部振

  
machunshui 发表于 2007-12-27 11:57 | 显示全部楼层

支持zlg,讨厌因为商业利益诋毁他人

支持zlg,讨厌因为商业利益诋毁他人.<br />做商业的原则是说自己好,但别说别人不好!<br /><br />要是子虚乌有的说法,那人品就有问题了,商家的商业道德就有问题了.
AIRWILL 发表于 2008-1-4 10:56 | 显示全部楼层

感谢 ZLGMCU

那是我在&nbsp;101&nbsp;里的第一个试验结果<br /><br />不过,&nbsp;很高兴看到这个改进.&nbsp;<br />另外我倒是还希望软件能够对内部&nbsp;RC&nbsp;频率进行微调.(AT&nbsp;MEGA&nbsp;新款芯片都有这个功能)
 楼主| zlgmcu 发表于 2008-1-4 20:34 | 显示全部楼层

谢谢楼上的朋友们的支持!

内部振荡器存在一定的误差,是由于芯片制造工艺的问题,而不是内部振荡器本身不稳定。
mohanwei 发表于 2008-1-4 21:11 | 显示全部楼层

像C8051那样内部RC振荡器精度能做到2%,就不用晶振了

  
LPcfANS 发表于 2008-1-5 09:14 | 显示全部楼层

不用晶震就好了.毕竟不可能烧完程序在把晶震拔下去.

  
立体几何 发表于 2008-1-31 16:03 | 显示全部楼层

不是说用内部振荡器吗?当然不用外部晶振了。

  
 楼主| zlgmcu 发表于 2008-1-31 17:17 | 显示全部楼层

内部振荡器误差较大,不能完全代替外接晶振

由于IC制造工艺方面的原因,内部振荡器误差较大。因此还不能完全取代外接晶振。<br /><br />(zlgmcu_wdx)
疯子8972 发表于 2008-2-3 16:33 | 显示全部楼层

哦 温漂有几个PPM?

不知道这个内部振荡,温漂有几个PPM<br />如果大一点的话,这个东西也就是实验玩玩的用处了<br />有周工的前期工作,这个开发板看来是一定要买着用用看了<br />
xiachu 发表于 2013-10-4 15:52 | 显示全部楼层
src/gpio.h 这种头文件需要自己下吗?在哪下 困扰好久了 一直编译错误
您需要登录后才可以回帖 登录 | 注册

本版积分规则

81

主题

1146

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部