我是IAR的新手,,最近搞avr才使用的IAR,在使用的過程中第一個遇到的問題就是很多寄存器不可以使用,比如PORTC,PORTD等等,,這些明明是可以用的,,不知道問什么不能用,,后來問人終于知道了,,這是IAR設(shè)置的問題,,在設(shè)置里面,option->general options -> system -> enable bit defination in I/O - Include files 把位操作使能勾上就可以了. ============================================================================================== ** IAR嵌入式開發(fā)平臺編譯鏈接時產(chǎn)生UBROF F8格式即可導(dǎo)入到AVR Studio中調(diào)試,。 ** 按下面設(shè)置:Project -> Options -> LINKER -> Output -> Other -> UBROF F8 ** 打開AVR Studio,F(xiàn)ile -> Open File -> Debug\Exe\*.d90 (有必要改變文件類型為“所有文件”),。 ============================================================================================== IARAVR C編譯器的中斷使用方法 IAR公司開發(fā)的AVR單片機(jī)C編譯器是一款非常優(yōu)秀的開發(fā)工具,,由于它的編譯效率要比ICCAVR、CODEVISIONAVR,、GCCAVR編譯器都要高,,很容易編寫出高效的C程序。 對于C程序的編寫,,大體都是一樣的,,只是不同的編譯器在標(biāo)準(zhǔn)C基礎(chǔ)上都有自己的擴(kuò)展特性。AVR單片機(jī)的中斷服務(wù)程序的編寫對于不同的編譯器聲明的方法也就不同,。例如在IAR AVR C編譯器中使用定時器Timer0溢出中斷聲明的方法如下: #pragma vector = TIMER0_OVF_vect __interrupt void Timer0_OverFlow_Interrupt(void) { //用戶自己添加的程序段 } "#pragma vector = "是必須聲明的,,等于號后面內(nèi)容為對應(yīng)中斷向量地址 “__interrupt”這是IAR AVR C編譯器中的中斷服務(wù)程序聲明的關(guān)鍵字,是必須的,。后面就是用戶給該中斷服務(wù)程序取的函數(shù)名,,由用戶自己定義。 另外有一點必須注意的是:中斷服務(wù)函數(shù)必須為無參,,無返回參數(shù)的函數(shù),。 IAR的中斷使用和GCC有所區(qū)別: 例如:使用ADC中斷 IAR編譯器: #pragma vector = ADC_vect __interrupt void adc(void) GCC編譯器:SIGNAL(SIG_ADC) IAR可以直接進(jìn)行調(diào)試,,gcc需要在AVR Studio中進(jìn)行調(diào)試; IAR中定義了一些常用的內(nèi)部函數(shù)在intrinsics.h和comp_a90.h等頭文件中有函數(shù)聲明,; IAR中的寄存器位操作不能直接使用,,需要宏定義,#define ENABLE_BIT_DEFINITIONS IAR的位操作功能強(qiáng)大,,例如:PORTB_BIT2 = 1; IAR AVR 中斷應(yīng)用 2009-08-08 14:48 如何輸出HEX文件? 在配置文件后面加入以下代碼,便可輸出HEX文件,A90文件與HEX文件一樣,SLISP都能識別. // Output File -Ointel-extended,(XDATA)=.eep //產(chǎn)生eeprom文件 -Ointel-extended,(CODE)=.A90 //產(chǎn)生燒寫文件 -Ointel-extended,(CODE)=.hex //產(chǎn)生燒寫文件 中斷向量的使用 IAR中定義中斷函數(shù)的格式是 ///////////////////////////////// #pragma vector=中斷向量 __interrupt void 中斷服務(wù)程序(void) { //中斷處理程序 } ///////////////////////////////////// 中斷的初始化要另外加入代碼,,可在主程序內(nèi)加入。如下是各個中斷函數(shù)的定義,。 //中斷定義 #include <iom16.h> #pragma vector=INT0_vect __interrupt void INT0_Server(void) { } #pragma vector=INT1_vect __interrupt void INT1_Server(void) { } #pragma vector=TIMER2_COMP_vect __interrupt void TIMER2_COMP_Server(void) { } #pragma vector=TIMER2_OVF_vect __interrupt void TIMER2_OVF_Server(void) { } #pragma vector=TIMER1_CAPT_vect __interrupt void TIMER1_CAPT_Server(void) { } #pragma vector=TIMER1_COMPA_vect __interrupt void TIMER1_COMPA_Server(void) { } #pragma vector=TIMER1_COMPB_vect __interrupt void TIMER1_COMPB_Server(void) { } #pragma vector=TIMER1_OVF_vect __interrupt void TIMER1_OVF_Server(void) { } #pragma vector=TIMER0_OVF_vect __interrupt void TIMER0_OVF_Server(void) { } #pragma vector=SPI_STC_vect __interrupt void SPI_STC_Server(void) { } #pragma vector=USART_RXC_vect __interrupt void USART_RXC_Server(void) { } #pragma vector=USART_UDRE_vect __interrupt void USART_UDRE_Server(void) { } #pragma vector=USART_TXC_vect __interrupt void USART_TXC_Server(void) { } #pragma vector=ADC_vect __interrupt void ADC_Server(void) { } #pragma vector=EE_RDY_vect __interrupt void EE_RDY_Server(void) { } #pragma vector=ANA_COMP_vect __interrupt void ANA_COMP_Server(void) { } #pragma vector=TWI_vect __interrupt void TWI_Server(void) { } #pragma vector=INT2_vect __interrupt void INT2_Server(void) { } #pragma vector=TIMER0_COMP_vect __interrupt void TIMER0_COMP_Server(void) { } #pragma vector=SPM_RDY_vect __interrupt void SPM_RDY_Server(void) { } 如何把常數(shù)字符串定義在flash 空間? 法一:unsigned char __flash temptab[] = {1,2,3,4,5}; 法二:__flash unsigned char temptab[] = {1,2,3,4,5}; 法三:#pragma type_attribute=__flash unsigned char temptab[]={1,2,3,4,5}; 法四:const unsigned char temptab[]={1,2,3,4,5}; 注:第三種方式用#pragma說明后,,下面的定義的變量將都在FLASH空間了,用于定義一批FLASH變量,但實際上一般只能作為常 量使用了. IAR For AVR 定時器中斷初值計算方法 2009-08-10 23:57 使用芯片 AT Mega16 外部晶振 4.00MHz 定時器1 (16位定時器)寄存器 TCCR1B = 0x04 設(shè)定 256預(yù)分頻 要利用定時器定時1秒 1,,4000000 / 256 = 15625 說明定時器每當(dāng) 1/15625 秒 就會觸發(fā)一次中斷 2,,65535 - 15625 = 49910 計算出要累加多少次才能在1秒后出發(fā)定時器1的溢出中斷 3,49910 <==> C2 F6 將計算后的值換算成16進(jìn)制 4,, TCNT1H = 0xC2 ; 對寄存器賦值 TCNT1L = 0xF6 ; ============================================================================= 例如用16位定時器TIMER1,4MHZ晶振,,256分頻,100ms定時,,如何求得初值賦給TCNT1? 65536-(4M/256)*0.1=63973.5 其中,,4M是晶體頻率,0.1是定時時長單位秒,。 對于8位的定時器 T=(2^8-計數(shù)初值)*晶振周期*分頻數(shù)=(2^8-計數(shù)初值)/晶振頻率*分頻數(shù) 計數(shù)初值=2^8-T/晶振周期/分頻數(shù)=2^8-T*晶振頻率/分頻數(shù) 因為AVR一指令 一周期 IAR FOR AVR 定時器中斷的使用 2009-08-10 23:08 首先看下在iar 里面 iom16.h里面的中斷向量表 /* NB! vectors are specified as byte addresses */ #define RESET_vect (0x00) #define INT0_vect (0x04) #define INT1_vect (0x08) #define TIMER2_COMP_vect (0x0C) #define TIMER2_OVF_vect (0x10) #define TIMER1_CAPT_vect (0x14) #define TIMER1_COMPA_vect (0x18) #define TIMER1_COMPB_vect (0x1C) #define TIMER1_OVF_vect (0x20) #define TIMER0_OVF_vect (0x24) #define SPI_STC_vect (0x28) #define USART_RXC_vect (0x2C) #define USART_UDRE_vect (0x30) #define USART_TXC_vect (0x34) #define ADC_vect (0x38) #define EE_RDY_vect (0x3C) #define ANA_COMP_vect (0x40) #define TWI_vect (0x44) #define INT2_vect (0x48) #define TIMER0_COMP_vect (0x4C) #define SPM_RDY_vect (0x50) 然后我是用的atmega16 4mhz晶振 源程序: #include <iom16.h> char flag=0; void timer_init() // 中斷初始化 { TCCR1B = 0x04; TCNT1H = 0xc2; TCNT1L = 0xf6; TIMSK_Bit2 = 1; // 定時器中斷屏蔽寄存器 SREG_Bit7 = 1; // 總中斷 } # pragma vector = TIMER1_OVF_vect __interrupt void timer1(void) { TCNT1H = 0xc2; TCNT1L = 0xf6; flag=1; } void main(void) { timer_init(); DDRB_Bit1 = 1; while(1) { if(flag==1) { PORTB_Bit1 = ~PORTB_Bit1; flag = 0; } } } IAR For AVR USART 應(yīng)用 2009-08-10 23:19 #include <iom16.h> #define uchar unsigned char #define uint unsigned int //########################################################### /*串口初始化函數(shù)*/ void Uart_Init(void) { UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //允許發(fā)送和接收 UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8位數(shù)據(jù)位+1位停止位 UBRRH=0x00; //設(shè)置波特率寄存器低位字節(jié) UBRRL=47; //9600 //設(shè)置波特率寄存器高位字節(jié) DDRD_Bit1=1; //配置TX為輸出(很重要) } //########################################################### /*發(fā)送一個字符數(shù)據(jù),,查詢方式*/ void Uart_Transmit(uchar data) { while(!(UCSRA&(1<<UDRE))); //while(UCSRA_UDRE==0); /* 等待發(fā)送緩沖器為空*/ UDR = data; /* 發(fā)送數(shù)據(jù)*/ } //########################################################### //發(fā)送一串?dāng)?shù)據(jù) 帶回車符 void Uart_Puts(uchar *str) { while(*str) { Uart_Transmit(*(str++)); } Uart_Transmit(0x0a);//回車換行 Uart_Transmit(0x0d); } //########################################################### //發(fā)送一串?dāng)?shù)據(jù) 不帶回車符 void Uart_Put(uchar *str) { while(*str) { Uart_Transmit(*(str++)); } } //########################################################### /*數(shù)據(jù)接收,查詢方式*/ unsigned char Uart_Receive( void ) { while (!(UCSRA & (1<<RXC))); /* 等待接收數(shù)據(jù)*/ return UDR; } //########################################################### IAR For AVR EEPROM 應(yīng)用2009-08-10 23:31使用芯片 AT Mega16 #include<ina90.h> __EEPUT(ADR,VAL),;//向指定EEPROM空間地址(ADR)中寫入數(shù)據(jù)(VAL) __EEGET(VAR,ADR),;//從指定EEPROM空間地址(ADR)中讀取數(shù)據(jù)(VAL) IAR For AVR 精確延時2009-08-12 18:01C語言中,想使用精確的延時程序并不容易,。IAR 中有這樣的一個函數(shù) __delay_cycles(),該函數(shù)在頭文件intrinsics.h中定義,,函數(shù)的作用就是延時N個指令周期。根據(jù)這個函數(shù)就可以實現(xiàn)精確的延時函數(shù)了(但不能做到100%精確度),。 實現(xiàn)的方法: 建立一個delay.h的頭文件: #ifndef __IAR_DELAY_H #define __IAR_DELAY_H #include <intrinsics.h> #define XTAL 8 //可定義為你所用的晶振頻率(單位Mhz) #define delay_us(x) __delay_cycles ( (unsigned long)(x * XTAL) ) #define delay_ms(x) __delay_cycles ( (unsigned long)(x * XTAL*1000) ) #define delay_s(x) __delay_cycles ( (unsigned long)(x * XTAL*1000000) ) #endif 注意: __delay_cycles(x),x必須是常量或則是常量表達(dá)式,,如果是變量則編譯報錯! IAR For AVR 串口中斷接收2009-08-14 18:20應(yīng)用芯片: AT Mega16 晶振: 7.3728MHz 代碼文件: uart_int.c |_________DELAY.H ############################################## DELAY.H : #ifndef __IAR_DELAY_H #define __IAR_DELAY_H #include <intrinsics.h> #define XTAL 7.3728 //可定義為你所用的晶振頻率(單位Mhz) #define delay_us(x) __delay_cycles ( (unsigned long)(x * XTAL) ) #define delay_ms(x) __delay_cycles ( (unsigned long)(x * XTAL*1000) ) #define delay_s(x) __delay_cycles ( (unsigned long)(x * XTAL*1000000) ) #endif uart_int.c : #include <iom16.h> #include "delay.h" #define uchar unsigned char #define uint unsigned int uchar c; //########################################################### /*串口初始化函數(shù)*/ void Uart_Init(void) { UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //允許發(fā)送和接收 UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8位數(shù)據(jù)位+1位停止位 UBRRH=0x00; //設(shè)置波特率寄存器低位字節(jié) UBRRL=47; //9600 //設(shè)置波特率寄存器高位字節(jié) SREG_I = 1; //開總中斷 DDRD_Bit1=1; //配置TX為輸出(很重要) } //########################################################### /*發(fā)送一個字符數(shù)據(jù),,查詢方式*/ void Uart_Transmit(uchar data) { while(!(UCSRA&(1<<UDRE))); // 等待發(fā)送緩沖器為空 //也可以寫成 while(UCSRA_UDRE==0); UDR = data; // 發(fā)送數(shù)據(jù) } //########################################################### /*中斷接收*/ #pragma vector=USART_RXC_vect __interrupt void USART_RXC_Server(void) { UCSRB_RXCIE = 0; //關(guān)串口中斷 c = UDR ; //將收到的值賦值給變量 Uart_Transmit(c); //發(fā)給串口以檢測對錯 UCSRB_RXCIE = 1; //開串口中斷 } //########################################################### /*主函數(shù)*/ void main(void) { Uart_Init(); delay_us(20); //串口初始化后,,必須延時20us以上才能發(fā)送數(shù)據(jù),否則會出現(xiàn)錯誤 Uart_Transmit(0x64); while(1) { ; } //此時可以用串口助手發(fā)送字符,,然后可以正確接收 } IAR For AVR 兩線串行接口 TWI 應(yīng)用2009-08-15 16:39 ATMEL的TWI 和 PHILIPS的IIC 基本上應(yīng)該是算一個東西,,但是他們在名義上是不同的,這樣誰都不用支付給對方使用費。他們的協(xié)議是一樣的,,所有我們作為使用者基本可以簡單的看成 TWI就是IIC ,。 廢話說完,開始正題,。這次是關(guān)于在ATMega16 平臺下的硬件IIC(還不太習(xí)慣說TWI)的使用,。在ATMega16的Datasheet里我們可以看到很強(qiáng)大的功能,主從設(shè)置很多,。本文只說一種最常用的方式,,那就是“ATMega16 硬件TWI 的 掃描發(fā)送 和 掃描讀取”。 首先要明確TWI 發(fā)送和接受的流程: 發(fā)送: 1,,設(shè)定數(shù)據(jù)傳輸波特率 2,,發(fā)送START信號,等待應(yīng)答 ==》 《== 應(yīng)答信號 3,,發(fā)送芯片地址,,等待應(yīng)答 ==》 《==應(yīng)答信號 4,發(fā)送數(shù)據(jù)的絕對地址,,等待應(yīng)答 ==》 《==應(yīng)答信號 5,,發(fā)送要寫入的數(shù)據(jù),等待應(yīng)答 ==》 《==應(yīng)答信號 6,,發(fā)送STOP信號,,釋放總線 ==》 數(shù)據(jù)寫入成功 接收: 1,設(shè)定數(shù)據(jù)傳輸波特率 2,,發(fā)送START信號,,等待應(yīng)答 ==》 《== 應(yīng)答信號 3,發(fā)送芯片地址,,等待應(yīng)答 ==》 《==應(yīng)答信號 4,,發(fā)送數(shù)據(jù)的絕對地址,等待應(yīng)答 ==》 《==應(yīng)答信號 5,,發(fā)送RESTART信號,等待應(yīng)答 ==》 《==應(yīng)答信號 6,,發(fā)送芯片地址并注明讀操作,,等待應(yīng)答 ==》 《==應(yīng)答信號 7,讀取數(shù)據(jù),,等待應(yīng)答 ==》 《==應(yīng)答信號 8,,發(fā)送STOP信號,釋放總線 ==》 數(shù)據(jù)讀操作成功 應(yīng)用芯片 :ATMega 16 晶振 : 7.3728 代碼文件:Project |___TWI.C | |_____ IAR_DELAY.H |___UART.C @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IAR_DELAY.H #ifndef __IAR_DELAY_H #define __IAR_DELAY_H #include <intrinsics.h> #define XTAL 7.3728 //可定義為你所用的晶振頻率(單位Mhz) #define delay_us(x) __delay_cycles ( (unsigned long)(x * XTAL) ) #define delay_ms(x) __delay_cycles ( (unsigned long)(x * XTAL*1000) ) #define delay_s(x) __delay_cycles ( (unsigned long)(x * XTAL*1000000) ) #endif @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ UART.C #include <iom16.h> #define uchar unsigned char #define uint unsigned int //########################################################### /*串口初始化函數(shù)*/ void Uart_Init(void) { UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //允許發(fā)送和接收 UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8位數(shù)據(jù)位+1位停止位 UBRRH=0x00; //設(shè)置波特率寄存器低位字節(jié) UBRRL=47; //9600 //設(shè)置波特率寄存器高位字節(jié) DDRD_Bit1=1; //配置TX為輸出(很重要) } //########################################################### /*發(fā)送一個字符數(shù)據(jù),,查詢方式*/ void Uart_Transmit(uchar data) { while(!(UCSRA&(1<<UDRE))); //while(UCSRA_UDRE==0); /* 等待發(fā)送緩沖器為空*/ UDR = data; /* 發(fā)送數(shù)據(jù)*/ } @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #include <iom16.h> #include "IAR_DELAY.H" #define uchar unsigned char #define uint unsigned int void Uart_Init(void); void Uart_Transmit(uchar data); //變量聲明 #define EEPROM_BUS_ADDRESS 0xA0 //器件地址 /*#####################################################################*/ /*從器件地址位定義:______________________________________-------------*/ /* AT24C02 | 1 | 0 | 1 | 0 | A2 | A1 | A0 | R/~W |------------*/ /* ---------------------------------------------------*/ /*#####################################################################*/ //主機(jī)發(fā)送模式時各狀態(tài)字的后續(xù)動作 #define TW_START 0x08 //開始信號已發(fā)出 #define TW_REP_START 0x10 //重復(fù)開始信號已發(fā)出 #define TW_MT_SLA_ACK 0x18 //寫字節(jié)已發(fā)出并受到ACK信號 #define TW_MT_SLA_NACK 0x20 //寫字節(jié)已發(fā)出并受到NACK信號 #define TW_MT_DATA_ACK 0x28 //數(shù)據(jù)已發(fā)出并受到ACK 信號 #define TW_MT_DATA_NACK 0x30 //數(shù)據(jù)已發(fā)出并受到NACK 信號 #define TW_MT_ARB_LOST 0x38 //丟失總線控制權(quán) //主機(jī)接收模式時各狀態(tài)字的后續(xù)動作 #define TW_MR_ARB_LOST 0x38 //丟失總線控制權(quán),,未收到應(yīng)答信號 #define TW_MR_SLA_ACK 0x40 //讀命令已發(fā)出并受到ACK #define TW_MR_SLA_NACK 0x48 //讀命令已發(fā)出并受到NACK #define TW_MR_DATA_ACK 0x50 //數(shù)據(jù)已收到,ACK已發(fā)出 #define TW_MR_DATA_NACK 0x58 //數(shù)據(jù)已收到,NACK已發(fā)出 #define IIC_Start() TWCR =(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) // TWINT位 通過寫1進(jìn)行清零,,一旦清零則TWI開始工作,,當(dāng)相應(yīng)硬件工作完成后 TWINT位會重新置位為1 // TWSTA位 會讓硬件在總線上產(chǎn)生一個START的信號 , 聲明自己希望成為主機(jī) // TWEN 位 使能TWI功能,將 PC0 和 PC1 管腳切換到第二功能上來, 如果清零則為中斷 TWI的傳輸 #define IIC_Stop() TWCR =(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) // TWSTO位 在主機(jī)模式下,,會讓硬件在總線上產(chǎn)生一個STOP得信號,,并且SCL 和 SDA 兩個引腳位高阻態(tài) #define IIC_Wait() while(!(TWCR&(1<<TWINT))) // TWINT位 經(jīng)過一次置位使硬件TWI開始工作 ,然后在檢測 TWCR 寄存器的 TWINT 位是不是被置位,如果置位為1則表示工作完成可以向下進(jìn)行 //############################################################################## /*I2C總線單字節(jié)寫入*/ unsigned char twi_write(unsigned char addr, unsigned char dd) { TWBR = 10; //設(shè)定波特率 /*start 啟動*/ IIC_Start(); //硬件發(fā)送START信號,,并且清零TWINT位,,使能硬件TWI,使TWI開始工作 IIC_Wait(); //等待 發(fā)送START完成 TWINT位置位 if ((TWSR & 0xF8) != 0x08) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量,,如果正確則向下進(jìn)行數(shù)據(jù)傳輸,錯誤返回 0 /*SLA_W 芯片地址*/ TWDR = EEPROM_BUS_ADDRESS ; //芯片地址 0xA0 ,,賦值給數(shù)據(jù)寄存器 TWDR ,,等待發(fā)送 TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,然后 使能TWI硬件接口 ,,讓TWI進(jìn)行工作,,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x18) return 0; //檢測到TWINT位置位,比對TWSR寄存器內(nèi)的狀態(tài)量 ,, 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,,錯誤返回 0 /*addr 操作地址*/ TWDR = addr; //將寫入數(shù)據(jù)的絕對地址 ,賦值給數(shù)據(jù)寄存器 TWDR ,,等待發(fā)送 TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,,然后 使能TWI硬件接口 ,讓TWI進(jìn)行工作,,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x28) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量 , 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,,錯誤返回 0 /*dd 寫入數(shù)據(jù)*/ TWDR = dd; //將要寫入的數(shù)據(jù) ,,賦值給數(shù)據(jù)寄存器 TWDR ,等待發(fā)送 TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,,然后 使能TWI硬件接口 ,,讓TWI進(jìn)行工作,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x28) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量 ,, 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,錯誤返回 0 /*stop 停止*/ IIC_Stop(); //數(shù)據(jù)傳輸完成,,發(fā)送STOP信號,,釋放對總線的控制 return 1; //寫入數(shù)據(jù)成功 ,,返回1 ,用來判斷是否成功寫入數(shù)據(jù) } //############################################################################## /*I2C總線單字節(jié)讀取*/ unsigned char twi_read(unsigned char addr) { unsigned char Receive_Byte ; TWBR = 2; //設(shè)定波特率 /*start 啟動*/ IIC_Start(); //硬件發(fā)送START信號,,并且清零TWINT位,,使能硬件TWI,使TWI開始工作 IIC_Wait(); //等待 發(fā)送START完成 TWINT位置位 if ((TWSR & 0xF8) != 0x08) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量,,如果正確則向下進(jìn)行數(shù)據(jù)傳輸,錯誤返回 0 /*SLA_W 芯片地址*/ TWDR = EEPROM_BUS_ADDRESS; //芯片地址 0xA0 ,,賦值給數(shù)據(jù)寄存器 TWDR ,,等待發(fā)送 TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,然后 使能TWI硬件接口 ,,讓TWI進(jìn)行工作,,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x18) return 0; //檢測到TWINT位置位,比對TWSR寄存器內(nèi)的狀態(tài)量 ,, 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,,錯誤返回 0 /*addr 操作地址*/ TWDR = addr; //將寫入數(shù)據(jù)的絕對地址 ,賦值給數(shù)據(jù)寄存器 TWDR ,,等待發(fā)送 TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,,然后 使能TWI硬件接口 ,讓TWI進(jìn)行工作,,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x28) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量 , 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,,錯誤返回 0 /*restart 重啟動*/ IIC_Start(); //硬件發(fā)送 RESTART 信號,,并且清零TWINT位,使能硬件TWI,,使TWI開始工作 IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x10) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量 , 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,,錯誤返回 0 /*SLA_R 芯片地址*/ TWDR = 0xA1; //芯片地址 0xA0 并注明是讀取操作(最后一位為 1 ),,賦值給數(shù)據(jù)寄存器 TWDR ,等待發(fā)送 TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,,然后 使能TWI硬件接口 ,,讓TWI進(jìn)行工作,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x40) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量 , 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,,錯誤返回 0 /*讀取數(shù)據(jù)*/ TWCR = (1 << TWINT) | (1 << TWEN); //對控制寄存器TWCR的 TWINT 位軟件寫1進(jìn)行清零,,然后 使能TWI硬件接口 ,,讓TWI進(jìn)行工作,發(fā)送 TWDR寄存器 中的數(shù)據(jù) IIC_Wait(); //等待數(shù)據(jù)發(fā)送完畢 TWINT重新置位 if ((TWSR & 0xF8) != 0x58) return 0; //檢測到TWINT位置位,,比對TWSR寄存器內(nèi)的狀態(tài)量 ,, 如果正確則向下進(jìn)行數(shù)據(jù)傳輸,錯誤返回 0 Receive_Byte = TWDR; //讀取到的數(shù)據(jù)放到局部變量里 /*stop 停止*/ IIC_Stop(); //數(shù)據(jù)傳輸完成,,發(fā)送STOP信號,,釋放對總線的控制 return Receive_Byte; //將讀取到的數(shù)據(jù)作為函數(shù)的輸出 } //############################################################################## /*主函數(shù)*/ void main(void) { uchar c,d; Uart_Init(); //串口初始化 delay_us(20); Uart_Transmit(0x55); //測試串口 c = twi_write(0x51,0xf8); //在地址0x51里寫入數(shù)據(jù)0x22 Uart_Transmit(c); //將返回值發(fā)送到串口測試是否寫入成功 delay_ms(2); d = twi_read(0x51); //將地址0x51里的數(shù)據(jù)讀出來 Uart_Transmit(d); //將讀取到的數(shù)據(jù)發(fā)送串口 while(1); } IAR AVR WatchDog 使用2009-08-29 23:44首先要包括 comp_a90.h 頭文件 , 他里面有喂狗程序 _WDR() ,。 #include <iom16.h> #include <intrinsics.h> #include <comp_a90.h> #include "delay.h" void watchdog_init(void) { WDTCR |= ((1 << WDTOE) | (1 << WDE)); /*啟動時序*/ WDTCR = ((1<< WDE) | (1 << WDP2) | (1 <<WDP1)); /*設(shè)定周期為1S*/ } void main(void) { watchdog_init(); DDRB_Bit0 = 1; PORTB_Bit0 = 0 ; delay_ms(500); _WDR(); PORTB_Bit0 = 1 ; delay_ms(500); _WDR(); while(1){;} |
|