打印

函数在中断里执行和在上电就执行到底有什么区别?

[复制链接]
2366|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
fxhfxh|  楼主 | 2011-11-18 10:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
问题描述:型号:stc11f32xe,想达到的目的:通过串口将4196个字节(或者更多)写入eeprom保存,由于stc的eeprom写入必须整个扇区擦除,因而在要写入数据时首先由上位机通过串口中断程序发出扇区擦除指令,扇区擦除函数执行完后,然后写入数据,扇区擦除函数是在串行中断程序中执行的(进入中断程序时已关闭中断,中断退出前打开),实际中发现擦除不可靠,(即写入的数据发现不正确),为了找出问题所在,将扇区擦除函数放在一上电就执行,则每次的写入均十分可靠。可以肯定的是擦除函数在中断程序中是完全执行了的,没有任何干扰,也没有其他的中断程序执行(执行时已关闭了中断)。
问题:一个函数在中断程序里执行和在上电就执行到底有什么区别呢?
(也可以就在上电时就执行擦除函数,但每次上电就擦除一次,担心寿命呀.)

相关帖子

沙发
hotpower| | 2011-11-18 10:22 | 只看该作者
俺不懂这种eeprom,别人都叫flash

使用特权

评论回复
板凳
DownCloud| | 2011-11-18 10:26 | 只看该作者
问题很奇怪。。。可能是擦除需要等待一段时间才能写吧?已经忘了stc的eeprom。

使用特权

评论回复
地板
fxhfxh|  楼主 | 2011-11-18 11:52 | 只看该作者
谢谢楼上朋友们的回复,等待时间在擦除程序里面已有了。

使用特权

评论回复
5
ShakaLeo| | 2011-11-18 13:19 | 只看该作者
是用的keil吗?我想到一种可能性,是不是你的中断和主程序用的不是同一个寄存器组,而擦除的函数在编译时使用的是寄存器的绝对地址,这样的话在中断里调用擦除函数就不能得到正确的执行结果。用simulator看一下反汇编代码就知道了。

使用特权

评论回复
6
DownCloud| | 2011-11-18 14:18 | 只看该作者
按ls的分析,中断里调用擦除为什么不能得到正确执行结果啊?感觉没影响啊,我没换组过,最近又生病了,不能去尝试,但按照ls说法,执行完中断,程序就崩溃了吧。所以  换组=不能调用子函数(或者很小心)?  是吗?

使用特权

评论回复
7
DownCloud| | 2011-11-18 14:22 | 只看该作者
额,,
弄错了。
换组后编译器中断入栈的还是r0-r7 ,所以后面的问题去掉。
所以只有一个问题 为什么不能正确执行啊?

使用特权

评论回复
8
DownCloud| | 2011-11-18 14:24 | 只看该作者
入栈0x00-0x07,不是r0-r7

使用特权

评论回复
9
ShakaLeo| | 2011-11-18 14:48 | 只看该作者
回楼上,只是使用不同的寄存器组不会导致问题,但如果中断里调用的函数在编译时使用的是寄存器的绝对地址就可能有问题了。keil一般是用寄存器传参,如果用不同的寄存器组,对同一个函数来说,在中断里传参使用的寄存器和在主程序里用的并不是一个寄存器,而程序如果使用寄存器的绝对地址来编译,那么代码就可能是MOV A, direct的形式而不是MOV A, Rn的形式,而导致传参错误。

使用特权

评论回复
10
fxhfxh|  楼主 | 2011-11-18 15:37 | 只看该作者
5# ShakaLeo
谢谢,基本可以肯定是这个原因了,当时写中断程序时我担心干扰,中断程序我是换了一个组,用默认的现在看可以正确的写入了,我再观察一下。

使用特权

评论回复
11
DownCloud| | 2011-11-18 16:43 | 只看该作者
嗯,确实如此。很细节的问题,学习了。

使用特权

评论回复
12
DownCloud| | 2011-11-18 16:47 | 只看该作者
那如果要解决这个问题,不改中断使用的寄存器组,要怎么改擦除子程序啊?

使用特权

评论回复
13
fxhfxh|  楼主 | 2011-11-18 17:39 | 只看该作者
void seriall() interrupt 4      //   using 3  千万注意此处不能换用寄存器组

{  ES=0;                  
    RI=0;                  
   if(sq_cc_ok_w1==1)        goto  jx;
   if(tx_ok_w1==1)goto  zp_w_90_m;    //  jx;
   nop;
  if(SBUF!=85)  goto  fh;
    tx_ok_w1=1;
   goto fh;
zp_w_90_m:
   nop;
  if(SBUF!=90) goto   fh;
  nop;
cc_57g_sq();   //擦除函数        
nop;                        
  sq_cc_ok_w1=1;

使用特权

评论回复
14
ShakaLeo| | 2011-11-18 18:37 | 只看该作者
回12楼:在擦除函数那个文件的开头写上#pragma noaregs
或者在工程设置里选中"don't use absolute register acesses"

使用特权

评论回复
15
sysdriver| | 2011-11-19 08:34 | 只看该作者
有些东西,很多前辈就提前警告了,但还是有人用。

goto 语句会造成结构不清晰,难理解,但是LZ还是用了。
中断里面最好不要有函数,而且不要长,中断是可以嵌套的,最好不要随意关中断,但LZ也用了。
前辈的警告不是无厘头的,现在也许你不知道原因,等你提高了就知道。为了避免诸多问题,原则还是要遵循的。

使用特权

评论回复
16
fxhfxh|  楼主 | 2011-11-19 09:55 | 只看该作者
15# sysdriver
      很感谢楼上前辈的指教。
      我看书上说goto语句尽量少用,是正确的,但我这个地方好像不用goto语句写比较难写,就用了。有时间我再看看怎么改一改,看行不行。
      我是在一进入中断就关闭了中断的,主要是在中断程序里有擦除和写入程序,不关中断害怕有影响,退出中断前又开了中断的。我在实际试验的时候试了一试进入中断程序时关中断和不关中断,好像没有什么区别,就按照一般书上的写法,一进入中断就关闭了中断,退出前再打开了的。这个问题到底有什么影响,真没有搞明白,前辈能否再指教一下?谢谢。
     因为这个程序是上位机连续的发出擦除指令和连续的写入数据,而擦除的扇区又比较多(58个扇区),连续写入的数据也比较多(4千多或者更多字节),我确实也不想在中断里面完成,那么,到底还有不有更好的办法呢?

使用特权

评论回复
17
sysdriver| | 2011-11-19 14:52 | 只看该作者
中断里面,不用做太多的事情。只是收到数据,还有置标记位。
r_temp_sbuf = SBUF;
b_has_receive = 1;


在主循环里面判断标记位和处理数据
void main(void)
{
       //------------
       while(1)
       {
                  //-------------
                  f_deal_sbuf();
       }
}

void f_deal_sbuf(void)
{
         if(b_has_receive != 1) return;
         b_has_receive = 0;

         //--------
         switch(r_temp_sbuf)
         {
                     case  ----------------
         }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

382

帖子

1

粉丝