1.在汇编里面位造作用SEIPORTA3,把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里可以找到这样的定义"#defineOCR1A06",所以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,则无法用=直接赋值.
2.ICCAVR的macros.h里定义了一些有用的宏,如SEI(),其实是"asm("SEI")",此外还有CLI(),NOP()等等,大家可以去看看,顺便说说,ICCAVR嵌入汇编的格式是asm("汇编指令");
C里面我们把一些宏定义,函数的声明等写到.h头文件,而.c则是函数具体实现,当程序比较大时可以把一般函数和main函数分开,一起ADD到Project里面,便于管理.
3.ICCAVR里面的中断用#pragmainterrupt_handlerINTTERRUPT_NAME:INTERRUPT_NUM,INTERRUPT_NAME是自己取的中断函数名,
INTERRPT_NUM是所选中断的中断号,在DATAsheet里有..在这之后就可以写自己的中断函数体了.
4.在嵌入式的C程序编写里边,尽量少用float,double等等数据类型,可以用整数运算,到最后一步再除以10的多少次方得到所要的数.此外像sin,log这样的高级函数,虽然C编译器自动给你生成,不想汇编那样自己用加减移位来编写,但是对于这样的函数,C编译器会比较大的代码,所以尽量少用.除法运算若被除数是2的次方,可以用移位操作代替.
以上是我个人感觉写C时要注意的问题,希望对初写C的人有一些帮助