LPC单片机延时异常(LPC21xx,LPC2300)--欢迎高手指点

qusongsong1 2009-12-25 10:26:34
小弟在使用LPC21xx及LPC2300系列单片机遇到点棘手的问题,用C做一段延时程序时,当程序代码放置于不同的地址将导致延时不确定,就是说同样的代码放置的地址不一样可能导致延时不一样,百思不得其解,而且代码都运行于通一个类型的存储区域,以下为扑捉的C代码图片、汇编代码图片,以及抓到的引脚输出波形。
使用的是周立功的工程模板,ADS1.2编译器,AXD仿真,在进入循环前已禁止所有中断,通过示波器检测NRF_CLK2引脚的变化来查看延时时间,可以看到示波器抓到的图片有三段(3个100us)较长,紧跟的三段较短,并周期性循环。正常的100us在不正常的时候大概为66us,汇编代码也是完全一样的。
有哪位兄台碰到过类似问题吗?




...全文
426 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
majie132ma 2011-06-04
  • 打赏
  • 举报
回复
学习下
qusongsong1 2009-12-27
  • 打赏
  • 举报
回复
呵呵,好的,我再试下。你的意思让他从4字边界上开始就不会因为MAM加速的时候导致延时的不确定了?
因为MAM预取址是为4字的。
Great_Bug 2009-12-26
  • 打赏
  • 举报
回复
..........你的示波器波形.....好像并没锁定......
Great_Bug 2009-12-26
  • 打赏
  • 举报
回复
另一个办法: 用汇编语言写延时函数,总是让它从4字(16字节)的边界上开始,这样程序改了它的行为也不会变化.
qusongsong1 2009-12-26
  • 打赏
  • 举报
回复
怎么看出来示波器波形没锁定?锁定了的
因为是在驱动一个芯片的时候发现的延时函数延时不确定,比如延时300us,有时候就成了延时200us了,所以才用示波器抓波形来验证的,折腾了我蛮久的。
qusongsong1 2009-12-26
  • 打赏
  • 举报
回复
感谢Great兄,果然是高手中的高手!
就目前的情况应该是MAM加速出了问题,因为得我MCU使用的是60M以上的频率,然后可能因为MAM的加速导致了系统在需要精确延时的时候不稳定,目前我在延时函数的开始关闭MAM,当结束延时后再打开MAM加速,暂时还没有发现问题,在后期还需要继续观察会不会有不稳定的现象出现。
虽然目前现象没有了,但是我感觉还需要继续观察,呵呵,因为又发现了一个异常问题:for (j=0;j<342;j++);当我把342改为361,延时为324us,当我把342改为360,延时为288us,但是小于360的时候,比如342,延时为300us。。。。。。就是说在360这个地方导致延时不是线性的,但是大于360和小于360又恢复为线性的。。。。调试中偶然发现的这个问题。

再次感谢Great_Bug兄弟,感谢ID6886兄弟,感谢FLandY1982兄弟。
ld6886 2009-12-25
  • 打赏
  • 举报
回复
楼主的代码是用两样的编译参数进行编译的吗?从现象描述上看似乎是用不同的参数编译了两个函数,而从给的代码上看又不是这样的,楼主可以再给些背景资料吗?
qusongsong1 2009-12-25
  • 打赏
  • 举报
回复
感谢楼上两位的帮助,
1.引脚为LPC2300--P0.24脚
2.程序中断已经屏蔽,快速中断,慢速中断都禁止了,而那是一个死循环,不可能存在其他调用
3.我用IO脚的变化来测我延时函数是否准确,但是还不需要精确到IO的翻转速度也需要计算在内,因为一些芯片的驱动是需要严格按照时序的,比如上电需延时300us,那么如果只延时了200us就会出现问题。我追究这个问题的根源是因为我本来调好的延时100us的函数,在我增加了一些应用代码后有可能导致延时100us函数变成延时66us了,当再增加一些代码又可能回复到100us,而只要代码不更改,延时100us就不会变成延时66us,延时66us也不会变成100us,只有当代码增加或者减少,可能导致这一个函数的实际延时变化,并可以确定增加和减少的代码毫不影响这个延时函数。
4.上面两个延时函数Delay_100us11()和Delay_100us22()只是名字不一样,里面的代码完全一样,为什么会导致这样的现象?
Great_Bug 2009-12-25
  • 打赏
  • 举报
回复
NXP的ARM7有个MAM模块,你把它关闭了再试试...
Great_Bug 2009-12-25
  • 打赏
  • 举报
回复
猜测.....你的MCU内的程序存储器是分页的,如果在同一个页内部,访问会快一些,如果跨越页面访问,要慢一些.....纯属猜测,没有根据.
FLandY1982 2009-12-25
  • 打赏
  • 举报
回复
用如下代码测试下:
#deifne DELAY_TEST() SET_NRF24_CLK2(); \
for(j = 0; j < 800; j++); \
CLR_NRF24_CLK2();

// 注意不要用循环来调用.
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();
DELAY_TEST();

以前看到某个MCU厂商测试IO翻转速度时就是以这种形式测试的.
ld6886 2009-12-25
  • 打赏
  • 举报
回复
根据我的分析是你示波器测量的I/O脚(也就是你用来输出延时的pin)被重复使用了,也就是这个pin可能被程序中的其他部分的代码所控制,中间的66us就是因此而产生的(66.666*3 = 200),所以应该重点看一下是否有这种情况,也许你的程序中没有复用,但要考虑系统中的其它程序(比如调试系统等)是否用了此pin.
qusongsong1 2009-12-25
  • 打赏
  • 举报
回复
请问楼上你回答前看到图片了吗?
采用软件延时是因为对延时的精确度要求不是很高
而且方便其他地方调用,并且测试延时时工作频率一样,中断已关, 函数调用开销也不会导致较大误差。
现在的情况是延时100us有时可能只有66us,而有时候又是100us,而且同样的代码,只是函数名不一样,有时候也会导致误差。
谢谢你的回答,我也是打算用定时器延时,不过这个问题的根源还得找出来。
qusongsong1 2009-12-25
  • 打赏
  • 举报
回复



qusongsong1 2009-12-25
  • 打赏
  • 举报
回复
FLandY1982 2009-12-25
  • 打赏
  • 举报
回复
建议使用定时器做延时.
软件延时会受以下几方面影响:
1. 编译器优化程度.
2. 主芯片频率.
3. 中断.
4. 函数调用开销.


你把程序修改下..复制多个延时代码段, 而不是通过循环调用同一个延时代码段, 如:
由形式:
for(i = 0; i < n; i++)
DELAY();
改为:
DELAY();
DELAY();
DELAY();
DELAY();
DELAY();
DELAY();
形式, DELAY最好写成宏, 再测试IO速度.
qusongsong1 2009-12-25
  • 打赏
  • 举报
回复
图片没有 ,马上传
qusongsong1 2009-12-25
  • 打赏
  • 举报
回复
晕,下划线没对上,下面一行的下划线在上面下划线的空白处
qusongsong1 2009-12-25
  • 打赏
  • 举报
回复
示波器的扑捉应该是没有问题的,P0.24放在函数外面置位也是一样,只不过没有了三个低脉冲,如下图所示的一个波形
_________ _________ _________ _________
______ ______ ______ ______

呵呵 都不知道咋整了,感觉应该跟延时函数在内存中的存放位置有关系
ld6886 2009-12-25
  • 打赏
  • 举报
回复
综上所述,你的Delay_100us11及Delay_22us应该是完全一致的。

我认为你的程序中的输出方式可能有问题,考虑一下你的外循环内的最后一条语句和第一条语句,先复位再置位,如果外循环没有结束,这两个语句(clr和set)之间的时间极短,生成的波形宽度极短,很可能你的示波器都没办法将这么窄的东西捕获并显示,同样的问题也出现在Dealy_100us11结束和Delay_11us22开始时,所以建议你不要用这种方式来显示(输出高低电平)。

建议你只在外循环的的开始或结束处用一条将P0.24变反语句来测试你的循环时间是否正确。
加载更多回复(2)

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧