电竞比分网-中国电竞赛事及体育赛事平台

分享

IAR FOR AVR

 diligent_wzh 2011-03-28

IAR for AVR 學(xué)習(xí)筆記(1--數(shù)據(jù)類型


數(shù)據(jù)類型(編譯器支持 ISO/ANSI C 基本數(shù)據(jù)類型和一些附加數(shù)據(jù)類型)

 

11. 整型數(shù)據(jù)

bool 數(shù)據(jù)類型在C++語言里是默認(rèn)支持的。如果你在C代碼的頭文件里包含stdbool.h, bool數(shù)據(jù)類型也可以使用在C語言里。也可以使用布爾值 false true。

 

12.浮點(diǎn)數(shù)據(jù)類型:

 

13.指針類型:指針有數(shù)據(jù)指針和函數(shù)指針。
1
、數(shù)據(jù)指針:
數(shù)據(jù)指針的大小為8位,16位,24位。定義為:在整型數(shù)據(jù)類型后加”*”符號(hào)。
例如:char * p;
整型數(shù)據(jù)沒有24位,具體定義指針見后面擴(kuò)展關(guān)鍵字章節(jié)。
2
、函數(shù)指針:函數(shù)指針的大小為16位,24位。
指針定義:在函數(shù)類型后加”*”符號(hào)

 

IAR for AVR 學(xué)習(xí)筆記(2--擴(kuò)展關(guān)鍵字

        可以用來解決數(shù)據(jù),函數(shù)的存放等。有了它我們就可以定義變量存放在EEPROM,FLASH空間。定義中斷函數(shù),指針等等。IAR關(guān)鍵字很多,這里只列舉常用的。

21.?dāng)U展關(guān)鍵字:用于控制數(shù)據(jù)和指針。
__eeprom
用于EEPROM 存儲(chǔ)空間, 控制數(shù)據(jù)存放,控制指針類型和存放
__tinyflash, __flash, __farflash, __hugeflash
用于flash 存儲(chǔ)空間, 控制數(shù)據(jù)存放,控制指針類型和存放:
__ext_io, __io
用于I/O存儲(chǔ)空間, 控制數(shù)據(jù)存放,控制指針類型和存放
__regvar
放置一個(gè)變量在工作寄存器中

22.函數(shù)擴(kuò)展關(guān)鍵字:。
__nearfunc __farfunc
用于控制數(shù)據(jù)存放,這組關(guān)鍵字必須在函數(shù)聲明和定義的時(shí)候指定:
__interrupt.
關(guān)鍵字控制函數(shù)的類型。這組關(guān)鍵字必須在函數(shù)聲明和定義的時(shí)候指定
__root.
關(guān)鍵字僅僅控制有定義的函數(shù):

23.其它特別的關(guān)鍵字:
@
用于變量的絕對(duì)地址定位。也可以用#pragma location 命令
#pragma vector
提供中斷函數(shù)的入口地址。
__root
保證沒有使用的函數(shù)或者變量也能夠包含在目標(biāo)代碼中
__no_init
禁止系統(tǒng)啟動(dòng)的時(shí)候初始化變量.
asm, __asm
插入?yún)R編代碼

 

IAR for AVR 學(xué)習(xí)筆記(3--位操作

3.1.在c語言里對(duì)位的操作如一般如下:
PORTB|=
1<<2;//PORTB的第2=1
PORTB&=~
1<<2;//PORTB的第2=0
PORTB^|=
1<<2;//取反PORTB的第2
While(PORTB&(1<<2));//
判斷1
While(!(PORTB&(1<<2)));//
判斷為0

3.2IAR編譯器對(duì)位的支持更強(qiáng)大,除了上面的方法外還有以下更簡(jiǎn)單的操作方法:
PORTB_ Bit2=1; //
PORTB的第2=1
PORTB_ Bit2=0; //
PORTB的第2=0
PORTB_ Bit2=~ PORTB_ Bit2;//
取反PORTB的第2
While(PORTB_ Bit2);
或者while(PORTB_Bit2==1);//判斷1
while(PORTB_ Bit2==0);//
判斷0
PORTC_Bit4=PORTB_Bit2;//
PORTB的第2位傳送到PORTC的第4

3.3.位變量定義:
由于iar使用了擴(kuò)展語言,它對(duì)位域的支持變?yōu)樽钚?span lang="EN-US">char
類型,我們可以很方便地用來定義位變量。
采用結(jié)構(gòu)體來定義位變量:
struct
{
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char bit3:1;
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
}t;
然后就可以用以下位變量了。
t.bit0=1;
t.bit0=~t.bit0;
但是采用以上結(jié)構(gòu)體做出來的位變量只可以訪問t的位,不能夠直接訪問變量t,和標(biāo)準(zhǔn)的IAR位操作也不一樣。采用聯(lián)合體來定義效果更佳。
i nclude<iom8.h>
union
{
unsigned char t;
struct
{unsigned char t_bit0:1,
t_bit1:1,
t_bit2:1,
t_bit3:1,
t_bit4:1,
t_bit5:1,
t_bit6:1,
t_bit7:1;
};
};
void main(void)
{
t_bit0=1;//
訪問變量t的位
t_bit0=~t_bit0;
PORTB=t;//
直接訪問變量t
}
位變量也可以直接定義在工作寄存器里。

3.4 bool 數(shù)據(jù)類型在C++語言里是默認(rèn)支持的。
   
如果你在C代碼的頭文件里包含stdbool.h, bool數(shù)據(jù)類型也可以使用在C語言里。也可以使用布爾值 false true。不過是占用81個(gè)字節(jié)。
i nclude<iom8.h>
i nclude<stdbool.h>
bool y=0;//
定義位變量
void main(void)
{
y=!y;//
取反位變量
PORTB_Bit3=y;//
傳遞位變量
}

IAR for AVR 學(xué)習(xí)筆記(4--Flash操作

FLASH常用類型的具體操作方法

41FLASH 區(qū)域數(shù)據(jù)存儲(chǔ)。
用關(guān)鍵字 __flash 控制來存放, __ flash 關(guān)鍵字寫在數(shù)據(jù)類型前后效果一樣
__flash unsigned char a;//
定義一個(gè)變量存放在flash空間
unsigned char __flash a;//
效果同上
__flash unsigned char p[];//
定義一個(gè)數(shù)組存放在flash空間
對(duì)于flash空間的變量的讀操作同SRAM數(shù)據(jù)空間的操作方法一樣,編譯器會(huì)自動(dòng)用
LPM
ELPM 指令來操作。
例:
i nclude<iom8.h>
__flash unsigned char p[];
__flash unsigned char a;
void main(void)
{PORTB=p[1];//
flash 數(shù)組變量的操作
PORTB=a;//
flash 變量的操作
}
由于在正常的程序中,flash 空間是只讀的,所以沒有賦值的變量是沒有意義的。定義常數(shù)在flash 空間,只要給變量賦與初值就可以了。由于常數(shù)在flash空間的地址是隨機(jī)分配的,讀取變量才可以讀取到常數(shù)值。
10
IAR-AVR –C
編譯器簡(jiǎn)要指南
__flash unsigned char a=9;//
定義一個(gè)常數(shù)存放在EEPROM空間。
__flash unsigned char p[]={1
,2,3,4,56,78};
//
定義一個(gè)組常數(shù)存放在flash 空間。
例:
i nclude<iom8.h>
__flash unsigned char p[]={1,2,3,4,5,6,7,8};
__flash unsigned char a=9;
void main(void)
{
   PORTB=a;//
讀取flash 空間值9
   PORTC=p[0]; //
讀取flash 空間值
}

4.1.2flash 空間絕對(duì)地址定位:
__flash unsigned char a @ 0x8;//
定義變量存放在flash 空間0X08單元__flash unsigned char p[] @ 0x22//定義數(shù)組存放在flash 空間,開始地址為0X22單元
__flash unsigned char a @ 0x08=9;//
定義常數(shù)存放在flash 空間0X08單元
__flash unsigned char p[] @ 0x22={1
,2,3,4,5,67,8};
//
定義一個(gè)組常數(shù)存放在EEPROM空間開始地址為0X22單元
由于常數(shù)在flash 空間的地址是已經(jīng)分配的,讀取flash 空間值可以用變量和地址。

42.與 __flash 有關(guān)的指針操作。 __flash 關(guān)鍵字控制指針的存放和類型。
4.2.1
指向flash 空間的指針flash 指針(控制類型屬性)
unsigned char __flash * p;//
定義指向flash 空間地址的指針,8位。
unsigned int __flash * p;//
定義個(gè)指向flash 空間地址的指針,16位。
unsigned int __farflash * p;//
定義指向flash 空間地址的指針,24位。
unsigned int __hugeflash * p;//
定義指向flash 空間地址的指針,24位。
unsigned char __flash * p;//
定義一個(gè)指向flash 空間地址的指針,指針本身存放在SARM中。P的值代表flash 空間的某一地址。*p表示flash 空間該地址單元存放的內(nèi)容。例:假定p=10,表示flash空間地址10單元,而flash M空間10單元的內(nèi)容就用*p來讀取。
例:
i nclude<iom8.h>
char __flash t @ 0x10 ;
char __flash *p ;
void main(void)
{
PORTB=*p;//
讀取flash 空間10單元的值
PORTB=*
p+3;//讀取flash 空間0x13單元的值
}

4.2.2.存儲(chǔ)于flash 空間的指針數(shù)據(jù)指針
就象存儲(chǔ)與flash 空間的數(shù)據(jù)一樣控制存儲(chǔ)屬性
__flash unsigned char * p; //
定義指向SARMM空間地址的指針,指針本身存放在flash 中。

43.控制數(shù)據(jù)和指針存放的__flash 定義必須是全局變量,控制類型屬性(好像只有指針)可以是局部變量。
i nclude<iom8.h>
__flash unsigned char p;//
控制存放
void main(void)
{
unsigned char __flash* t;//
控制屬性
PORTB=p;
PORTB=*t;
}

44 __root 關(guān)鍵字保證沒有使用的函數(shù)或者變量也能夠包含在目標(biāo)代碼中.
定義存放在__flash 空間的數(shù)據(jù)在程序編譯時(shí)會(huì)自動(dòng)生成代碼嵌入到flash代碼中,對(duì)于程序沒有使用也要求編譯的數(shù)據(jù)(比如可以在代碼中嵌入你的版本號(hào),時(shí)間等)必須加關(guān)鍵字__root 限制。
例:
i nclude<iom8.h>
__root __flash unsigned char p @ 0x10 =0x56;
void main(void)
{}
程序沒有使用P變量,編譯也會(huì)生成該代碼。
:020000020000FC
:1000000016C018951895189518951895189518955F
:10001000569518951895189518951895189518953A
:10002000189518951895089500008895FECF0FE94A
:100030000DBF00E00EBFC0E8D0E003D0F4DFF4DF76
:06004000F3CF01E008957A
:0400000300000000F9
:00000001FF

45flash 操作宏函數(shù):在comp_a90.h intrinsics.h頭文件里有詳細(xì)說明。flash 空間具正常情況下有只讀性能,對(duì)于讀flash 數(shù)據(jù)編譯器會(huì)自動(dòng)編譯對(duì)應(yīng)的LPM,ELPM指令,但對(duì)于flash 空間的自編程寫命令SPM就沒有對(duì)應(yīng)的C指令了,這里不講解詳細(xì)的自編程方法,只是講解一下對(duì)flash 的讀寫函數(shù)。
直接在程序中讀取flash 空間地址數(shù)據(jù):要包含intrinsics.h頭文件
__load_program_memory(const unsigned char __flash *);//64K
空間
//
從指定flash 空間地址讀數(shù)據(jù)。該函數(shù)在intrinsics.h頭文件里有詳細(xì)說明。
comp_a90.h文件有它的簡(jiǎn)化書寫_LPM(ADDR)。注意匯編指令LPM Rd ,Z中的Z是一個(gè)指針。所以用(const unsigned char __flash *)來強(qiáng)制轉(zhuǎn)換為指向flash空間地址指針。故該條宏函數(shù)的正確寫法應(yīng)該如下:
__load_program_memory(
const unsigned char __flash *ADDR);
例:
i nclude<iom8.h>
i nclude <intrinsics.h>
void main(void)
{PORTB=__load_program_memory((const unsigned char __flash *)0x12);
}
該條函數(shù)書寫不方便,在comp_a90.h文件有簡(jiǎn)化:
#define _LPM(ADDR) __load_program_memory (ADDR)
稍微方便一點(diǎn)。改為
#define _LPM(ADDR) __load_program_memory ((const unsigned char
__flash *)ADDR)
就更方便了,直接使用數(shù)據(jù)就可以了。
例:
i nclude<iom8.h>
i nclude<comp_a90.h>
i nclude<intrinsics.h>
void main(void)
{
PORTB=__LPM(0x12);//
從指定flash 空間地址單元0x12中讀數(shù)據(jù)
}
__extended_load_program_memory(const unsigned char __farflash *);
//128K
空間_ELPM(ADDR); //128K空間
參照上面的理解修改可以書寫更簡(jiǎn)單。

4.6.自編程函數(shù):
_SPM_GET_LOCKBITS()
;//讀取縮定位
_SPM_GET_FUSEBITS()
//讀取熔絲位
_SPM_ERASE(Addr)
;//16位頁擦除
_SPM_FILLTEMP(Addr,Word)
//16位頁緩沖
_SPM_PAGEWRITE(Addr
;)//16位頁寫入
_SPM_24_ERASE(Addr)
//24位頁擦除
_SPM_24_FILLTEMP(Addr,Data)
; //24位頁緩沖
_SPM_24_PAGEWRITE(Addr) //24
位頁寫入

IAR for AVR 學(xué)習(xí)筆記(5--SRAM操作

SARM數(shù)據(jù)類型的具體操作方法

    SARM空間是AVR單片機(jī)最重要的部分,所有的操作必須依賴該部分來完成。變量在SARM空間的存儲(chǔ)模式有tiny ,small large 三種,也就是對(duì)應(yīng)于__tiny, __near __far三中存儲(chǔ)屬性。一旦選擇為哪種存儲(chǔ)模式,對(duì)應(yīng)的數(shù)據(jù)默認(rèn)屬性也就確定了,但可以采用__tiny, __near __far關(guān)鍵字來更改。
對(duì)于程序中的局部變量,編譯器會(huì)自動(dòng)處理的,我們也不可能加什么儲(chǔ)存屬性,但IAR提供了強(qiáng)大的外部變量定義。

51.定義變量在工作寄存器
IAR
編譯器內(nèi)部使用了部分工作寄存器,留給用戶的只有R4-R1512個(gè)寄存器供用戶使用,要使用工作寄存器必須在工程選項(xiàng)里打開鎖定選項(xiàng)。
例:
定義兩個(gè)變量使用工作寄存器R14,R15
i nclude<iom8.h>
__regvar __no_init char g @ 15;
__regvar __no_init char P @ 14;
void main(void)
{
g++;
P++;
}
在工程選項(xiàng)里c/c++ complier>code里打開要使用的寄存器R14-R15。

 


編譯結(jié)果就如下,看看是不是直接使用了寄存器做為數(shù)據(jù)應(yīng)用
// 4 void main(void)
main:
CFI Block cfiBlock0 Using cfiCommon0
CFI Function main
// 5 { g++;
REQUIRE ?Register_R14_is_global_regvar
REQUIRE ?Register_R15_is_global_regvar
INC R15
// 6 P++; }
INC R14
RET
注意:定義在寄存器里變量不能帶有初始值。最好不要使用超過9個(gè)寄存器變量,不然可能引起潛在的危險(xiǎn),因?yàn)榻斓臅r(shí)候沒有鎖定任何寄存器。

52.定義變量的絕對(duì)地址.沒有特性的變量是隨機(jī)分配的,要給變量分配地址必須加以特性修飾注意在定義地址的時(shí)候千萬不要和片內(nèi)寄存器地址重合了。
5.2.1
定義沒有存儲(chǔ)特性的絕對(duì)地址變量必須加__no_init 或者const對(duì)象特性
__no_init char t @ 0x65;//
定義在I/O地址以外
const char t @ 0x65;//
定義只讀變量的地址
例:
i nclude<iom8.h>
__no_init char u @ 0x65 ;
void main(void)
{u++;}
對(duì)應(yīng)匯編:
void main(void)
\ main:
{u++;}
\ 00000000 E6E5 LDI R30, 101
\ 00000002 E0F0 LDI R31, 0
\ 00000004 8100 LD R16, Z
\ 00000006 9503 INC R16
\ 00000008 8300 ST Z, R16
\ 0000000A 9508 RET
5
22帶存儲(chǔ)特性的關(guān)鍵字定義變量的絕對(duì)地址__io,__ext_io定義變量在i/o空間
i nclude<iom8.h>
__io char u @ 0x65 ;
void main(void)
{u++;}
對(duì)應(yīng)匯編:
void main(void)
\ main:
{u++;}
\ 00000000 91000065 LDS R16, 101
\ 00000004 9503 INC R16
\ 00000006 93000065 STS 101, R16
\ 0000000A 9508 RET
5.2.15.2.2對(duì)比,發(fā)現(xiàn)用5.2.2方法定義代碼小多了。


5.3
.關(guān)鍵字volatile保證從最原始的位置讀取變量。在IAR編譯器里,除了__no_init__root定義的變量外,其他的類型的變量都包含有volatile__no_init特性

IAR for AVR 學(xué)習(xí)筆記(6--中斷及相關(guān)函數(shù)操作

61.中斷函數(shù):
   
IAR編譯器里用關(guān)鍵字來__interrupt來定義一個(gè)中斷函數(shù)。用#pragma vector來提供中斷函數(shù)的入口地址
#pragma vector=0x12//
定時(shí)器0溢出中斷入口地址
__interrupt void time0(void)
{
;
}
   
上面的入口地址寫成#pragma vector=TIMER0_OVF_vect更直觀,每種中斷的入口地址在頭文件里有描述。函數(shù)名稱time0可以為任意名稱。中斷函數(shù)會(huì)自動(dòng)保護(hù)局部變量,但不會(huì)保護(hù)全局變量。

6.2.內(nèi)在函數(shù)也可以稱為本征函數(shù)
   
編譯器自己編寫的能夠直接訪問處理器底層特征的函數(shù)。在intrinsics.h中有描述完整類型在comp_a90.h里有進(jìn)一步的簡(jiǎn)化書寫方式

621延時(shí)函數(shù),以周期為標(biāo)準(zhǔn)
__delay_cycles(unsigned long );
如果處理器頻率為1M,延時(shí)100us,如下:
__delay_cycles(100 );
當(dāng)然你也可以對(duì)該函數(shù)進(jìn)行修改:
#define CPU_F 1000000
#define delay_us (unsigned long) __delay_cycles((unsigned long )*CPU_F)
#define delay_ms (unsigned long) __delay_cycles((unsigned long )*CPU_F/1000)

622中斷指令
   __disable_interrupt( );//
插入CLI指令, 也可以用_CLI();也可以SREG_Bit7=0;
    __enable_interrupt( );//
插入SEI指令,也可以用_SEI();也可以SREG_Bit7=1;
   
其實(shí)對(duì)于狀態(tài)字的置位和清零只有BSET S BCLR S兩條指令。像SEI不過是BSET 7;的另一個(gè)名字而已。AVR指令中還有很多類似的現(xiàn)象,如:ORI SBR 指令完全一樣,號(hào)稱130多條指令的AVR其實(shí)沒有那么多指令的。

623FLASH空間指定地址讀取數(shù)據(jù)
__extended_load_program_memory(unsigned char __farflash *);
__load_program_memory(unsigned char __flash *);
該條指令以及正確的使用方法在45flash 操作宏函數(shù)里詳細(xì)講解,這里不再重復(fù)

624乘法函數(shù)
__fracdtional_multiply_signed(signed char, signed char);
__fractional_multiply_signed_with_unsigned(signed char, unsigned char);
__fractional_multiply_unsigned(unsigned char, unsigned char);
//
以上為定點(diǎn)小數(shù)乘法
__multiply_signed(signed char, signed char);//
有符號(hào)數(shù)乘法
__multiply_signed_with_unsigned(signed char, unsigned char);
//
有符號(hào)數(shù)和無符號(hào)數(shù)乘法
__multiply_unsigned(unsigned char, unsigned char);//
無符號(hào)數(shù)乘法

624 半字節(jié)交換指令
__swap_nibbles(unsigned char);

625 MCU控制指令
__no_operation();//
空操作指令
_NOP()
;
__sleep()
;//休眠指令
_SLEEP()
;
__watchdog_reset();//
看門狗清零
_WDR()
;

 

IAR for AVR 學(xué)習(xí)筆記(7--頭文件含義

avr_macros.h里面包含了讀寫16位寄存器的簡(jiǎn)化書寫,和幾個(gè)位操作函數(shù)


comp_a90.h
對(duì)大量的內(nèi)在函數(shù)做了簡(jiǎn)要書寫


ina90.h
包含"inavr.h" "comp_A90.h"文件


intrinsics.h
內(nèi)在函數(shù)提供最簡(jiǎn)單的操作處理器底層特征。休眠,看門狗,FLASH函數(shù)。


iomacro.H I/O
寄存器定義文件樣本。


iom8.h
包含I/O等寄存器定義

 

IAR for AVR 學(xué)習(xí)筆記(8--匯編嵌入方式

嵌入?yún)R編語言
在線匯編:使用asm或者__asm,推薦使用__asm。
i nclude<iom8.h>
void main()
{
   asm("NOP \n"
       "CLH \n"
       "OR R16,R17 \n");
}
不過IAR提供了完全可以訪問底層的函數(shù),建議不要頻繁使用匯編

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多