示例一
感谢阿莫的努力,使AVR-51多功能实验板能与大家见面。希望它能对大家学习和使用AVR或51(实际在上面可以使用任何DIP<40PIN的单片机)有帮助。这个学期我在学校也开AVR的课,我已经向网站定了50套,在整个学期中,每个学生都有一套实验板带回住所,我的AVR实验是家庭作业。第一次的课,就发了100M资料的光盘,规定了4篇必读的英文的文献(器件手册、AVR STUDIO ONLINE HELP、CVAVR USER MENU、CVAVR ONLINE HELP),因为考试中有15分为整理和翻译其中一段英文资料。
课堂上课每周3节,回家看资料,编写、调试程序至少要3个晚上,努力不努力就看你自己。反正学这门课不合算的。
随着上课,我会陆续将课上的例子贴上,作为配合该板的使用,提供从头开始学习AVR的网友参考。同时也会有一些讨论和思考,欢迎大家参加。
这里是第一个例子点击此处打开armok0139768.pdf。
关于硬件的讨论:
1。不用R1是否可以(RESET悬空)
2。LED的正端由I/O口控制,R3的一端接GND与现在的使用方式哪种好一些
3。R3的阻值在什么范围比较合适
4。如果控制一个3相的步进马达(5V/300MA),硬件电路如何设计
5。M16的熔丝位如何设置才能与使用的系统时钟源的类型相配合
软件的讨论:
1。第一句语句的作用是什么(指INCLUDE)?不用可以吗?如果不用,程序的开始应该如何写
2。M16DEF.INC文件在哪里,其内容是什么
3。程序中的RAMEND代表什么,在本程序中它的值是多少?从哪里来的。
4。
.org $0000 ;上电复位启始地址
rjmp reset ;转上电复位后的初始化程序执行
;中断向量区
.org $002A ;跳过中断向量区
reset:
ldi r16,high(RAMEND) ;取内部RAM最高地址的高位字节
out sph,r16 ;放入SP的高位
ldi r16,low(RAMEND) ;取内部RAM最低地址的低位字节
out spl,r16 ;放入SP的低位,SP中的值见器件配置文件“m16def.inc”
以上语句的作用是什么,后4句不要可以吗
5。仔细分析延时子程序的结构,运行情况,堆栈和堆栈指针的变化
-----此内容被machao于2005-03-05,13:42:28编辑过 搬个板凳,学习来啦 本人是汇编的菜鸟,把这个延时程序嵌入CVAVR中,编译时出错.而用CVAVR自带的delay.h编译后正常.请各位前辈指教.(程序中芯片的初始设置略.)
#include <mega16.h>
#define led PORTC.0
void delay_1s(void)
{#asm
ldi r16 197
delay:push r16
del1:push r16
del2:push r16
del3:dec r16
brne del3
pop r16
dec r16
brne del2
pop r16
dec r16
brne del1
pop r16
ret
#endasm
}
void main(void)
{DDRC.0=1;
while (1)
{
led=0;
delay_1s();
led=1;
delay_1s();
};
} 新手,我来的还真是时候. 马老师,提个汗颜的问题,为什么总是用R16来做数据传送的中转站
我的理解是R1~R16都胜任,因为AVR的寄存器组里,R1~R16是最“四通八达”的,考虑到一般使用寄存器的习惯,R16的使用频率最低,因此一般需要内容交换的时候,可以用R16来做中间传递 crazyeda:
R16就是顺手用而已,因此却是汇编中使用频率最高的寄存器。 4楼这个问题很好,有一定的深度。5楼的说明不在点上。先等等其他人的解释。 我想两端的寄存器都有特殊用途,例如r0,r1,r26-31,所以选择中间的寄存器如r16做内容交换。 我今年又要带领学生参加"中小学生电脑制作大赛"中的机器人比赛项目,今年我决定全部自己制作5个机器人,3个用来灭火,2个踢足球。芯片一律使用ATMEGA16L,现在硬件已经基本完成,正在考虑设计程序。
我的思路如下:
1、灭火:输入部分:使用4个地面光感,用来检测房门白线,同时可以粗略校正机器人的方向;一个车轮编码(用T0进行计数,用以控制转弯以及检测运行距离);8个火源检测,同时监视8个方位,以节省机器人转向的时间;5个避障开关,前、左前、右前、左后、右后;还有一个MIC输入,用声音来启动机器人;
输出部分:电机驱动采用L293D,4个端口控制两个电机的运行方向,T1使用8位PWM,由OC1A和OC1B分别控制两个电机的运行速度;一个声音输出端口,使蜂鸣器发声;一个灭火风扇电机驱动端口,当机器人确定正前方是火源时便启动灭火风扇进行灭火;
2、足球:输入部分:使用1个电子指南针,用来检测机器人的方位;使用2个超声波测距卡,用来检测前方和左侧的距离;8个光电检测,用来寻找足球;4个碰撞开关,用来避免碰撞;
输出部分:电机驱动采用L298N,4个端口控制两个电机的运行方向,T1使用8位PWM,由OC1A和OC1B分别控制两个电机的运行速度。
马老师以及各路高手能否给我点建议和意见,不胜感激! 再来详细解释一下:
R0~R15这低16个寄存器不能装载常数
R16~R31 这高16个寄存器能做所有功能
但其中的R26~R31 为X,Y.Z指针,很珍贵,不能乱用
所以R16~R25都可以用作普通数据处理--------------相当于有10个51的ACC累加器
而R16是第一个,用得最顺手,就默认成规了。 hehe,马老师会不会到时候也贴答案呀! 怎么没人回答问题呢
我来说两个把
1 CMOS器件不能象TTL器件一样不用的脚可以悬空
否则将引入干扰,照成该引脚的电平不确定.所以应该接上拉或下拉电阻
如果RESTE悬空会造成电路复位不稳定
第二个问题涉及到驱动的问题,大部分的单片机的IO口在低电平时的驱动能力更强
所以电路应该设计成灌电流模式即低电平驱动要好.
小弟在此献丑了
不对之处请各位大虾指点 9楼的解释非常正确。在AVR中,32个通用寄存器实际上功能还是有一些不同,在使用汇编时应特别注意。其中R16-R25功能更多一些,如可以装载立即数,完成乘法指令等。
另外再谈谈如何学习单片机。我认为,最重要的是要学到如何发现问题后,自己能够去找到问题的所在,分析出出现问题的原因,从而去解决之的方法和习惯。
以R16使用的问题为例,当我有疑问或发现问题是,我会首先自己动手,将程序中所有的R16换成R0试一下。此时你会发现编译的错误,知道出现在给R0赋值这句。这样你就会去(或再次)仔细看AVR的汇编指令,去找到R0和R16的区别,你就会进一步的总结和归纳出32个寄存器的特点了。
我提倡这种学习态度,而不是先去问别人。因为当你自己开发设计产品时,会出现各种的问题,其原因可能出现在硬件上,也可能在软件上,最主要的还是要靠你自己的努力,学会自己思考、自己如何通过测试,去找出问题和解决方法。
我提出的讨论题,更希望大家能通过自己的思考,经过讨论获得答案。如果直接给出答案,其意义就不大了。 谢谢11楼。2个问题回答是正确的。
再给出更深层次的资料参考:
1。涉及到提高系统抗干扰和稳定问题的设计。点击此处打开armok0139970.pdf
其中有RESET脚的接法。
2。更多关于使用AVR的I/O口大电流驱动时注意的事项(摘自器件手册)
*3. 虽然在稳定状态条件(非瞬态)下每个I/O端口都可以吸收比测试条件下更多的电流(20 mA,VCC = 5V 以及10 mA, VCC = 3V) ,
但是需要遵循以下要求:
PDIP 封装:
1] 所有端口的IOL 总和不能超过400 mA
2] 端口A0 - A7 的IOL 总和不能超过200 mA
3] 端口B0 - B7,C0 - C7, D0 - D7 与XTAL2 的IOL 总和不能超过300 mA
TQFP 与MLF 封装:
1] 所有端口的IOL 总和不能超过400 mA
2] 端口A0 - A7 的IOL 总和不能超过200 mA
3] 端口B0 - B4 的IOL 总和不能超过200 mA
4] 端口B3 - B7, XTAL2, D0 - D2 的IOL 总和不能超过200 mA
5] 端口D3 - D7 的IOL 总和不能超过200 mA
6] 端口C0 - C7 的IOL 总和不能超过200 mA
如果IOL 超出了测试条件, VOL 可能超过指标。不保证引脚可以吸收比列于此处的测试条件更大的电流。
*4. 虽然在稳定状态条件(非瞬态)下每个I/O端口都可以输出比测试条件下更多的电流(20 mA,VCC = 5V 以及10 mA, VCC = 3V) ,
但是需要遵循以下要求:
PDIP 封装:
1] 所有端口的IOH 总和不能超过400 mA
2] 端口 A0 - A7 的IOH 总和不能超过200 mA
3] 端口 B0 - B7,C0 - C7, D0 - D7 与 XTAL2 的IOH 总和不能超过 300 mA
TQFP 与MLF 封装:
1] 所有端口的IOH 总和不能超过400 mA
2] 端口 A0 - A7 的IOH 总和不能超过200 mA
3] 端口B0 - B4 的IOH 总和不能超过200 mA
4] 端口B3 - B7, XTAL2 与D0 - D2 的IOH 总和不能超过200 mA
5] 端口D3 - D7 的IOH 总和不能超过200 mA
6] 端口 C0 - C7 的IOH 总和不能超过200 mA。如果IOH 超出了测试条件,VOH 可能超过指标。不保证引脚可以输出比列于此
处的测试条件更大的电流。
以上在实际设计系统时应该考虑和注意。
-----此内容被machao于2005-03-05,14:20:12编辑过 请教马老师,Atmega16的RESET应该有内置的上拉电阻见datasheet的英文版第36页,是否可以把R1省略呢?
http://cache.amobbs.com/bbs_upload782111/files_1/armok0139971.GIF 是可以把R1省到,但要提高抗干扰性,应该将RESET同VCC连接,见13楼的英文参考。
我一般使用R1,这样在调试中,需要时用连线将RESET同GND短路一下,实现了手动的RESET。如果RESET直接连到VCC,就无法实现外部的RESET控制了。 谢谢马老师。很多问题,自己平时都只是胡囵吞枣的看过,老师提出后再查书。收益很多。谢谢!! 马老师您好:
我要用ATmega8的pwm输出控制220v~50Hz交流,怎么实现精确控制?用moc3063光耦,BTA16的可控硅。 像datasheet上的reset脚接法,好像不能人工手动复位哦,在电容旁边加个按钮问题不大吧?
还有他电源的滤波加入了一个电感,有必要吗? 给maochao老师找的bug
.include "m16def.inc" ;包括器件配置定义文件,不能缺少
.def temp1=r20 ;定义寄存器R21用临时变量名temp1代表
【tjww】这里面是R20,而非R21 谢谢。这是笔误,上传的是初稿。但不能算BUG,因为程序没问题,只是解释出了问题。正确改正:
.include "m16def.inc" ;包括器件配置定义文件,不能缺少
.def temp1=r20 ;定义寄存器R20用临时变量名temp1代表
欢迎继续指正。 马老师:
我在AVR Studio中debug你的例子的时候,觉得运行的好慢!
我把ldi r16 197 中的延时参数197改为7后才看到PORTC.0一动一动的,
在调试的时候需要在AVR Studio中怎样设置才能跟真实情况一样呢?(我是指指令运行速度)
谢谢您的指导! 你已经在掌握软件模拟的经验了。
软件模拟不能达到硬件那样的速度,尤其是模拟延时程序。以本例来讲,正确的调试方式为:
1.将延时参数197改为3,然后单步执行每一句语句,查看程序的逻辑对不对,能否正确运行,堆栈是如何工作的,SP指针如何变化,各个寄存器如何变化,PC的变化,RAM中数据的变化。这样即了解了AVR的工作原理,也了解程序设计的技巧(学别人的),或验证程序是否同自己想象的那样正确(自己编的),而且训练了如何熟练使用DEBUG(熟练使用工具也是很重要的一环)。
2.验证了整个程序没有逻辑错误时,可以查看延时子程序的延时时间了。
A。将延时参数由3改回197;
B。在调用该子程序的语句上rcall delay设置一个断点;在接下来的一个语句上sbi portc,0设置第二个断点;
C。全速运行程序;
D。当程序在断点处第一次停下时,到查看Processor的选项中(打开该图标)找到Stop Watch,双击将其清另;
E。从断点处继续全速运行程序;
F。要等了,大约十几秒或几十秒后(看你的PC速度了,在我的机器上为45s),程序在第二个断点处停下;
G。查看Processor的选项中的Stop Watch,它记录下调用子程序返回后的时间。
由此验证了延时子程序的执行时间。调节延时参数,可以得到不同的延时时间,通过软件模拟可以精确的得到。这比使用在线实时仿真的手段要方便多了,而直接在目标板上运行,你也不能得到精确的时间。
使用软件模拟,是现在调试技术的发展方向。当你了解和熟练掌握使用AVR Studio后,你的设计研发速度会提高,硬件系统和软件编程可以平行开展,当硬件完成了,你的软件也完成了60-70%。
-----此内容被machao于2005-03-17,02:19:00编辑过 【2楼】的ynkmyfk,
你的问题:
1。 ldi r16 197 ===》ldi r16,197
2。 ret ====> 去掉。 在CVAVR中,建立函数时自动加上了RET,不用你再加了。
CVAVR中有延时程序,用此程序的目的只能在于学习如何将C和汇编混用。建议你看AVCVR中的HELP帮助,它给出了如何在CVAVR中使用汇编的介绍和例子。
另外,作为进一步的学习,你能否写一个带参数的void delay(char t)函数,函数还是使用汇编。当调用时,delay(197)延时1s,改变参数,延时的时间不一样的。完成后贴上让大家学习,作为如何在CVAVR中使用汇编的参考?
且当做老师的给你一个作业,你要完成的。
学习过程是互动的,学习单片机更需要自己思考、消化和动手实践。我只能带带各位入门了,指个方向。碰到问题先要自己尝试着去解决的,象上面第一个BUG,应该能自己处理的,第2个问题可以问,但先看一下HELP的话自己也能解决了。
实例一我出了10个问题,仅有一人回答了2个问题,其它沉入大海,有点悲哀了。
-----此内容被machao于2005-03-17,01:28:34编辑过 马老师:是否应该把
void delay(char t);
改为:
void delay_1s(unsigned char t)
不然delay(197)是负数。
先贴上我的作业,老师指教。
#pragma warn- // this will prevent warnings
void delay_1s(unsigned char t)
{#asm
ldr16, y
delay:push r16
del1:push r16
del2:push r16
del3:dec r16
brne del3
pop r16
dec r16
brne del2
pop r16
dec r16
brne del1
pop r16
#endasm
}
#pragma warn+ // enable warnings 我偷懒了,在CVAVR中,缺省的定义char等同与unsigned char。不过使用unsigned char是标准的表示方法,应该提倡。
另请你整理个贴子,仔细介绍如何在CVAVR中嵌入汇编?C和汇编之间的参数调用方法,以及注意点如何? 马老师,不要悲哀,我也是做老师的,您的心情我能理解。在这里我也就是您的学生,
您的意见我们都虚心接受,其实您出的那些题目,我都仔细思考过,只不过在论坛上养成了
一些习惯:不懂的问题不会随便说,等着看别人是怎么答的;懂的,也只是在心里面衡量衡量,
算是自测。您出的问题思考性针对性很强,希望您一如既往的做下去!
我是初学者,说说吧:
1。R1让单片机更稳定,防止RESET受干扰而复位;
2。atmle系列单片机的端口输入电流一般为20mA左右,而输出电流要小一些,为10mA左右,
如果直接驱动LED的话,现在的方式要好一些。(分别叫灌电流和拉电流是吗?)
3。R3的阻值应限制LED的电流在20mA以内。一般在200欧到600欧之内。(VCC=5V时,等实验板
收到后,我要亲自调试测量)
4。考虑用达林顿管增大驱动电流。(步进电机了解一点,3相的需要占用三个端口吧?那么
要设计三条独立的线路),如果电机更大,220/380,可以用光偶、继电器…………
5。查数据手册,手册上讲的详细,所以没仔细看。待收到实验板后,再小心翼翼的搞,反正有
手册。
软件:
1。因为不同的芯片硬件资源不尽相同,为了便于阅读和移植,用通用的符号为各种资源(我想
主要是“地址”类的吧?)做了定义,如果不要这一句,就要把M16DEF.INC中的全部内容复制
过来,(但是想把这个程序移植到M8或其它芯片上,又得改不少东西了)
2。在“Program Files\Atmel\AVR Studio\Appnotes”里面,其他编译器里面也应该有吧?
3。在M16DEF.INC文件中有“.equ RAMEND =$45F”从字面上看是RAM的“结束地址”
我不知到是最高还是最低,呵呵(您的注解让我看糊涂了),值是$45F
4。在51里面没这么烦琐,没这么个步骤,我不知道作用,等会试试看
5。昨晚调试了的,今晚再按你的指点调试(设置断点) 那四句是定义堆栈地址的吗?去掉那四句,程序执行到rcall delay 就出不来的,估计跟push和
pop有关,请马老师给我们讲讲,手里几乎没有这方面的书 哎,我看书不仔细,在你的教程上讲了的(第2章18面)。我再看看……
-----此内容被chen于2005-03-17,23:04:59编辑过 2。LED的正端由I/O口控制,R3的一端接GND与现在的使用方式哪种好一些
答:看过一本书,说是有移植性好的有点。 【26楼】chen 陈老师:
昨天我贴上三章内容,您是第一个下载的。由于我看错了目录,第一次实际上我贴上的是2-3年之前的底稿。后来我马上发现了,立即将最新改的版本贴上了。请您核对一下,希望您看新的,因为它是按M16为主线介绍的,原来的以90S8515,早期的产品,许多功能不强。这也是我把底稿压了2-3年的原因之一。
前三章主要是让大家对AVR的结构有个初步的认识,从基本知识、硬件结构、到指令系统做了基本的介绍,使大家有一定的基础进入下面的学习和实践。示例一的一些问题的答案,在这三章中大都有解答和介绍的。
与51相比,AVR复杂,入门相对困难,但这是技术和实力的发展。我们使用的PC从8088发展到P4,软件从DOS发展到WINXP,INTEL和微软还在不断努力推新的东西,他们为什么不说P4比8088复杂,WINXP比DOS复杂,而躺在8080和DOS上不动呢。
从某种意义上讲,我们学习使用单片机就是在做类似INTEL和微软的事情,因为单片机就是一块芯片,它没有任何的程序,我们是从零开始,构建一个专用的计算机系统。使用51能构建一台类似8088运行DOS的PC(当然它已经能满足许多的应用了),而使用AVR能构建一台类似P2运行WIN3x的PC。如果说AVR复杂,那么我们就不要谈使用32位的ARM去构建P4运行WINXP的PC了(不知道这样的比喻是否恰当)。
您也是老师,没想到第一次的“作业”仅成为老师与老师之间的交流了,可见我们现在的教育“成果辉煌”。行,就当我们两个老师做表演吧:我扮演“老师”;您扮演“学生”,可我绝对不敢把您当做学生的,希望对我写的东西提出意见和建议。
谢谢! dengxihua 邓细华:
“用ATmega8的pwm输出控制220v~50Hz交流,怎么实现精确控制?用moc3063光耦,BTA16的可控硅”,这可是个研究生级的论文题目了。“精确控制”要达到什么要求? 顶上 mark,以后学习 软件的讨论:
1。第一句语句的作用是什么(指INCLUDE)?不用可以吗?如果不用,程序的开始应该如何写
2。M16DEF.INC文件在哪里,其内容是什么
3。程序中的RAMEND代表什么,在本程序中它的值是多少?从哪里来的。
4。
.org $0000 ;上电复位启始地址
rjmp reset ;转上电复位后的初始化程序执行
;中断向量区
.org $002A ;跳过中断向量区
reset:
ldi r16,high(RAMEND) ;取内部RAM最高地址的高位字节
out sph,r16 ;放入SP的高位
ldi r16,low(RAMEND) ;取内部RAM最低地址的低位字节
out spl,r16 ;放入SP的低位,SP中的值见器件配置文件“m16def.inc”
以上语句的作用是什么,后4句不要可以吗
5。仔细分析延时子程序的结构,运行情况,堆栈和堆栈指针的变化
1, 汇编的第一行.include "m128def.inc" 表示你这段程序运行在那个型号的AVR 上,不同的型号, 很多默认的变量是没有的。
RAMEND 所代表的值也不一样。
2,M16DEF.INC 简单的说就是名字对物理地址的翻译文件,相同的名字,对于不同的单片机,地址是不一样的。
3,RAMEND 就是RAM 的末端,也就是最高位地址,每个机型都不一样。M128 的是 0x10ff
4,根据芯片手册,未配置BOOT 熔丝位的芯片,上电第一句是从 0000 开始执行,但是中断向量标必须放在头部程序空间。(默认配置) 所以第一句是一个跳转指令,后面的4句是指定堆栈地址,是从RAM最高位开始使用的,不写这个,你就不能用PUSH 了。
第5条没看例子,呵呵,马老师,我也是最近开始学 AVR, 一直都是用AVR STUDIO 的汇编在编写程序。我觉得用汇编,一个模块 一个模块的写,主意一下寄存器,不要冲突了,也是蛮好用的。
页:
[1]