给AVR初学者

2008年11月16日 星期日 19:58
C语言现在因为其可读性,移植性,效率较高等特点越来越受到欢迎,但是还有一些人因为不了解C里面的一些操作,而坚持用汇编,所以有必要介绍一下在嵌入式C编程的一些技巧.



在汇编里面位造作用   SEI   PORTA   3,把PORTA的第三位置1 ,
在C里面,可以用&与|表达:
PORTA=PORTA|0x08,   简写为PORTA|=(0x08);  
PORTA=PORTB&(0xF7) 简写为PORTA&=0xF7

以上是对寄存器的某一位操作,当然也可以同时操作几个位, |0x0F ,则低四位置1;




在很多地方,如ATMEL的文档里我们会看到像TCCR1A|=(1<<COM1A0);//A比较匹配,

这样的操作,这是怎么回事呢?   

首先要知道<<   ,>>的意思,这是左移,右移操作,(A<<3)是把A的二进制数向左移3位,即乘以2的三次方.

COM1A0是TCCR1A的第6位,这是ATMEL给TCCR1A寄存器第6位取的名字,   在ICCAVR编译器的头文件iom16v.h里可以找到这样的定义"#define OCR1A0    6"   ,所以TCCR1A|=(1<<OCR1A0)的意思是把TCCR1A寄存器的第6位置1, 如果TCCR1A|=(1<<OCR1A0)|(1<<WGM10),那么WGM10同时也被置1;

而TCCR1A&=~(1<<OCR1A0)把第6位清零.   之所以我们要这样写而不写作TCCR1A|=0x40我想一是便于记忆,只记每一位的名字,不记在哪位,这样不容易错,便于对照DATAsheet检查程序.此外还更好移植,从一个系列的一个单片机到另一个单片机,只要控制某功能的位的名字不变,例如OCR1A0不管在哪个位置,此语句都实现OCR1A0置一的功能.

以上是某一个或几个位置一或清零操作,当然可以直接赋值,例如PORTA=0X0F,则是把低四位置1,高四位清零,这样看起来最简单但是对于我们想要改变某些位而不影响其它位的场合是不行的,例如1602液晶操作E和RS,还有数据等等,有严格的时间顺序,彼此要独立,按4data线统统接到PORTA,则无法用=直接赋值.




ICCAVR 的macros.h里定义了一些有用的宏,如SEI(),其实是"asm("SEI") ",    此外还有CLI(),NOP()   等等,大家可以去看看,顺便说说,ICCAVR嵌入汇编的格式是asm("汇编指令");

C 里面我们把一些宏定义,函数的声明等写到.h头文件,而.c则是函数具体实现,当程序比较大时可以把一般函数和main函数分开,一起ADD到Project里面,便于管理.




ICCAVR里面的中断用#pragma interrupt_handler INTTERRUPT_NAME:INTERRUPT_NUM,         INTERRUPT_NAME是自己取的中断函数名,

INTERRPT_NUM是所选中断的中断号,在DATAsheet里有..在这之后就可以写自己的中断函数体了.




在嵌入式的C程序编写里边,尽量少用float,double等等数据类型,可以用整数运算,到最后一步再除以10的多少次方得到所要的数.此外像sin,   log这样的高级函数,虽然C编译器自动给你生成,不想汇编那样自己用加减移位来编写,但是对于这样的函数,C编译器会比较大的代码,所以尽量少用.除法运算若被除数是2的次方,可以用移位操作代替.
PORTA=PORTA|0x08,   简写为PORTA|=(0x08);   
PORTA=PORTB&(0xF7) 简写为PORTA&=0xF7

TCCR1A|=(1<<COM1A0);

在嵌入式的C程序编写里边,尽量少用float,double等等数据类型,可以用整数运算,到最后一步再除以10的多少次方得到所要的数.此外像sin,   log这样的高级函数,虽然C编译器自动给你生成,不想汇编那样自己用加减移位来编写,但是对于这样的函数,C编译器会比较大的代码,所以尽量少用.除法运算若被除数是2的次方,可以用移位操作代替.

======================================================================================

以上LZ提到的事项与用51还是AVR无关,只要用C语言作为开发平台的话,在程序中都会出现这样的语句和尽量使用短类型的变量等。

以上的问题关键不在于使用AVR还是使用51,实际就是C语言编程能力本身的问题,在学校学的那点C,到了实用是远不够的,不管你是使用51,还是使用AVR。 呵呵,还发现一个小问题。那就是A&=0xf7和A&=~(0x01)生成的汇编代码是不一样的。我是在ICC上面试的,其它编译软件不知道会不会不一样。有兴趣可以自己发现一下。 首先是结果应该是一样的。不同的C平台产生的汇编代码是非常有可能不同的,这也说明了不同的C,效率上是有差别的。

作为初学者,首先应该把C本身的使用搞清楚,会使用。等到了有一定的经验和积累后,才能更深入的了解从C到汇编的更深入的问题,优化自己的程序。饭要一口一口的吃,基础要扎实全面,才能有真正的上升空间。 to 马老师
     有句话不知道该说,那就是作为老师来说,总感觉自己的学生应该注重基础,当然我也不是说不应该注重基础。只是有时候感觉老师一碰到什么与“基础无关”的东西都把它屏蔽掉了,总感觉这些内容与“学生”无关。结果就直接导致很多学生毕业之后才发现自己学的东西与现实之间的差距有多大,也就使得很多公司不敢要这些学生。这也算是教育界的定势吧。
     我感觉这些方面的内容应该多和学生交流,这样就会使学生更加信任老师。而不是只是感觉老师在念书。
     惭愧的说。我就是这种教育定势的受害者。开始是学生的时候没见过什么深入一点的东西,总感觉这些东西太简单了。以致于对毕业后的工作充满豪情壮志。过了几年才明白,原来学校里面学的东西真的是太…………。
     呵呵,说多了点。我也是有感而发。现在工作有两年了。22楼说的问题是我在工作的时候发现的,老师没和我说过。在用之前根本不会往这个方面去想。
     总之,个人感觉,初学者不一定是要把基础学牢了以后再上升,那样会失去很多的乐趣,而是应该交叉提升,当然,只要是对于有心的人。无心的人也只能学完基础就拜拜了。to lwfengbao:

我们现在的教育是一种应试教育的模式,造成这种状况是社会的问题。从学校角度讲,有教师的原因,也有学生的原因。

我不想和你讨论如何改变这种情况,我也无力、也不可能改变这种情况。我只是想在这里告诉大家,如果你真的喜欢和想成为真正的电子工程师的话,应该如何学习。能够到这里访问的网友,其学习的积极性可能比电子专业的大学生要高,所以我才强调要注意基础的学习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值