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

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

3天内不再提示

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

2oON_changxuemc 来源:YXQ 2019-06-20 10:47 次阅读

先上代码:第一个为错误代码,第二个为正确代码。这是用来向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了。

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

    关注

    6030

    文章

    44505

    浏览量

    632361
  • ACC
    ACC
    +关注

    关注

    1

    文章

    56

    浏览量

    22723

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

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

收藏 人收藏

    评论

    相关推荐

    请问TPA3112D1的datasheet上的control system要连在单片机上吗?

    请问TPA3112D1的datasheet上的control system 要连在单片机上吗?AVCC是连在单片机上的某个引脚吗?PVCC是连接电源吗?附件是datasheet上给的参考电路图。
    发表于 10-31 08:32

    西门子博途中循环中断功能的编程示例

    在以下示例中,将读取循环中断 OB (OB31) 的相位和循环时间,并设置一个新的循环时间。
    的头像 发表于 10-28 10:11 389次阅读
    西门子博途中<b class='flag-5'>循环中</b>断功能的编程示例

    单片机烧录程序的线比单片机上的少还能烧录吗

    单片机烧录原理 单片机烧录是指将编写好的程序代码通过一定的方式传输到单片机的存储器中,使其能够按照程序的指令运行。这个过程通常需要使用烧录器或者编程器等设备,通过一定的接口与单片机进行
    的头像 发表于 09-02 09:54 388次阅读

    单片机上位机软件用什么开发

    在开发单片机上位机软件时,选择合适的开发工具和编程语言至关重要。本文将详细介绍单片机上位机软件开发的各个方面,包括开发环境、编程语言、界面设计、通信协议、调试与测试等。 1. 开发环境选择 开发单片机上
    的头像 发表于 06-07 09:17 1164次阅读

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

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

    使用 MISRA C++:2023® 避免基于范围的 for 循环中错误

    在前两篇博客中,我们 向您介绍了新的 MISRA C++ 标准 和 C++ 的历史 。在这篇博客中,我们将仔细研究以 C++ 中 for 循环为中心的特定规则。
    的头像 发表于 03-28 13:53 725次阅读
    使用 MISRA C++:2023® 避免基于范围的 for <b class='flag-5'>循环中</b>的<b class='flag-5'>错误</b>

    单片机中for语句的运用

    单片机中的for语句是一种常见的循环控制结构,用于重复执行一段代码块,可以简化程序的编写和减少代码量。本文将详细介绍单片机中for语句的运用。 一、for语句的基本结构和功能 for语
    的头像 发表于 01-05 14:02 2113次阅读

    如何在循环中断中创建工艺对象PID控制器?

    以下步骤将介绍如何在循环中断 OB“PID [OB200]”中调用工艺对象“PID_Compact” 。
    的头像 发表于 12-29 18:10 1711次阅读
    如何在<b class='flag-5'>循环中</b>断中创建工艺对象PID控制器?

    51单片机for循环结束之后还在运行

    当我们设计并编写嵌入式系统时,使用51单片机编写程序时,常常会用到循环结构来重复执行一段代码。然而,有时我们可能会遇到51单片机循环结束之后还在运行的问题,这可能会导致系统的功能异常
    的头像 发表于 12-26 14:06 1001次阅读

    AvR单片机for循环需要几个指令周期

    在AvR单片机中,for循环语句的执行需要多个指令周期。指令周期是一个基本的处理器时钟周期,用于执行一条指令的所有操作。 首先,我们需要了解AvR单片机的架构,它使用了在指令级别上进行并行处理
    的头像 发表于 12-26 14:03 1047次阅读

    关于AD5940移植到其他单片机上的问题求解

    你好,我想问一下关于AD5940移植到其他单片机上的问题,我有以下问题。 1、我在调试过程中,单片机可以正常发送数据,但无法读回AD5940芯片的数据,为什么会出现这种情况?AD5940
    发表于 12-01 06:05

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

    的含义。i++被称为后缀递增运算符,它的作用是先使用变量i的值,然后再将i的值加一。而++i被称为前缀递增运算符,它的作用是先将i的值加一,然后再使用i的值。尽管这两个运算符都会增加变量的值,但它们在使用变量值的时机上稍有不同。 在循环中,i++和++
    的头像 发表于 11-26 09:20 9349次阅读

    c语言在while中嵌套if循环

    C语言是一种广泛使用的面向过程编程语言,它提供了许多控制结构来帮助程序员实现复杂的逻辑和流程控制。其中,while循环和if语句是非常常见和重要的控制结构。本文将详细介绍C语言中在while循环中
    的头像 发表于 11-22 10:09 5593次阅读

    python循环里的输出结果汇总

    循环是计算机编程中常用的一种控制结构,用于重复执行一段代码。Python提供了多种类型的循环结构,包括for循环和while循环。在这篇文章中,我们将详细介绍Python
    的头像 发表于 11-22 09:59 1576次阅读

    python怎么把for循环的值拿出来

    Python中可以使用for循环来遍历一个序列或者迭代器中的元素。当我们希望将for循环中的值取出来并进行其他操作时,我们可以使用一些方法和技巧来实现。 一、使用列表解析 列表解析是一种创建新列表
    的头像 发表于 11-22 09:54 3246次阅读