
/**************************************
硬件:單片機mega162,EEPROM 25256,晶振3.6864MHZ
編譯環境: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) | /*發送完成中斷允許*/
(1 << RXEN0) | /*接收允許*/
(1 << TXEN0); /*發送允許*/
UBRR0H = BAUD_H; //設置波特率
UBRR0L = BAUD_L;
UCSR0C = (1 << URSEL0) | /*選擇訪問UCSRC寄存器*/
(3 << UCSZ00); /*UCSZ2 UCSZ1 UCSZ0=3 8個數據位*/
}
//串口1初始化
void USART1_Init()
{
UCSR1B = (1 << RXCIE1) | /*接收完成中斷允許*/
// (1 << TXCIE1) | /*發送完成中斷允許*/
(1 << RXEN0) | /*接收允許*/
(1 << TXEN0); /*發送允許*/
UBRR1H = BAUD_H; //設置波特率
UBRR1L = BAUD_L;
UCSR1C = (1 << URSEL1) | /*選擇訪問UCSRC寄存器*/
(3 << UCSZ10); /*UCSZ2 UCSZ1 UCSZ0=3 8個數據位*/
}
//串口0查詢方式發送數據
void USART0_Transmit(unsigned char data)
{
while(!(UCSR0A&(1<<UDRE0)));
/*等待發送緩沖器為空。UDRE數據寄存器空標志位,
當發送緩沖器空時被置1;發送緩沖器包含需要發送的數據時清零*/
UDR0=data; //將數據放入緩沖器,發送數據
}
//串口1查詢方式發送數據
void USART1_Transmit(unsigned char data)
{
while(!(UCSR1A&(1<<UDRE1)));
/*等待發送緩沖器為空。UDRE數據寄存器空標志位,
當發送緩沖器空時被置1;發送緩沖器包含需要發送的數據時清零*/
UDR1=data; //將數據放入緩沖器,發送數據
}
/*
//發送GPRS命令給手機模塊
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))); //等待接收數據
return UDR0; //從緩沖器中獲取并返回數據
}
*/
////////////////////////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開機
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關機
void GPRS_Off()
{
GPRS_ONOFFL;delayms(1800);
GPRS_ONOFFH;delayms(5000);
GPRS_RSTL;
}
//GPRS復位
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,選擇主機模式,SCK=fosc/128,選擇SPI模式CPOL=0,CPHA=0
*/
}
unsigned char SPI_MasterTransmit(unsigned char cData)
{
//啟動數據傳輸
SPDR = cData;
//等待數據傳輸結束
while(!(SPSR&(1<<SPIF)));
//發送完成后,清除發送標志
// SPSR&=~(1<<SPIF);
return SPDR;
//每次發送數據的同時,也會接收到數據。
}
//EEPROM寫使能
void EEPROM_WREN()
{
EEPROM_CSL; //拉低片選端
SPI_MasterTransmit(0x06); //0x06為寫使能的指令
EEPROM_CSH; //抬高片選端,結束
}
//EEPROM寫禁止
void EEPROM_WRDI()
{
EEPROM_CSL;//delayms(20);
SPI_MasterTransmit(0x04); //0x04為寫禁止的指令
EEPROM_CSH;//delayms(20);
}
//寫狀態寄存器
void EEPROM_WRSR()
{
EEPROM_WREN();
EEPROM_CSL; //使能
SPI_MasterTransmit(0x01); //0x01為寫狀態寄存器的指令
SPI_MasterTransmit(0x82); //把0x82寫入狀態寄存器
EEPROM_CSH; //抬高片選,結束
}
/*
讀狀態寄存器。讀SPI從機數據時,主機要給從機發送任意數據,才能收到從機返回的數據.
即0x00可以是任何數據(但是不能是25256的指令,例如0x01,0x04之類的)
*/
unsigned char EEPROM_RDSR()
{
unsigned char StatusReg;
EEPROM_WREN();
// EEPROM_WRDI(); //如使用此句,不使用EEPROM_WREN(),則讀出0x80
EEPROM_CSL; //使能
SPI_MasterTransmit(0x05); //0x05為讀狀態寄存器指令
StatusReg=SPI_MasterTransmit(0x00); //給25256發送任意數據
/*
此處原為:
SPDR = 0x00;
while(!(SPSR&(1<<SPIF)));
StatusReg=SPDR;
時出錯,讀出數據都為0xff。想不清楚為什么
*/
EEPROM_CSH;
return StatusReg;
}
//25256字節寫
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); //寫入數據
EEPROM_CSH;delayms(50);
}
//25256頁寫。試驗結果,只能連續寫入三個字節
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); //寫入數據
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);//發送任意數據
EEPROM_CSH;
return dataa; //返回讀到的數據
}
////////////////////////////////////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(用于新終端開關電源控制),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寫入數據0x48
USART0_Transmit(EEPROM_Read(0x2010));
USART0_Transmit(EEPROM_Read(0x2030));//讀出地址0x2030中數據,從串口0發送出來
USART0_Transmit(0x44);
USART0_Transmit(0x55);
USART0_Transmit(EEPROM_RDSR());
EEPROM_PageWrite(0x1001,"456789",6); //輸出結果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中斷,但是沒有加入中斷函數,導致其他地方不能工作。
串口中斷0能執行,是由于其優先級比串口中斷1高
以下是書上的說法:
接收結束標志位(RXC)用來說明接收緩沖器中是否有未讀出的數據。當接收緩沖器中有未讀出的
數據時,此位為1,當接收緩沖器空時為0(即不包含未讀出的數據)。如果接收器被禁止(RXEN=0),
接收緩沖器會被刷新,從而使RXC清零。
置位UCSRB的接收結束中斷使能位(RXCIE)后,只要RXC標志置位(且全局中斷使能)就會產生USART
接收結束中斷。使用中斷方式進行數據接收時,數據接收結束中斷服務程序必須從UDR讀取數據
以清除RXC標志,否則只要中斷處理程序結束,一個新的中斷就會產生。
終上所述,RXC標志未清零,導致中斷一直產生。
*/
#pragma interrupt_handler USART1Rx:21
void USART1Rx()
{
unsigned char data1;
data1=UDR1;
// USART1_Transmit(data1);
}