电子产业
数字化服务平台

扫码下载
手机洽洽

  • 微信小程序

    让找料更便捷

  • 扫码下载手机洽洽

    随时找料

    即刻洽谈

    点击下载PC版
  • 华强电子网公众号

    电子元器件

    采购信息平台

  • 华强电子网移动端

    生意随身带

    随时随地找货

  • 华强商城公众号

    一站式电子元器件

    采购平台

  • 芯八哥公众号

    半导体行业观察第一站

ATmega16读写EEPROM AT25256(ICC编译)程序

来源:-- 作者:-- 浏览:1122

标签:

摘要: #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

#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);
}

 
型号 厂商 价格
EPCOS 爱普科斯 /
STM32F103RCT6 ST ¥461.23
STM32F103C8T6 ST ¥84
STM32F103VET6 ST ¥426.57
STM32F103RET6 ST ¥780.82
STM8S003F3P6 ST ¥10.62
STM32F103VCT6 ST ¥275.84
STM32F103CBT6 ST ¥130.66
STM32F030C8T6 ST ¥18.11
N76E003AT20 NUVOTON ¥9.67