无限循环并不是防止程序“跑飞”的,而是防止main()返回

 
例子:
//实例13:用P0口显示逻辑"与"运算结果
#include   //包含单片机寄存器的头文件
void main(void) 
{
  P0=(4>0)&&(9>0xab);//将逻辑运算结果送P0口
  while(1)
    ;    //设置无限循环,防止程序“跑飞”
}

请问大侠们最后的无限循环是如何防止程序跑飞的? 
---------------------------------------------------------------------------------------------------------------------------------------3#
这个程序并不能阻止程序的跑飞(应该用看门狗才行),不过这样写也是很正确的做法,就是让程序一直在运行着(原地循环),这里的while(1)并不是防止程序“跑飞”的,而是防止main()返回。
①    在嵌入式中main是不能返回的。不同的C语言实现的startup code会有不同的表现,有的是在call _main后jmp,而有的是jmp  0,等等这些会导致 不可预料的结果。
②    在我们写的C语言后转换成汇编,在观察单片机的代码区,你会发现没有写程序的部分例如全1或者全0区域,程序运行到这里如果在往下执行的话,就会有可能造成 意料不到的结果。   不过我还没有这样实验过,理论上是这样的,希望大家一起讨论,多多指教。
------------------------------------------------------------------------------------------------------------------------------------------
3楼正解,我觉得最后那个while里面没有代码,就是让程序原地运行,但是它不能阻止在特殊情况下程序跑飞,如外界电磁干扰等,那个无限循环的作用就是将PC指针控制在程序的代码区内,防止PC跑偏。
------------------------------------------------------------------------------------------------------------------------------------------
路过 打酱油 用看门狗就好
 
 
 
R8C/1B单片机的Flash编程/擦除挂起功能
 
Flash存储器已成为嵌入式系统中数据和程序最主要的载体。但是在对Flash进行 编程擦除的操作过程中,如果 单片机需要处理一些紧急的情况(如中断、数据存储等等),就需要暂停相对比较消耗时间的Flash编程/擦写过程,优先处理这些紧急情况。这对Flash存储器的工艺水平及控制技术提出了更高的要求。

图1编程/擦除挂起操作时序


  瑞萨公司推出的R8C/1B单片机采用改进的Flash存储器工艺,大大缩短了编程/擦除挂起的时间,使其能够更加及时地响应中断或进行其他操作。

  Flash编程/擦除挂起功能

  所谓挂起功能,是指当Flash模块正在执行编程或擦除操作时,CPU改写模式可以暂停当前的Flash操作,将编程或擦除挂起的功能。在编程/擦除挂起的过程中,用户ROM区的内容可通过程序来读取。

  瑞萨R8C/Tiny单片机在R8C/18以后的产品中(如R8C/1B),较之以前的产品(如R8C/15),Flash存储器在编程/擦除挂起功能上有了很大改进,其具体功能的比较请参见表1,编程/擦除挂起操作时序请参见图1。

  由表1可以看出,R8C/1B单片机所采用的Flash模块工艺在以下方面拥有明显的优势。

表1Flash存储器功能比较表

 


  挂起时间延迟最长为97μs+6个CPU时钟周期,最长的挂起重新启动时间延迟为3μs+4个CPU时钟周期;R8C/15单片机Flash模块只能在擦除时挂起,但改进Flash工艺的R8C/1B单片机在编程时也可以实现挂起功能;擦除时可以编程。

  图1为编程/擦除挂起的简单示意图,在编程/擦除开始之后,如果发生了某个中断请求,在等待一段挂起延迟之后,CPU转向中断子程序的处理。中断处理子程序执行之后,Flash存储器继续执行编程或擦除过程,直至操作结束。

  Flash编程/擦除挂起功能的实现

  ●  EW0模式与EW1模式

  CPU改写模式是通过固化在单片机程序存储器中的软件命令对Flash存储器进行编程的形式,适合对单片机进行在应用中编程(IAP)的场合,即能够在不使用Flash编程器,且将单片机安装在电路板的状态下实现对Flash的改写。

  CPU改写模式分为擦除/编程0模式(EW0模式)和擦除/编程1模式(EW1模式)。

  这两种模式的根本区别在于改写控制程序的执行区域不同。如图2所示,EW0模式中,改写控制程序在Flash存储器以外的区域执行,因此在这种模式下可以改写所有的用户ROM区。EW1模式中,改写控制程序依然存放在用户ROM区的某一个块中,并在此区域执行,因此在这种模式下,除了存有改写控制程序的块以外,其他的用户ROM区都可以被改写。

图2EW0模式与EW1模式


  在执行擦除/编程的过程中,在EW0模式下CPU处于正常运行的状态,而在EW1模式下CPU处于保持状态。

  ●  Flash编程/擦除挂起的设定

  相关的寄存器

  与Flash编程/擦除挂起相关的寄存器是闪存控制寄存器4(FMR4),FMR4有6个位均与编程/擦除挂起功能相关,请参见表2。

表2闪存控制寄存器4


  EW0模式的擦除挂起设定

  对于EW0模式转移到擦除挂起时,首先需要将FMR40位置“1”(允许挂起)、FMR41位置“1”(请求擦除挂起),然后延迟一段时间(97μs+CPU时钟周期×6),在确认FMR46位为“1”(允许读)后才能对用户ROM区进行存取。如果将FMR41位置“0”(重新启动擦除),就重新开始自动擦除。设定过程如图3所示。注意,在EW0模式,请将所使用中断的中断向量表和中断程序存储在RAM区中。

  EW1模式的擦除挂起设定

图3EW0模式的擦除挂起设定


  对于EW1模式,首先需要将擦除挂起功能设定为有效,即将FMR40位置“1”(允许挂起),并预先将需要响应的可屏蔽中断设定为中断允许状态。这样在执行块擦除命令后,如果该中断产生,经过一段时间延迟后(电气特性推荐值为:97μs+CPU时钟周期×6),就能执行擦除挂起,并接受中断请求。如果发生中断请求,FMR41位就自动变为“1”,执行擦除挂起。在结束中断处理后,如果自动擦除还没有结束(FMR00位为“0”),就必须将FMR41位置“0”,重新开始自动擦除。设定过程如图4所示。

图4EW1模式的擦除挂起设定


  在EW1模式下执行擦除指令进行Flash擦除时(典型值为200ms/1K字节块),CPU虽处于HOLD状态,但可以接受中断响应,实现分时擦除。利用这个工作原理,下面给出一个R8C/1B单片机的应用实例,利用Timer(定时器)中断和Flash擦除挂起功能实现对擦除时间的估算。

  使用TimerX定时1ms,Flash擦除过程中每1ms挂起一次,进入中断处理程序并调整计时变量g_Timers。在擦除结束后,g_Timers所存储的就是擦除时间的估算值。

  例程如下。

  #include "sfr_r81b.h"
  unsigned int g_Timers;//总擦除时间计数变量 

       /* 定时器X中断处理函数 */
  #pragma interrupt timerX_ISR
  void timerX_ISR(){
  g_Timers++;
  }
  /* 检查Data Flash状态寄存器 */
  unsigned char checkStatusRegister(){
  return fmr07|fmr06;
  }
  /* 清除DataFlash状态寄存器  */
  void clearStatusRegister(){
   *((unsigned char *)0x2400) = 0x50;//执行清除状态寄存器软件命令
  }
  /* 块擦除 */
  unsigned char eraseBlock(unsigned int adr){
  unsigned char   result="1";
  asm("FCLR I");//关中断
  fmr01 = 0;
  fmr01 = 1;//进入CPU改写模式
  fmr11 = 0;
  fmr11 = 1;//设置为EW1模式&nb
 

sp;
  fmr40 = 0;
  fmr40 = 1;//允许中断擦除挂起 
  asm("FSET I");//开中断
  g_Timers = 0;//计数值清零
  prex=0x32-1;tx=0x32-1;//定时值1ms
  txs=1;//定时器X开始计数
  *((unsigned char *)adr) = 0x20;//执行块擦除软件命令
  *((unsigned char *)adr) = 0xD0;
  while(fmr00 != 1){//判断擦除是否结束
  fmr41 = 0;//中断返回后继续擦除
  }
  txs=0;//定时器X停止计数
  fmr01 = 0;//退出CPU改写模式
  if(!checkStatusRegister()){//查看状态寄存器
  result = 0;//擦除成功
  }
  else //擦除失败
  clearStatusRegister();//清除状态寄存器
  return result;
  }
  /* 对MCU进行初始化 */
  void initMCU(){
  unsigned char i="0";
  asm("FCLR I");//关中断
  //将CPU时钟切换为主时钟20MHz
  prcr = 1;//解除对cm0,cm1,ocd寄存器的写保护
  cm13 = 1;//接通 Xin-Xout
  cm15 = 1;//Xin-Xout驱动能力:高
  cm05 = 0;//Xin-Xout启动
  cm16 = 0;//无分频模式
  cm17 = 0;
  cm06 = 0;//使CM16,CM17有效
  while(1){//等待主时钟振荡稳定
  if(!ocd3){
  if(i>=10) break;
  else ++i;
  }
  }
  ocd2 = 0;//选择主时钟
  prcr = 0;//设定对cm0,cm1,ocd寄存器的写保护
  //设置定时器
  txmr=0x00;//定时器X设为定时器模式
  tcss=0x11;//选择计数源为f8
  txic=0x07;//定时器X中断优先级为7
  asm("FSET I");//开中断
  }


  /* 主函数 */
  void main(void)
  {
  unsigned char flag;
   initMCU();//对MCU进行初始化
   flag = eraseBlock(0x2400);//擦除大小为1kB的块A,块首地址为2400H
   while (1);
  }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值