/************************************** 硬件:單片機(jī)mega162,EEPROM 25256,晶振3.6864MHZ 編譯環(huán)境:ICC ****************************************/ #include<iom162v.h> #define BAUD 9600 //波特率4800 #define CRYSTAL 3686400 //晶振3M #define BAUD_set (unsigned int)( (unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1 ) //波特率計算 #define BAUD_H (unsigned char)(BAUD_set>>8) //波特率寄存器 #define BAUD_L (unsigned char)(BAUD_set) /* //GPRS #define GPRS_ONOFFH PORTA|=(1<<PA5) #define GPRS_ONOFFL PORTA&=~(1<<PA5) #define GPRS_RSTH PORTB|=(1<<PB1) #define GPRS_RSTL PORTB&=~(1<<PB1) //通訊燈 #define LED1H PORTC|=(1<<PC4) #define LED1L PORTC&=~(1<<PC4) #define LED2H PORTC|=(1<<PC6) #define LED2L PORTC&=~(1<<PC6) #define LED3H PORTC|=(1<<PC7) #define LED3L PORTC&=~(1<<PC7) */ //25256 #define EEPROM_CSH PORTD|=(1<<PD5) // #define EEPROM_CSL PORTD&=~(1<<PD5) #define EEPROM_WPH PORTD|=(1<<PD2) #define EEPROM_WPL PORTD&=~(1<<PD2) #define SPIF 7 //////////////////////USRT0,USTR1 begin////////////////////////// /////////////////////////////////////串口begin/////////////////////////////////////////// //串口0初始化 void USART0_Init() { UCSR0B = (1 << RXCIE0) | /*接收完成中斷允許*/ // (1 << TXCIE0) | /*發(fā)送完成中斷允許*/ (1 << RXEN0) | /*接收允許*/ (1 << TXEN0); /*發(fā)送允許*/ UBRR0H = BAUD_H; //設(shè)置波特率 UBRR0L = BAUD_L; UCSR0C = (1 << URSEL0) | /*選擇訪問UCSRC寄存器*/ (3 << UCSZ00); /*UCSZ2 UCSZ1 UCSZ0=3 8個數(shù)據(jù)位*/ } //串口1初始化 void USART1_Init() { UCSR1B = (1 << RXCIE1) | /*接收完成中斷允許*/ // (1 << TXCIE1) | /*發(fā)送完成中斷允許*/ (1 << RXEN0) | /*接收允許*/ (1 << TXEN0); /*發(fā)送允許*/ UBRR1H = BAUD_H; //設(shè)置波特率 UBRR1L = BAUD_L; UCSR1C = (1 << URSEL1) | /*選擇訪問UCSRC寄存器*/ (3 << UCSZ10); /*UCSZ2 UCSZ1 UCSZ0=3 8個數(shù)據(jù)位*/ } //串口0查詢方式發(fā)送數(shù)據(jù) void USART0_Transmit(unsigned char data) { while(!(UCSR0A&(1<<UDRE0))); /*等待發(fā)送緩沖器為空。UDRE數(shù)據(jù)寄存器空標(biāo)志位, 當(dāng)發(fā)送緩沖器空時被置1;發(fā)送緩沖器包含需要發(fā)送的數(shù)據(jù)時清零*/ UDR0=data; //將數(shù)據(jù)放入緩沖器,發(fā)送數(shù)據(jù) } //串口1查詢方式發(fā)送數(shù)據(jù) void USART1_Transmit(unsigned char data) { while(!(UCSR1A&(1<<UDRE1))); /*等待發(fā)送緩沖器為空。UDRE數(shù)據(jù)寄存器空標(biāo)志位, 當(dāng)發(fā)送緩沖器空時被置1;發(fā)送緩沖器包含需要發(fā)送的數(shù)據(jù)時清零*/ UDR1=data; //將數(shù)據(jù)放入緩沖器,發(fā)送數(shù)據(jù) } /* //發(fā)送GPRS命令給手機(jī)模塊 void USART1_Tx_Str(char *s,unsigned char cnt) { while(cnt--) { USART1_Transmit(*s); s++; } } */ /////////////////////////////////////////////串口end///////////////////////////////////// /* unsigned char usart0_receive(void) { while(!(UCSR0A&(1<<RXC0))); //等待接收數(shù)據(jù) return UDR0; //從緩沖器中獲取并返回數(shù)據(jù) } */ ////////////////////////USRT1,USRT2 end/////////////////////// ///////////////////////////////////////////GPRS begin//////////////////////////////////// //延時ms /* void delayms(unsigned int ms) { unsigned int i,j; for(i=0;i<ms;i++) for(j=0;j<3500;j++) ; } //GPRS開機(jī) void GPRS_On() { GPRS_RSTH; GPRS_ONOFFH; delayms(20); GPRS_RSTL; delayms(10); GPRS_ONOFFL;LED1L;LED2L;LED3L;delayms(1800); GPRS_ONOFFH;LED1H;LED2H;LED3H;delayms(200); LED1L;LED2L; } //GPRS關(guān)機(jī) void GPRS_Off() { GPRS_ONOFFL;delayms(1800); GPRS_ONOFFH;delayms(5000); GPRS_RSTL; } //GPRS復(fù)位 void GPRS_Rst() { GPRS_Off(); GPRS_On(); } */ ////////////////////////////////////////GPRS end///////////////////////////////////////// ////////////////////////////////////eeprom begin////////////////////////////////////// void SPI_MasterInit(void) { EEPROM_WPH; delayms(20); SPCR =(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0); /* 使能SPI,選擇主機(jī)模式,SCK=fosc/128,選擇SPI模式CPOL=0,CPHA=0 */ } unsigned char SPI_MasterTransmit(unsigned char cData) { //啟動數(shù)據(jù)傳輸 SPDR = cData; //等待數(shù)據(jù)傳輸結(jié)束 while(!(SPSR&(1<<SPIF))); //發(fā)送完成后,清除發(fā)送標(biāo)志 // SPSR&=~(1<<SPIF); return SPDR; //每次發(fā)送數(shù)據(jù)的同時,也會接收到數(shù)據(jù)。 } //EEPROM寫使能 void EEPROM_WREN() { EEPROM_CSL; //拉低片選端 SPI_MasterTransmit(0x06); //0x06為寫使能的指令 EEPROM_CSH; //抬高片選端,結(jié)束 } //EEPROM寫禁止 void EEPROM_WRDI() { EEPROM_CSL;//delayms(20); SPI_MasterTransmit(0x04); //0x04為寫禁止的指令 EEPROM_CSH;//delayms(20); } //寫狀態(tài)寄存器 void EEPROM_WRSR() { EEPROM_WREN(); EEPROM_CSL; //使能 SPI_MasterTransmit(0x01); //0x01為寫狀態(tài)寄存器的指令 SPI_MasterTransmit(0x82); //把0x82寫入狀態(tài)寄存器 EEPROM_CSH; //抬高片選,結(jié)束 } /* 讀狀態(tài)寄存器。讀SPI從機(jī)數(shù)據(jù)時,主機(jī)要給從機(jī)發(fā)送任意數(shù)據(jù),才能收到從機(jī)返回的數(shù)據(jù). 即0x00可以是任何數(shù)據(jù)(但是不能是25256的指令,例如0x01,0x04之類的) */ unsigned char EEPROM_RDSR() { unsigned char StatusReg; EEPROM_WREN(); // EEPROM_WRDI(); //如使用此句,不使用EEPROM_WREN(),則讀出0x80 EEPROM_CSL; //使能 SPI_MasterTransmit(0x05); //0x05為讀狀態(tài)寄存器指令 StatusReg=SPI_MasterTransmit(0x00); //給25256發(fā)送任意數(shù)據(jù) /* 此處原為: SPDR = 0x00; while(!(SPSR&(1<<SPIF))); StatusReg=SPDR; 時出錯,讀出數(shù)據(jù)都為0xff。想不清楚為什么 */ EEPROM_CSH; return StatusReg; } //25256字節(jié)寫 void EEPROM_ByteWrite(unsigned int Address,unsigned char Data) { EEPROM_WREN(); EEPROM_CSL; //使能 SPI_MasterTransmit(0x02); //0x02為寫指令 SPI_MasterTransmit(Address/256); //地址高位 SPI_MasterTransmit(Address%256); //地址低位 SPI_MasterTransmit(Data); //寫入數(shù)據(jù) EEPROM_CSH;delayms(50); } //25256頁寫。試驗結(jié)果,只能連續(xù)寫入三個字節(jié) void EEPROM_PageWrite(unsigned int Address,unsigned char *Data,unsigned char NData) { unsigned char i; EEPROM_WREN(); EEPROM_CSL; SPI_MasterTransmit(0x02);//頁寫指令 SPI_MasterTransmit(Address/256); //地址高位 SPI_MasterTransmit(Address%256); //地址低位 for(i=0;i<NData;i++) { SPI_MasterTransmit(*Data); //寫入數(shù)據(jù) Data++; } EEPROM_CSH; } //25256讀 unsigned char EEPROM_Read(unsigned int Address) { unsigned char dataa; EEPROM_CSL; //使能 SPI_MasterTransmit(0x03); //0x03為讀25256的指令 SPI_MasterTransmit(Address/256); //地址高位 SPI_MasterTransmit(Address%256); //地址低位 dataa=SPI_MasterTransmit(0x00);//發(fā)送任意數(shù)據(jù) EEPROM_CSH; return dataa; //返回讀到的數(shù)據(jù) } ////////////////////////////////////eeprom end//////////////////////////////////////// //端口初始化 void Port_Init() { PORTA=0xff; DDRA=0x30; //PA4,PA5輸出1 PORTB=0xbf; DDRB=0xb7; //PB1輸出1,PB2輸出1,PB3輸入0,PB4輸出1,PB0輸出1(用于新終端開關(guān)電源控制),PB5PB7為輸出1 PORTC=0xff; DDRC=0xd0; //PC4輸出1,PC6,PC7輸出1 PORTD=0xff; DDRD=0x26; //PD0輸入0,PD1輸出1,PD5PD2輸出1 } void main(void) { // unsigned char dataa,i,j; SREG=0x80; //開放全局中斷 Port_Init(); USART0_Init(); USART1_Init(); // GPRS_On(); SPI_MasterInit();EEPROM_WRSR(); while(1) { USART0_Transmit(0x22); USART0_Transmit(0x33); EEPROM_ByteWrite(0x2030,0x48); //給25256地址0x2030寫入數(shù)據(jù)0x48 USART0_Transmit(EEPROM_Read(0x2010)); USART0_Transmit(EEPROM_Read(0x2030));//讀出地址0x2030中數(shù)據(jù),從串口0發(fā)送出來 USART0_Transmit(0x44); USART0_Transmit(0x55); USART0_Transmit(EEPROM_RDSR()); EEPROM_PageWrite(0x1001,"456789",6); //輸出結(jié)果0xff,0xff,0xff,0x37,0x38,0x39 USART0_Transmit(EEPROM_Read(0x1001)); USART0_Transmit(EEPROM_Read(0x1002)); USART0_Transmit(EEPROM_Read(0x1003)); USART0_Transmit(EEPROM_Read(0x1004)); USART0_Transmit(EEPROM_Read(0x1005)); USART0_Transmit(EEPROM_Read(0x1006)); USART0_Transmit(0x11); } } /* //IAR中中斷的寫法 #pragma vector=USART0_RXD_vect __interrupt void Usart0Rx(void) { unsigned char dataa; dataa=UDR0; usart0_transmit(dataa); } */ //串行0通信接收完成中斷\ //ICC中中斷的寫法 #pragma interrupt_handler USART0Rx:20 void USART0Rx() { unsigned char data0; data0=UDR0; USART0_Transmit(data0); } /*串行1通信接收完成中斷 分析燈不亮原因,開了串口1中斷,但是沒有加入中斷函數(shù),導(dǎo)致其他地方不能工作。 串口中斷0能執(zhí)行,是由于其優(yōu)先級比串口中斷1高 以下是書上的說法: 接收結(jié)束標(biāo)志位(RXC)用來說明接收緩沖器中是否有未讀出的數(shù)據(jù)。當(dāng)接收緩沖器中有未讀出的 數(shù)據(jù)時,此位為1,當(dāng)接收緩沖器空時為0(即不包含未讀出的數(shù)據(jù))。如果接收器被禁止(RXEN=0), 接收緩沖器會被刷新,從而使RXC清零。 置位UCSRB的接收結(jié)束中斷使能位(RXCIE)后,只要RXC標(biāo)志置位(且全局中斷使能)就會產(chǎn)生USART 接收結(jié)束中斷。使用中斷方式進(jìn)行數(shù)據(jù)接收時,數(shù)據(jù)接收結(jié)束中斷服務(wù)程序必須從UDR讀取數(shù)據(jù) 以清除RXC標(biāo)志,否則只要中斷處理程序結(jié)束,一個新的中斷就會產(chǎn)生。 終上所述,RXC標(biāo)志未清零,導(dǎo)致中斷一直產(chǎn)生。 */ #pragma interrupt_handler USART1Rx:21 void USART1Rx() { unsigned char data1; data1=UDR1; // USART1_Transmit(data1); }