⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 framflashmemory.c

📁 这是一个使用C8051F020单片机实现对时钟芯片SD2000E操作以及对单片机内部FLASH进行读写的例程。操作时钟时采用了模拟时序的方式而不是常规的中断方式。
💻 C
字号:
/*******************NVRAM读写程序以及时钟程序********************************/
/*******************用芯片SD2000E来实现**************************/

#include <C8051f120sfr.h>
#include <intrins.h>
#include <DataDefine.h>

#define DELAY_WRITE		5000 			// 延时时间,目的是让I2C元件读的过程
#define high_byte(x)    ((x&0xff00)>>8)	// 取字的高位字节	

//外部变量定义
xdata unsigned int smbus_over_time_num=0;
xdata unsigned char MyBuff[72];

//I2C元件读写部分函数原型
void NVRAM_write_byte (unsigned char data_out, unsigned char address); //写NVRAM
unsigned char NVRAM_read_byte (unsigned char address); //读NVRAM               
void i2c_write (unsigned char output_data);                     
unsigned char i2c_read (void);                                  
void delay_time (unsigned int time_end);                        
void i2c_start (void);
unsigned char  i2c_stop_and_read (void);
void repeated_i2c_start_and_write (unsigned char output_data);
void i2c_stop_and_write (unsigned char output_data);
 

//SD2000B(第一页)的写入程序,如果是SD2000E,需注意机器字及地址位数的区别。
void NVRAM_write_byte (unsigned char data_out, unsigned char address)  // 往NVRAM里写一个字节
{
xdata unsigned int i,j;
    char SFRPAGE_SAVE=SFRPAGE;
    SFRPAGE=SMB0_PAGE;

    i=address;
    EA=0;
	i2c_start();							// 使总线开始工作
   	i2c_write(0xA0);              			// 往总线上写目标装置的地址,以便识别目标装置
   	i2c_write(address);  	                // 写NVRAM中地址的低位
   	i2c_stop_and_write(data_out);      		// 往给定地址中写数据并停止总线   	
    EA=1;		
    for(j=0;j<2000;j++)                     // 延时一段时间给NVRAM让它自己写
    _nop_();
    SFRPAGE=SFRPAGE_SAVE;
}
 
//SD2000B(第一页)的读出程序,如果是SD2000E,需注意机器字及地址位数的区别。
unsigned char NVRAM_read_byte (unsigned char address)            // 从NVRAM中读一个字节
{
   	unsigned char data_in;
    xdata unsigned int i;
    char SFRPAGE_SAVE=SFRPAGE;
    SFRPAGE=SMB0_PAGE;

    i=address;
    EA=0;
	i2c_start();							// 发送开始信号
  	i2c_write(0xA0);              			// 发送目标元件地址,标志位为写
//   	i2c_write(high_byte(address));   		// 发送要读数据地址的高位
	repeated_i2c_start_and_write((unsigned char)address);	//发送要读地址的地位并重发起始信号				
   	i2c_write(0xA1);              			// 发送目标元件地址,标志位为读
   	data_in = i2c_stop_and_read();			// 读数据并停止总线
    EA=1;

    SFRPAGE=SFRPAGE_SAVE;
   	return data_in;                 
}

//  当SCL为高时,SDA上由高到低的变化,就是一个起始状态,这个状态必须先于其它任何命令
void i2c_start (void)                       // 发送起始条件函数
{
	while (BUS_BUSY)						// 判断总线是否空闲
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_STOP=1;
          SMB0CN=0x00;
          SMB0CN=0x44;                            //应答周期内返回确认,允许SMBUS
		  BUS_BUSY=0;
          smbus_over_time_num=0;
	   }
    }
    smbus_over_time_num=0;
	BUS_START = TRUE;						// 若总线空闲,就发送一个起始条件
	while (!BUS_INT)						// 判断起始条件是否发送
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_INT=1;
	      BUS_STOP=1;
          smbus_over_time_num=0;
	   }
    }
    smbus_over_time_num=0;
	BUS_START = FALSE;						// 起始条件发送后该位复位,否则将重复发送起始条件
	BUS_INT = 0;							// 将中断标志清零
}

void repeated_i2c_start_and_write (unsigned char output_data)    // 重复开始并写,用于随即读的时序中,顺序???
{
	BUS_START = TRUE;						// 发送开始标志
	SMB0DAT = output_data;					// 将要写的数据写到数据寄存器
	while (!BUS_INT)						// 等待发送完成
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_INT=1;
	      BUS_STOP=1;
          smbus_over_time_num=0;
	   }
    }
    smbus_over_time_num=0;
	BUS_INT = 0;							// 中断标志清零
	BUS_START = FALSE;						// 起始条件发送后该位复位,否则将重复发送起始条件
	while (!BUS_INT)						// 这句是否可以不要????
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_INT=1;
	      BUS_STOP=1;
          smbus_over_time_num=0;
	   }
    }
    smbus_over_time_num=0;
	BUS_INT = 0;							// 将中断标志清零
}

void i2c_stop_and_write (unsigned char output_data)        // 发送停止信号并写,用于字节写的时序
{
	BUS_STOP = TRUE;						// 发送停止信号
	SMB0DAT = output_data;					// 发送要写的最后一个数据
	while (!BUS_INT)						// 等待发送完
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_INT=1;
	      BUS_STOP=1;
          smbus_over_time_num=0;
	   }
    }
    smbus_over_time_num=0;
	BUS_INT = 0;							// 中断标志清零
}

unsigned char i2c_stop_and_read (void)      // 发送停止信号并读,用于随机读的时序
{
	unsigned char input_data;

	BUS_STOP = TRUE;						// 发送停止信号
	while (!BUS_INT)						// 等待发送完
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_INT=1;
	      BUS_STOP=1;
          smbus_over_time_num=0;
	   }
    }
	smbus_over_time_num=0;                  //SMBUS超时计数器清零

	input_data = SMB0DAT;					// 读数据
	BUS_INT = 0;							// 清中断标志

	return input_data;
}

void i2c_write (unsigned char output_data)  // 向总线上写一个字节
{
	SMB0DAT = output_data;					// 将要写的数据装入总线数据寄存器
	while (!BUS_INT)						// 判断数据是否发送出去
	{
	   smbus_over_time_num++;
	   if(smbus_over_time_num>=5000){       //如果超时,则发送停止条件
	      BUS_INT=1;
	      BUS_STOP=1;
          smbus_over_time_num=0;
	   }
    }
    smbus_over_time_num=0;
	BUS_INT = 0;							// 发送完将中断标志清零
}

void Write_Self_Flash(void)
{
   unsigned char i,j,k;
   unsigned char xdata *pwrite;
   char SFRPAGE_SAVE=SFRPAGE;
   SFRPAGE=LEGACY_PAGE;

   EA=0;
   FLSCL=0x31;
   PSCTL=0x07;
   pwrite=0x10000;
   *pwrite=0;
   for(i=0;i<255;i++)
   for(j=0;j<255;j++)
   for(k=0;k<10;k++)
   _nop_();
   PSCTL=0x05;
   for(i=0;i<72;i++)
   *(pwrite+i)=MyBuff[i];
   PSCTL=0;
   FLSCL=0x30;
   EA=1;

   SFRPAGE=SFRPAGE_SAVE;
}

void Read_Self_Flash(void)
{
   unsigned char i;
   unsigned char code  *pread;
   char SFRPAGE_SAVE=SFRPAGE;
   SFRPAGE=LEGACY_PAGE;

   PSCTL=0x04;
   pread=0;
   for(i=0;i<72;i++)
   MyBuff[i]=*(pread+i);
   PSCTL=0;

   SFRPAGE=SFRPAGE_SAVE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -