AVR编程感悟

发布者:蓝天飞行最新更新时间:2016-10-22 来源: eefocus关键字:AVR  编程感悟 手机看文章 扫描二维码
随时随地手机看文章
公司的项目中用的单片机都是avr,有Atmega128,Atmega2561,和刚刚用的Attiny2313,玩了两三个月了,这三个单片机也玩熟了,因之前都是写上层应用的,一些编程的观念,特别是在玩完2313后有了很大的改变,把最近的一些编程中认识到的问题及想法先记录下来,当个备忘录吧。
  1. 首先是“封装”的思想
    • 先说下原先的观念吧,原先参加的项目比较大,芯片资源也很丰富,RAM都是几十兆的,ROM都是过百兆的,自己只负责一个模块的,这方面特别的重视,包括一些用到的变量,都根据实际用途进行封装,这样便于维护,也便于编写程序,同时也便于后期扩展,变量的封装对应要有相应的函数封装,将所有的全局变量的操作都封装起来,会提高程序的灵活度以及移植性,在与别人的模块接口方面也比较灵活,所以养成了习惯,只要抽象成一个功能模块的,都将其封装起来,然后复杂的功能用一些小的功能往起拼,个人觉得这样降低了逻辑的复杂度,而且也是遵循软件工程的“低耦合,高内聚”的原则。这也是先前一直认为很好的编程习惯,所以写程序前都要规划规划,看看那些能做成模块,方便开放和关闭一些功能(应对定制版或多平台的需求)。
    • 最近这几个项目都很小,软件的工作量都是一个人搞定的,资源都很有限,128-->RAM(4K bytes),ROM (128Kbytes),2561->RAM(8K+32K ext),ROM(256K bytes),2313->RAM(128 bytes),ROM(2K bytes),刚开始玩128,哇塞才4K的RAM,记得原来做一个FAX的buffer都超过4K了,偶滴神那,但用起来,慢慢发现也不是那么恐怖,里面还有4K的EEProm嘛,用的过程中才真正的体会到了RAM和ROM的功能,原来写程序真的不是特别清楚,也没有去想过自己的程序中所有的东西怎么分配的,有点“活的不明不白”。原来4K的RAM可以干好多好多事情的,包括LCD的控制显示,485通信,控制多个模块的工作,接收PC的控制命令,按键的控制等等。对于128,它的代码空间已经足够大了,所以可以将一些功能啥的都封装起来,这些一点问题没有,2561也是同理,但最近这两天玩的2313,让我豁然发现,并不是所有的程序都适用这个原则的。开始用结构体将相关功能封装起来,在把基本的功能(IO口的配置,定时器的配置,串口的配置,看门狗的配置,中断的配置,串口的解包,EEPROM的接口)完成后,我了个去,ICC提示代码空间已用了80%多了,我去了,这还玩个P啊,先不管了,将串口的处理完成后,90%多了,先不管了,用VB写了个简单的上位机,调试了大半天,终于连上位机和这些简单的功能调通了。还要用IO模拟另一个串口啊,没空间了,咋整涅,精简代码被,想想看那些可以精简,首先想到的是函数调用的地方,将只用到了一次的直接将代码搬过去,函数干掉,多次用到的保留,函数调用最多只要两层(main函数本身不包括),清理了下,少了点,然后觉得还不行,应该还能清理,后来发现那些结构体封装的变量了,因为从结构体变量成员的访问需要在结构体的基址上加偏移玩的,所以估计这块会多消耗一些额外的指令的,所以将结构体通通干掉,改用多个全局变量,对其直接访问(这也是我原先最痛恨的一种写代码的方式),试了下,少了好多,代码变成70%多了,不错,继续看看,然后发现解包函数中有些共用的语句,包括正常的处理和异常的处理,想着,干脆放一块,用两个goto跳过去得了,试了下,恩,又小了些,已经很满足了。至此程序已改的和原先设计的结构完全不一样了,有点“面目全非”了,不过实用性提高了很多,将IO模拟的另一个串口的接收完成后,代码空间80%多一点,还好,还有其他的余地来干一些事情,到此我的工作也暂时完成了。此时我认识最深刻的就是稀缺资源的嵌入式设备编程时要尽量的用全局变量,尽量直接访问,少些函数,少用调用,多用goto,当然了,需要斟酌着用。完全和原先的观念相反。
  2. 对于RAM使用的认识,对于很小的RAM设备,能共用就共用,必然2313这个东东,串口的首发的buff完全可以用一个来实现,刚开始我也用的两个,但后来在用IO模拟另一个串口是发现RAM不够用了,因128的RAM,30个字节还要用到函数栈空间,程序的空间只剩下可怜的90多个字节了,一条串口命令最长还有17个字节,所以很是吃紧了,后来干脆将串口的收发合到一起,因为只有在收完了才会发送的,所以在发送时关闭接收中断得了。RAM终于足够IO模拟用了。另外实在不够,还可以用128字节的EEPRom做中转,还是比较可观的。另外一个就是函数栈空间,这里面的空间包括函数调用的地址保存,局部变量的保存,所以嘛这就是函数为什么尽可能的少调用,因为函数里面少不了局部变量,调用的多了,将栈空间用完,栈溢出,你就哭吧,程序某些功能正常,某些功能异常。最开始,为了确认板子程序启动了,在main的开始部分添加了个20字节的buf,惨了。。。后来终于被我发现这个罪魁祸首了AVR编程感悟 - 苍海一笑 - 生命在于折腾
  3. 另外一些算是常识性的东西,最近印象比较深刻的,记录下吧:
    • 每个有效的功能变量都有范围的,一定要限定边界值
    • 如果代码空间比较富裕,对EEPROM的操作最好做加校验,好处是在EEPROM被冲掉后,程序检测出异常会做异常的保护,也可以用来调试,提醒系统有问题。
    • 看门狗一定是要的
    • AD采样,一定要多次采样,求平均值,这样可以减少异常的干扰
    • 程序一定要有版本号,否则,版本多了,哼哼。。。
    • 按键不仅要检测按下,还要检测释放按键,否则长按着。。。。。(这个就看需求了)
    • 驱动一定要隔离,一定要做成模块,为上层应用提供接口,上层应用不要直接控制驱动相关的东东
    • avr的单片机呢,熔丝位(fuse)一定要烧写的,根据datasheet来确定
    • 对于每一个功能性的变量,要确定好其实际范围,符号类型,来选择适当的数据类型及符号类型,不要将有符号和无符号的数进行比较。

先写到这儿吧,以后想到在更新吧。

关键字:AVR  编程感悟 引用地址:AVR编程感悟

上一篇:编程点滴:AVR的I/O端口操作测试程序
下一篇:AVR fuse位详解

推荐阅读最新更新时间:2024-03-16 15:16

AVR IO输出之蜂鸣器控制程序
系统功能 使用AVR控制一个蜂鸣器,能随心所欲控制蜂鸣器的鸣叫,不会让它乱叫! 硬件设计 关于AVR的I/O结构及相关介绍详见Datasheet,这里仅对作部分简单介绍,下面是AVR的I/O引脚配置表: DDRXn PORTXn PUD I/O 方式 内部上拉电阻 引脚状态说明 0 0 X 输入 无效 三态(高阻) 0 1 0 输入 有效 外部引脚拉低时输出电流 (uA) 0 1 1 输入 无效 三态(高阻) 1 0 X 输出 无效 推挽 0 输出,吸收电流 (20mA) 1 1 X 输出 无效 推挽 1 输出,输出电流 (20mA) 虽然
[单片机]
<font color='red'>AVR</font> IO输出之蜂鸣器控制程序
AVR串口 getchar(),getchar(),printf()等函数的使用
AVR串口 getchar(),getchar(),printf()等函数的使用 AVR单片机可以用getchar(),getchar(),printf()等函数,他们的操作默认会和串口连接起来。 需要包含stdio.h,ICC默认会包含这个文件,但是依然建议你写上这句#include stdio.h CODE: //ICC-AVR application builder : 2007-5-25 21:35:24 // Target : M16 // Crystal: 7.3728Mhz // 用途:演示getchar(),getchar(),printf()等函数的使用。 // 作者:古欣 // AVR与虚拟仪
[单片机]
<font color='red'>AVR</font>串口 getchar(),getchar(),printf()等函数的使用
AVR单片机对开关电源的控制方法
单片机控制开关电源,单从对电源输出的控制来说,可以有几种控制方式。 其一是 单片机 输出一个电压(经DA芯片或PWM方式),用作电源的基准电压。这种方式仅仅是用单片机代替了原来的基准电压,可以用按键输入电源的输出电压值,单片机并没有加入电源的反馈环,电源电路并没有什么改动。这种方式最简单。 其二是 单片机 扩展AD,不断检测电源的输出电压,根据电源输出电压与设定值之差,调整DA的输出,控制PWM芯片,间接控制电源的工作。这种方式单片机已加入到电源的反馈环中,代替原来的比较放大环节,单片机的程序要采用比较复杂的PID算法。 其三是 单片机 扩展AD,不断检测电源的输出电压,根据电源输出电压与设定值之差,输出PWM波,直接
[单片机]
<font color='red'>AVR</font>单片机对开关电源的控制方法
基于AVR单片机设计的电压电流功率表
测试范围:360.00V5A2000W 设计思路: 1、利用AVR单片机ATtiny26L一对差分AD做VI转换; 2、为了提高测试的速度,使用V1、I1、V2、I2.......V64、I64交错AD测试;取样时间是50Hz工频的整数倍; Vout = 1/64(V1+....+V64) Iout = 1/64(I1+....+I64) Pout = 1/128(V1*I0+V1*I1+V2*I1+V2*I2+.....+V64*I63+V64*I64) 3、电路增加了升压电路,将Li电提升到7.1V。增加Li电简单限压充电电路,使用外部电源时,升压电路停止工作; 4、利用内部EEPROM做校正数据保存。 单片机编程: T
[单片机]
基于<font color='red'>AVR</font>单片机设计的电压电流功率表
爱特梅尔推出全球最小的快闪AVR微控制器封装产品
爱特梅尔公司( Atmel Corporatio)宣布,全球最小的快闪AVR 微控制器 微控制器   一个微控制器,(也称作微处理器或MCU)就是一个小型的计算机,它由一系列简单的电路和一些支持CPU作用的简单模块组成,如晶体振荡器,定时器,看门狗,串行和模拟I / O口等等。芯片里包括非闪烁存储器和OTP ROM 用来存储程序,以及一个很小的读写程序。 封装产品开始投入生产。爱特梅尔的ATtiny4、ATtiny5、ATtiny9和ATtiny10 AVR微控制器 ( MCU MCU   MCU Microcontroller(微控制器)又可简称MCU 或μ C,也有人称为单芯片微控制器(S
[工业控制]
AVR c语言优秀编程风格
文件结构 模块化的程序应该是有一个很好的程序结构的。AVR C语言程序有两种用户文件,.c程序文件,.h头文件,程序中编写过程中需要在.c文件中包含.h头文件。初学者往往出现重复包含或者头文件包含错误的问题,我当时也时常为这种错误而发愁。下面我以我写的电机驱动例程来给大家说明一下,优秀的编程文件结构。 这个工程中有8个文件,一个说明文件,如下图:下载程序例子 电机控制案例 。 我写的成型的程序的文件个数基本上都是偶数,因为每一个结构化的函数定义.c文件都会对应一个.h文件。main.c对应config.h。我们来看看各文件的包含关系。下面我们看看这些文件的包含关系与内容: 所有.c文件都包含了config.h文件。如: #
[单片机]
<font color='red'>AVR</font> c语言优秀<font color='red'>编程</font>风格
基于AVR单片机硬件多机通讯功能的实现
通讯规则: 1:时钟7.3728MHz/波特率9600/9个数据位/奇校验/1个停止位/硬件多机通讯功能/ 2:通讯连接采用硬件MAX485,双向单工 3:每个上行/下行的数据包的字节个数都是一样的(通讯数据量) 4:每个上行/下行的数据包都采用CRC8校验 5:数据接收采用中断+查询的方式 6:总是由主机向从机发送一个数据包,从机收到数据包后向主机回复一个数据包 7:不管是主机还是从机,如果收到的数据包有任何错误,都将丢弃该数据包,等效于没有接收 8:从机之间不能相互通讯,必须通过主机才能交换数据 9:无效地址是0,主机地址是1,从机地址是2.3.4.。。.。。广播地址是255 */ #include #includ
[单片机]
基于<font color='red'>AVR</font>单片机硬件多机通讯功能的实现
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved