0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何找出单片机for循环中ACC的隐藏问题

2oON_changxuemc 来源:feiyan 2018-12-09 11:06 次阅读

先上代码:第一个为错误代码,第二个为正确代码。这是用来向ds1302芯片写入命令或数据的函数。实现把8位的数据dat一位一位地写入ds1302的io口。其中ACC0为ACC的第0位。

认真对比这两个代码,可能会觉得没区别,而且这两个代码都可以通过编译(加上reg52.h和一些宏定义)。我也是一直认为for()这里边没有错误,结果。。。试着修改时钟信号,增加延时之类的,调了好久还是错,严重打击我的自信心。这两个代码的区别就只有for(i=0;i<8;i++)和for(i=8;i>0;i--)了。学过c语言的人都知道,这两个句子都是实现一个8次的循环,功能一模一样。怎么会因为这个句子的区别就导致单片机控制的错误呢?神奇!

接着我试着把错误程序中的ACC改为51芯片的寄存器B,烧录进单片机,程序运行成功,跟“for(i=8;i>0;i--),ACC版”一样,lcd在很嚣张地显示着正确的时间( for(i=0;i<8;i++),ACC版lcd的时间显示为0)。附:

这样就知道原因了,使用for(i=0;i<8;i++)的运算中可能有累加器ACC参与了,导致修改了ACC的值,使写入的命令出现错误。但为什么for(i=8;i>0;i--)就没有ACC的参与呢?一个大大的问号。基于我调试了一个星期的程序,皆因为这一个神奇的错误,我实在不甘心,决定研究到底。于是,分别查看了这三个程序代码keil4 编译后得到的 汇编代码。(学过汇编就是爽啊,哈)

对比后,可以发现,出错的原因是for(i=0;i<8;i++)ACC版中,用ACC接收了实参(存储的为要写入的指令),然后在 for 循环前要给变量 “ i " 赋值时,要用到ACC清零,再把ACC中的零赋给 R7 ("i"的值存储在R7)。这样的话,原来存储在ACC中的写入指令就被清零,自然会导致控制出现错误,最终没法读取ds1302芯片的时间,故显示为零。

而在for(i=8;i>0;i--)ACC版中,也用ACC接收了实参的值,但在 for 循环前,给变量“ i ” 赋值时,赋值为8,不需要用到ACC,所以ACC一直是存储着实参中的指令,没有被清零,所以能够顺利地向ds1302发送指令,从而能够读取到时间。

总结:

因为用for(i=0;i0;i--)类的指令多了 CLR A 和 INC R7 两条指令,CJNE 指令又比较DJNZ指令多了一个字节的程序代码存储空间,在频率为12M的51单片机上体现为执行同样功能的程序,要多用2us,代码空间花多一字节。所以前者是毫无优势的,以后应养成用

for(i=n;i>0;i--)的习惯。

请不要反驳我用了这么长的时间去研究,只能使单片机执行快2us,而说我钻牛角尖,只是因为,这个错误导致我整个程序无法正常运行,这不是一件小事。

至于为什么要用到累加器ACC来接收实参,是因为后面的程序要把一个8位的实参一位一位地输出到一个io口,自定义一个变量的话,按位寻址好像比较麻烦,要经过一系列 位运算 ,或者用bit定义8个位(有好的方法请告诉我,哈),而且我写不出来。而用ACC的话,可以很轻易地操作ACC的任意一位,如ACC0,ACC7。在网上查了一下,好像还有一种方法是定义 一种叫 位域 的东东,我看的c语言的书都没介绍,所以还不是很了解。

/************************************************************/

刚刚想了一下,不用ACC 的方法,作一个位运算dat &0x01,修改如下:

想到了这个方法后,觉得自己好白痴,以后都不用ACC了。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6002

    文章

    43982

    浏览量

    620934
  • ACC
    ACC
    +关注

    关注

    1

    文章

    54

    浏览量

    22585

原文标题:关于单片机上for循环中运用ACC的隐蔽错误

文章出处:【微信号:changxuemcu,微信公众号:畅学单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    使用STM32F401的单片机移植了ucosii操作系统后,在循环中调用sprintf函数时莫名卡死的原因?

    使用STM32F401的单片机移植了ucosii操作系统后。在编写任务函数时,在循环中调用sprintf函数时莫名卡死的原因?
    发表于 04-02 06:12

    如何使用单片机中的ACC

    在合泰单片机中 怎么实现对累加器ACC的位操作 求各位大神帮忙给个范例 谢啦
    发表于 03-25 23:35

    请教几个单片机程序规范的问题

    如果有一个比较大的单片机工程,用到了挺多中断,那么单片机代码应该是主要在中断服务程序中,而在main函数中简单进行初始化工作,让while循环中尽可能少干活,,,,,还是应该让主要的工作在main
    发表于 09-01 10:34

    如何停止while循环中的for循环,停止计时?

    各位大师,小弟请教如何在运行计时后,停止计时;也就是说,如何停止while循环中的for循环,谢谢大师们!
    发表于 10-23 16:29

    单片机上for循环中运用ACC的隐蔽错误解析

    的区别就导致单片机控制的错误呢?神奇!  接着我试着把错误程序中的ACC改为51芯片的寄存器B,烧录进单片机,程序运行成功,跟“for(i=8;i》0;i--),ACC版”一样,lcd
    发表于 01-13 16:04

    单片机程序结构

    、AD采样、脉冲计数、异步通信UART、EEPROM读写等;在这200微妙的循环中,实现各种中断任务处理;这个比硬件中断的方式对实时性有更好的管控;例如PIC系列单片机用UART接口和PC的232...
    发表于 11-24 07:27

    CH579M主循环中调用CH57xNET_MainTask,导致单片机不启动是怎么回事?

    问题:while循环中调用CH57xNET_MainTask,单片机就启动不起来,注释掉之后就可以正常运行了,注释之后网络库可以正常初始化,TMR0,ETH中断,串口中断都可以正常进入,就是在循环中
    发表于 10-14 07:32

    请问单片机的ALU、ACC功能是什么?

    单片机的ALU、ACC功能是什么?
    发表于 10-31 06:35

    找出隐藏的问题:更新速率应列入“指标性规格”的理由

    找出隐藏的问题:更新速率应列入“指标性规格”的理由
    发表于 08-03 13:02 14次下载

    干货 | 关于单片机上for循环中运用ACC的隐蔽错误

    想到了这个方法后,觉得自己好白痴,以后都不用ACC了。
    的头像 发表于 06-20 10:47 3546次阅读

    单片机的死循环有什么作用

    单片机是可编程器件,在使用时需要编写满足需求的程序。其C语言程序在各个端口、配置初始化完成后,会进入一个死循环,一般用while(1){;}的形式。初始化完成后,单片机就在死循环内一遍
    发表于 08-09 17:01 5181次阅读
    <b class='flag-5'>单片机</b>的死<b class='flag-5'>循环</b>有什么作用

    【Practical】单片机Acc与A的区别

    Acc与A的区别
    发表于 11-23 09:21 12次下载
    【Practical】<b class='flag-5'>单片机</b>中<b class='flag-5'>Acc</b>与A的区别

    单片机三种常见按键设计优化方案

    对于单片机初学者很容易理解和使用,但是缺点是,需要在主循环中不断检测按键是否按下,并且需要做消抖处理。若主循环中某个函数任务占用时间较长,则按键会有不同程度的“失灵”。
    发表于 07-01 11:37 2009次阅读
    <b class='flag-5'>单片机</b>三种常见按键设计优化方案

    西门子博途SCL: FOR:在计数循环中执行

    使用“在计数循环中执行”指令,重复执行程序循环,直至运行变量不在指定的取值范围内。
    的头像 发表于 07-18 10:07 5599次阅读

    for循环中i++与++i的区别

    i++和++i都是增加变量i的值的运算符,但它们之间有着一些微小的区别。在这篇文章中,我将详尽、详实、细致地解释i++和++i之间的差异,并探讨它们在循环中的应用。 首先,让我们明确i++
    的头像 发表于 11-26 09:20 1306次阅读