林夕依然AVR学习笔记移植笔记_1_第1页
林夕依然AVR学习笔记移植笔记_1_第2页
林夕依然AVR学习笔记移植笔记_1_第3页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、林夕依然atmega16学习笔记例程移植到atmel studio 6.2笔记相信你已经有了一定的c语言及数字电路基础,以及能定下心来,决心学点东西。如果做不到的话,麻烦您把我轻轻的放开,该干啥干啥去。前言最近学习avr,网上找了n多资料后,发现就算林夕依然atmega16学习笔记最合俺的心意。优点如下:1、 不讲原理,直接操作,适合俺这种不愿背书的差生。2、 每个例程都附有源程序及proteus仿真文件,省了买零件的金钱及焊板的时间。缺点当然也有:1、 太省事了,初学者容易只跑跑例程,不求甚解(这也是市售所有学习板的通病)。2、 基于iccavr,而不是最新的atmelstudio。3、 理

2、论知识太少(也算是优点)。还有一条就是这玩意是用exe文件打包的,初次下载时,我不敢打开,生怕会给我强装软件或者开个后门什么的。后来在网上下载了一个开发板的附带光盘文件,发现里面也带着这玩意。心想这里面不该会有问题呀,才不是太放心的打开,打开后发现相见恨晚呀!好吧,先把这些例程一个一个琢磨完吧。不过看程序时发现想打瞌睡,也难怪,看这玩意也太没挑战性了。既然我的电脑中装了atmelstudio,即然iccavr迟早要过时,不如把这里面的例程移植到atmelstudio中吧!顺便也可以学习一下编程。笔记不妨公开,俺也好刷一点成在感。本文中所有例程均在atmelstudio6.2+proteus7.

3、8中调试通过。本文是我个人学习时的笔记,希望后来者能少走一点弯路。学习mcu的惟一捷径是多读例程,多写程序,别无他法。林夕依然atmega16学习笔记下载链结如下:链接:/s/1eqbfb7k 密码:mzah实验1:8种led点亮模式1、 移植到atmelstudio中的步骤打开atmel studio 6.2,新建一个项目。不知道啥意思,我选第二个后,在下面起好项目名称及选好项目目录后ok。这个好办,按cpu型号选就好了。终于进入编辑窗口了。一言蔽之,提取包中所有.c(c源码)、.h(c头文件)、.dsn(proteus仿真文件)文件。atmelstud

4、io自己生成的那个.c文件要删掉,否则你懂的。移植的时候,要把头文件换一下,否则用不了所有的iom16v.h替换为avr/io.h所有#include 全部注释掉。有这一句的文件中,全部增加#define bit(x)(1 (x)当然了,移植的时候,我们懒得逐一去改bit,才这么将就一下。那么atmelstudio与bit()等价的命令是什么呢?打开sfr_defs.h文件,里面有一行:没错,atmelstudio中与bit等价的命令是_bv。再把随项目自动生成的那个c文件(含main函数的那个)删掉。main函数要改成int型。嗯,c99是这样规定的,新出的标准c编译器都得这么干,否则会有警

5、告。某个不仅仅是五百强的公司的编程规范中可是明文规定编译时不准有任何警告。按f7编译在项目目录中找到生成的hex文件,一般在debug子目录里,用proteus仿真。2、proteus仿真步骤假设已经装好proteus,我装的是7.8版本。双击打开包中的dsn文件。如上图所示,双击cpu,弹出下框。在program file中找到刚才编译出来的hex文件。然后点击ok。点击程序左下角的三角形图标开始仿真我们现在可以愉悦的看着led图标在欢快的上下滚动。3、知识点作为开山第一个实验,知识点会多一些,我会很认真的写,希望你能看懂。atmelstudio不支持直接对单个位进行操作,若要对单个位进行操

6、作,则要通过与或非的办法。小知识:iccavr位操作的宏定义/huangbin_1985/blog/static/1344470372010259113386/c语言位操作的功能是其比较出色的地方,现在许多微处理器都支持c编译器也可看出。汇编语言的位操作也很直观,但在某些c编译器对位操作却不能象汇编中对单个的位进行直接处理,而要转化为对一个字节的操作,在iccavr中这种限制充分体现出来。如要对porta的porta0置1,则应写成porta|=0x01;这样的位处在字节的两端还比较直观,但若是要置porta的第3位,第6位置1,则写出的程序可读性不强了。于

7、是便有了一些宏操作定义#define bit(x) (1 (x)(需要包含头文件macros.h)才可直接使用。下面给出两种置1和清0的宏定义:置1:1,#define set(x) (1(x)2,#define setb(temp,x) temp|=(1(x)清0:1,#define clr(x) (1(x)2,#define clrb(temp,x) temp&=(1(x)比较上述置1的两种宏定义,第1种在写1时需写成 porta|=set(x); x表示要处理的位,第2种更象函数,使用起来也比较直观:setb(porta,x), 可读性比较强 但是第2种却并非是万能的,以mega8515

8、为例,usart的ubrrh和ucsrc共用一个i/o location,在写ubrrh的时候最高位必须为0,写ucsrc时则正好相反。上述第2种的置1和清0操作只能对1 个bit进行操作,所以是不能处理ubrrh和ucsrc的写入工作的,而第1种置1和清0操作却可以通过或/与进行多个位操作的,比如写入ucsrc 0x01可以写作:ucsrc|=set(7)|set(0); 而如果用第2种宏定义则让它太为难了。两种方法有其利弊,使用的时候靠自己衡量了。#define checkbit(var,bit) (var&(0x01(bit) /*定义查询位函数*/#define setbit(var,

9、bit) (var|=(0x01(bit) /*定义置位函数*/#define clrbit(var,bit) (var&=(0x01(bit) /*定义清零位函数*/#define tglbit(reg,bit) reg=bit /*定义取反函数*/实验2:有源蜂鸣器驱动实验实验二很简单,移植也很简单,只要把所有#include 全部注释掉。所有的iom16v.h替换为avr/io.h,因为没有使用bit(),所以不用加相应的宏定义。main函数改为int型。程序就是这么个样子。void bell(void) portd&=(1pd5); delayms(50); portd|=(1pd5)

10、; delayms(50);int main(void) ddrd=0xff; portd=0xff; while(1) bell(); 其实bell()可以改得更简单一些,因为编译器不支持端口位操作,但是portd只接了个蜂鸣器,所以大可以把整个portd取反。portd=portd;虽然说编译器不支持端口位操作,不过我们可以牺牲点效率,用与或非的办法实现端口位操作。portd = _bv(pd5);可能会有人问pd5是什么意思,怎么定义的?在pd5上右击,点击goto implementation,会自动跳到pd5的定义。恩,pd5=5;下面是我改动过后的bell(),每一种方法都是可行的

11、。void bell(void)/方法一、原例,不停的输出高低电平portd&=(1pd5);/pd5等价于数值5,15表示把1左移五位。即000000015 = 00100000delayms(50);portd|=(1pd5);delayms(50);/方法二、对portd不停的取反portd=portd;/对整个端口取反delayms(50);/方法三、循环对单个端口置高低电平/编译器不支持对端口进行位操作,需要使用标准c语言中位操作的技巧,可以参看谭版c程序设计,位操作一章。portd |= _bv(pd5);/单独把pd5置高电平。delayms(50);portd &= _bv(p

12、d5);/单独把pd5置低电平delayms(50);/方法四、对单个位取反portd = _bv(pd5);/对单个端口进行取反操作delayms(50);实验3:按键扫描(用key选择对应led点亮)继续按实验一的方法处理:所有#include 全部注释掉,有这个头文件的地方增加宏定义#define bit(x)(1 (x)。所有的iom16v.h替换为avr/io.h。main函数改为int型。这个程序很简单,先初始化端口,然后循环运行key_scan函数。key_scan函数扫描所有有开关的端口,如果其中有一个为低电平的话,则将对应led点亮,之后检查pina有没有电平变化,如果有的话

13、,跳出while,然后重复上述流程。因为开关无论抖动几次,都不会影响结果,所以不需要防抖动。实验4:按键扫描+8种led亮灭模式控制移植方法与实验3一样一样的。程序是实验3与实验1的结合版本,很简单。实验5:按键扫描(用key选择led点亮模式)实验6:无源蜂鸣器驱动实验(icc)依电脑配置及设置不同,仿真时可能会有下列警告,表示仿真时间与实际时间不符。若把两个电阻属性改为数字的,警告会消失,不过声音会异常。实验7:外部中断int0实验这个实验就麻烦多了。先按照之前的套路:所有#include 全部注释掉,有这个头文件的地方增加宏定义#define bit(x)(1 (x)。所有的iom16v

14、.h替换为avr/io.h。main函数改为int型。因为main()调用了sei(),所以要增加宏定义:#define sei()asm(sei)atmelstudio的中断函数与iccavr不一样,需要改,如下图:前面还要增加一个头文件:#include isr表示是中断服务函数,所有中断服务函数必须叫这个名字,int0_vect表示int0入口,中断入口可以在iom16.h文件中找到(此为举例,实际cpu不同,文件名也会不同)。正常情况下,这样就大功告成了,实际仿真结果却与预期值大相径庭。预期值是程序运行后d0慢闪,按下int0键后,这一组led花样闪烁。实际仿真结果却是按下键后似乎毫无

15、反应,从逻辑分析仪上看,好像又有一点变化。我花费了好几个小时找资料排查,毫无所获,分析代码也没有发现任何问题,修改程序定位的结果delayms()好像没有执行。但是在main()中调用该函数却毫无问题。delayms()仅仅只是一个延时n毫秒的程序,其实我们完全可以用atmelstudio自带的库函数替代。在main.c与functions.c文件头上增加如下定义及头文件#define f_cpu 3686400ul#define _delay_backward_compatible_#include f_cpu表示cpu时钟频率,最后的ul代表无符长整型。后面一句可以参看下面的文章:/u010173859/article/details/20285627现在我们可以愉快的在这两个函数中调用_delay_ms()函数了,但是改后,结果还没有改善。好吧,现在把程序复原,然后回过头把这个程序再读一遍,发现这中断服务函数也太长了吧,长就算了,哪有中断服务程序加这么延时的?再者说,这函数内的变量也定义太多了吧?一个i不就得了。但是就算这样,也不该会出这种问题吧!接着上网查资料,死了无数脑细胞后,发现原来是atmelstudio编译时,认为延时函数没有做任何操作,将其忽略掉了。解决起来也很简单,在延时函数的变量前加入关键字volatile就好了。htt

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论