首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 单片机 >

SPI+EEPROM读写有关问题

2012-12-17 
SPI+EEPROM读写问题开发环境:Silicon Laboratories IDE+C8051F340+EEPROM IN24LC16目的:想向EEPROM中写入

SPI+EEPROM读写问题
开发环境:Silicon Laboratories IDE+C8051F340+EEPROM IN24LC16
目的:想向EEPROM中写入一串数据,然后再读出来,并显示在UART0上
状况:用Watch调试查看时发现在读的时候中间变量test_byte并没有发生变化,最终导致读出的结果不对,不知道是没有写进入,还是写错了,抑或读的不对,希望各位大侠解答


#include <C8051F340.h>                 // SFR declarations
#include <stdio.h>                     // printf is declared here
sfr16 TMR2     = 0xCC;                 // Timer2 low and high bytes together
#define uchar unsigned char
#define UINT unsigned int
#define BAUDRATE           115200  
#define SYSCLK             24000000   
#define  F_SCK_MAX         2000000    
#define  T_NSS_DISABLE_MIN 500      
#define  EEPROM_CMD_RDSR   0x05
sbit LED_1 = P3^4;             
sbit LED_2 = P3^5;
void PCA0_Init (void);
void OSCILLATOR_Init (void);
void PORT_Init (void);
void TIMER2_Init (void);
void UART0_Init (void);
void SPI0_Init (void);
void Init_Device (void);
void Delay_us (uchar time_us);
void Delay_ms (uchar time_ms);
void EEPROM_Write (UINT address, uchar value);
uchar EEPROM_Read (UINT address);
void main (void)
{
   UINT  address =0x0000;   
   uchar  test_byte;    
   UINT  i ;
   bit  flag = 1;
   Init_Device ();  
  LED_1 = 1;
  LED_2 = 1;
   for (i = 0; i < 7; i++)
   {
      test_byte = 0xAA;
  IE &= 0x7F ;
      EEPROM_Write (address, test_byte);
  IE |= 0x80 ;
  address += 1;
      
      printf ("%02x ", (UINT)test_byte);
   }
   test_byte = 0x00 ;

   // Verify 
   for (i = 0x0000; i < address; i+=2 )
   {
     IE &= 0x7F ;
      test_byte = EEPROM_Read (i);
  IE |= 0x80 ;
      if (test_byte == 0xAA)
      {
         LED_1 = 0;
         printf ("right at %u\n", i);
      }
  else {
  printf("wrong at %u\n",i);
flag = 0;
}

   }


   while (flag)                           // Loop forever
   {                                   
      LED_1 = ~LED_1;                      // Flash LED when done (all verified)
 LED_2 = ~LED_2;
      Delay_ms (200);
   }
}
void PCA0_Init (void)
{
   PCA0MD   &= ~0x40;
   PCA0MD    = 0x00;
}
void OSCILLATOR_Init (void)
{
   int i = 0;
   OSCICN    = 0x83;
   CLKMUL    = 0x80;
   for (i = 0; i < 20; i++);    // Wait 5us for initialization
   CLKMUL    |= 0xC0;
   while ((CLKMUL & 0x20) == 0);
   CLKSEL    = 0x02;
}
void PORT_Init (void)
{

   P1MDOUT   = 0x0D;       //spi sck miso mosi cs配置
   P2MDOUT   = 0x00;
   P2SKIP    = 0x03;
   P3MDOUT   = 0x30;       //LED D1 D2
   P3SKIP    = 0x0C;
   XBR0      = 0x03;  //spi i/o使能,UART TX0,RX0链接到P0.4,P0.5
   XBR1      = 0x40;  //7:弱上拉使能,6:交叉开关使能
}
void TIMER2_Init (void)
{
   CKCON    |= 0x10;
}

void UART0_Init (void)
{
   SCON0 = 0x10;                       // SCON0: 8-bit variable bit rate
                                       //        level of STOP bit is ignored
                                       //        RX enabled
                                       //        ninth bits are zeros
                                       //        clear RI0 and TI0 bits


   if (SYSCLK/BAUDRATE/2/256 < 1)
   {
      TH1 = -(SYSCLK/BAUDRATE/2);
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   } 
   else if (SYSCLK/BAUDRATE/2/256 < 4)
   {
      TH1 = -(SYSCLK/BAUDRATE/2/4);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01
      CKCON |=  0x09;
   }
   else if (SYSCLK/BAUDRATE/2/256 < 12)
   {
      TH1 = -(SYSCLK/BAUDRATE/2/12);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 00
   } else
   {
      TH1 = -(SYSCLK/BAUDRATE/2/48);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 10
      CKCON |=  0x02;
   }

   TL1 = TH1;                          // init Timer1
   TMOD &= ~0xf0;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=  0x20;
   TR1 = 1;                            // START Timer1
   TI0 = 1;                            // Indicate TX0 ready
}

//-----------------------------------------
// SPI0_Init
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configures SPI0 to use 4-wire Single-Master mode. The SPI timing is 
// configured for Mode 0,0 (data centered on first edge of clock phase and 
// SCK line low in idle state). The SPI clock is set to 2 MHz. The NSS pin 
// is set to 1.
//
//-----------------------------------------
void SPI0_Init()
{
   SPI0CFG   = 0x40;  //6:允许主方式,工作在主器件方式
   SPI0CN    = 0x0D;  // 3-2:四线单主方式,0:使能spi0


   
   // The equation for SPI0CKR is (SYSCLK/(2*F_SCK_MAX))-1
   SPI0CKR   = (SYSCLK/(2*F_SCK_MAX)) - 1;
   
}

//-----------------------------------------
// Init_Device
//-----------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Calls all device initialization functions.
//
//-----------------------------------------
void Init_Device (void)
{
   PCA0_Init ();
   OSCILLATOR_Init ();
   PORT_Init ();
   TIMER2_Init ();
   UART0_Init ();
   SPI0_Init ();
}

//-----------------------------------------
// Support Subroutines
//-----------------------------------------

//-----------------------------------------
// Delay_us

//-----------------------------------------
void Delay_us (uchar time_us)
{
   TR2   = 0;                          // Stop timer
   TF2H  = 0;                          // Clear timer overflow flag
   TMR2  = -( (UINT)(SYSCLK/1000000) * (UINT)(time_us) );
   TR2   = 1;                          // Start timer
   while (!TF2H);                      // Wait till timer overflow occurs
   TR2   = 0;                          // Stop timer
}

//-----------------------------------------
// Delay_ms
//-----------------------------------------
//
// Return Value : None
// Parameters   : 1. time_ms - time delay in milliseconds
//                   range: 1 to 255
//
// Creates a delay for the specified time (in milliseconds) using TIMER2. The 
// time tolerance is approximately +/-50 ns (1/SYSCLK + function call time).
//
//-----------------------------------------
void Delay_ms (uchar time_ms)
{
   uchar i;

   while(time_ms--)
      for(i = 0; i< 10; i++)           // 10 * 100 microsecond delay


         Delay_us (100);
}

//-----------------------------------------
// EEPROM_Write
//-----------------------------------------
//
//-----------------------------------------
void EEPROM_Write (UINT address, uchar value)
{
   // Writing a byte to the EEPROM is a five-step operation.
   
   // Step1: Set the Write Enable Latch to 1
   NSSMD0   = 0;                       // Step1.1: Activate Slave Select
   SPI0DAT = 0xA2;         // Step1.2: Send the WREN command
   while (!SPIF);                      // Step1.3: Wait for end of transfer
   SPIF     = 0;                       // Step1.4: Clear the SPI intr. flag
   NSSMD0   = 1;                       // Step1.5: Deactivate Slave Select
   Delay_us (1);                       // Step1.6: Wait for at least 
                                       //          T_NSS_DISABLE_MIN

   
   // Step3: Send the EEPROM destination address (MSB first)
   SPI0DAT  = (uchar)((address >> 8) & 0x00FF);  //一次只能传输8位数据,故先传送16位地址的高8位
   while (!SPIF);
   SPIF     = 0;
   SPI0DAT  = (uchar)(address & 0x00FF);
   while (!SPIF);
   SPIF     = 0;
   
   // Step4: Send the value to write
   SPI0DAT  = value;
   while (!SPIF);
   SPIF     = 0;
   NSSMD0   = 1;
   Delay_us (1);
   
   // Step5: Poll on the Write In Progress (WIP) bit in Read Status Register
   do
   {
      NSSMD0   = 0;                    // Activate Slave Select
      SPI0DAT  = EEPROM_CMD_RDSR;      // Send the Read Status Register command


      while (!SPIF);                   // Wait for the command to be sent out
      SPIF     = 0;
      SPI0DAT  = 0;                    // Dummy write to output serial clock
      while (!SPIF);                   // Wait for the register to be read
      SPIF     = 0;
      NSSMD0   = 1;                    // Deactivate Slave Select after read
      Delay_us (1);
   } while( (SPI0DAT & 0x01) == 0x01 );
}

//-----------------------------------------
// EEPROM_Read
//-----------------------------------------

uchar EEPROM_Read (UINT address)
{
   // Reading a byte from the EEPROM is a three-step operation.
   
   // Step1: Send the READ command
   NSSMD0   = 0;                       // Activate Slave Select
   SPI0DAT  = 0xA3;
   while (!SPIF);
   SPIF     = 0;
   
   // Step2: Send the EEPROM source address (MSB first)
   SPI0DAT  = (uchar)((address >> 8) & 0x00FF);
   while (!SPIF);
   SPIF     = 0;
   SPI0DAT  = (uchar)(address & 0x00FF);
   while (!SPIF);
   SPIF     = 0;
   
   // Step3: Read the value returned
   SPI0DAT  = 0;                       // Dummy write to output serial clock
   while (!SPIF);                      // Wait for the value to be read
   SPIF     = 0;
   NSSMD0   = 1;                       // Deactivate Slave Select
   Delay_us (1);
   
   return SPI0DAT;
}

//-----------------------------------------
// End Of File
//-----------------------------------------


[解决办法]
EEPROM要先擦除,后写。擦除是一个block一个block的擦的。
[解决办法]
IN24LC16
的代码很多,搜到之后使用IO模拟,很容易实现。
[解决办法]

引用:
EEPROM要先擦除,后写。擦除是一个block一个block的擦的。

在silicon ide中自带的示例程序中并没有擦除eeprom的内容啊
[解决办法]
换一个地址试试 

热点排行