在匯編里面位造作用 SEI PORTA 3,把PORTA的第三位置1 ,
在C里面,可以用&與|表達(dá):
PORTA=PORTA|0x08, 簡寫為PORTA|=(0x08);
PORTA=PORTB&(0xF7) 簡寫為PORTA&=0xF7
以上是對寄存器的某一位操作,當(dāng)然也可以同時操作幾個位, |0x0F ,則低四位置1;
在很多地方,如ATMEL的文檔里我們會看到像TCCR1A|=(1<<COM1A0);//A比較匹配,
這樣的操作,這是怎么回事呢?
首先要知道<< ,>>的意思,這是左移,右移操作,(A<<3)是把A的二進(jìn)制數(shù)向左移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檢查程序.此外還更好移植,從一個系列的一個單片機(jī)到另一個單片機(jī),只要控制某功能的位的名字不變,例如OCR1A0不管在哪個位置,此語句都實(shí)現(xiàn)OCR1A0置一的功能.
以上是某一個或幾個位置一或清零操作,當(dāng)然可以直接賦值,例如PORTA=0X0F,則是把低四位置1,高四位清零,這樣看起來最簡單但是對于我們想要改變某些位而不影響其它位的場合是不行的,例如1602液晶操作E和RS,還有數(shù)據(jù)等等,有嚴(yán)格的時間順序,彼此要獨(dú)立,按4data線統(tǒng)統(tǒng)接到PORTA,則無法用=直接賦值.
ICCAVR 的macros.h里定義了一些有用的宏,如SEI(),其實(shí)是"asm("SEI") ", 此外還有CLI(),NOP() 等等,大家可以去看看,順便說說,ICCAVR嵌入?yún)R編的格式是asm("匯編指令");
C 里面我們把一些宏定義,函數(shù)的聲明等寫到.h頭文件,而.c則是函數(shù)具體實(shí)現(xiàn),當(dāng)程序比較大時可以把一般函數(shù)和main函數(shù)分開,一起ADD到Project里面,便于管理.
ICCAVR里面的中斷用#pragma interrupt_handler INTTERRUPT_NAME:INTERRUPT_NUM, INTERRUPT_NAME是自己取的中斷函數(shù)名,
INTERRPT_NUM是所選中斷的中斷號,在DATAsheet里有..在這之后就可以寫自己的中斷函數(shù)體了.
在嵌入式的C程序編寫里邊,盡量少用float,double等等數(shù)據(jù)類型,可以用整數(shù)運(yùn)算,到最后一步再除以10的多少次方得到所要的數(shù).此外像sin, log這樣的高級函數(shù),雖然C編譯器自動給你生成,不想?yún)R編那樣自己用加減移位來編寫,但是對于這樣的函數(shù),C編譯器會比較大的代碼,所以盡量少用.除法運(yùn)算若被除數(shù)是2的次方,可以用移位操作代替.