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

📄 at24c02.#3

📁 C8051F.rar
💻 #3
字号:
//参考程序A:AT24C02.C   SMBUS  24C02 读/写  2005.12.25
//程序功能:在AT24C02的地址00---3FH中依次存入连续的数据10H--4FH
//再依次从地址00---3FH中读出数据并通过SAA1064驱动四位数码管显示出来.
//第一,二位数码管显示地址,第三,四位数码管显示存入该地址内的数据.
//显示格式:
//存储器的地址	存储器单元的内容
//00H---3FH	40H---4FH
#include <c8051f020.h>                    // SFR declarations
#include <intrins.h>
#define  WRITE       0x00                 //  SMBUS寻址字节的写标志位
#define  READ        0x01                 //  SMBUS寻址字节的读标志位
// Device addresses
#define  CHIP_A        0xA0                //AT24C02器件自身的寻址字节
#define  CHIP_B        0x70                //AT24C02器件自身的寻址字节
#define  SMB_BUS_ERROR  0x0  //总线错误                                  
  //MT为主发送器,MR为主接收器
#define  SMB_START      0x08              // (MT & MR) 发送起始位
#define  SMB_RP_START   0x10              // (MT & MR) 重复起始位
#define  SMB_MTADDACK   0x18              // (MT) 发送从地址 + W 后收到ACK
#define  SMB_MTADDNACK  0x20              // (MT) 发送从地址 + W 后收到NACK
#define  SMB_MTDBACK    0x28              // (MT) 发送数据后收到ACK
#define  SMB_MTDBNACK   0x30              // (MT) 发送数据后收到NACK
#define  SMB_MTARBLOST  0x38              //(MT)竞争失败
#define  SMB_MRADDACK   0x40              // (MR) 发送从地址 + R 后收到 ACK
#define  SMB_MRADDNACK  0x48              // (MR) 发送从地址 + R 后收到 NACK
#define  SMB_MRDACK     0x50              // (MR) 收到数据字节 后已发送ACK                                    
#define  SMB_MRDBNACK   0x58              // (MR) 收到数据字节 后已发送NACK      
char DATA0[6]={0x17,0x3f,0x06,0x5b,0x4f}; 
char	xdata DATA2[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
char SLAW,DATA1[64];                    // 保存从地址+ WRITE 位
char SLAR;                              // 保存从地址+ WRITE 位
char WORD,WORDADR;                      // 保存被收/发的数据字节
char xdata sendnumber;                  // 保存被收/发的数据字节的数目        
//unsigned char xdata  WORDADR;         //保存被传送的数据在24C02中的首地址.
unsigned char xdata SENDMODE;           //SENDMODE作读/写控制字                       
unsigned char xdata  i,j,k,sla,n,m,p;
bit SM_BUSY;           //忙碌标志位                                        void sleep_ms( unsigned int count);       //延时
void SYSCLK_Init (void);                  //系统时钟初始化
void DISPLAY(void);                       //通过SAA1064驱动四位数码管显示
void SMBUS_ISR (void);                    //中断服务程序
char SLA_READ(char chip,char wordadr,char number);
void SLA_SEND(char chip,char wordadr, char word,char number);
void sleep_ms(unsigned int count);

void MAIN (void)
{
   unsigned char check;              // 测试用的工作变量
   WDTCN = 0xde;                          // 关闭看们狗
   WDTCN = 0xad;
   SYSCLK_Init();                         // 时钟初始化
   XBR0 = 0x01;                           // 选交叉开关	:P0.0-->SDA,P0.1-->CLK
   XBR2 = 0x40;                           // 交叉开关使能
   SMB0CN = 0x44;                         // 允许SMBUS, 应答返回AA(低电平
   SMB0CR = 0xc9;                   // SMBus 速率= 100 kHz,系统时钟为11.0592MHZ
   EIE1 |= 2;                             // SMBus 中断使能
   EA = 1;                                // 开中断
   SM_BUSY = 0;                           //  SM_BUSY是忙碌标志位
   SI = 0;                                //SM_BUSY中断标志位
   //写64个连续的数据到AT24C02中去并依次存放.
//64个连续的数据的存放地址:00H--3fH.第一个数为10H,最后一个数为4FH.
   i=0x10;
   sla=CHIP_A;
  for  (j=0;j<0x40;j++)            //向24C02的000地址依次写入64个数据,
  {                                //64个数据的数值从10H---4FH   
   SLA_SEND(sla, j, i,0x01);       // 写入AT24C02
   i++;
   }
  for  (j=0;j<0x40;j++)          //从24C02的00地址依次连续读出64个数据,
  {                              //64个数据的数值应该是从10H---3FH(连续存放)
   check=SLA_READ(sla, j,0x01);     
   DATA1[j]=check;               //读出来的数据依次连续存入数组DATA[]中
   }
   for  (j=0;j<0x40;j++)     //把要显示的两位地址和两位数据存入DATA2[]中           
  { i=DATA1[j];              
    k=i&0x0f;
	m=DATA2[k];              //j为地址,i=DATA1[j]=check,i地址j中存放的数据
	DATA0[4]=m;
	k=i&0xf0;
	k=k>>4;
    n=DATA2[k];
	DATA0[3]=n;
    k=j&0x0f;
	m=DATA2[k];
	DATA0[2]=m;
	k=j&0xf0;
	k=k>>4;
    n=DATA2[k];
	DATA0[1]=n;
	DISPLAY();
    sleep_ms(1000);
	} 
   while(1);
 }
void  DISPLAY (void)
{
  sla=CHIP_B;
   	DATA0[0]=0x17;              //0x17是SAA1064的控制字.
  for  (p=0;p<0x5;p++)
  {i=DATA0[p];	               //向SAA1064写入五个数:SAA1064的控制字一字节,
  SLA_SEND(sla, p, i,0x01);     // 地址2字节,数据2字节.共五字节
}
}
 void SYSCLK_Init (void)
{
   int i;                               // i 用于延时计数
   OSCXCN = 0x67;                       // 先选择外捕振荡器,频率位11.0592MHZ
   for (i=0; i < 256; i++) ;            // 再延时(>1ms),
   while (!(OSCXCN & 0x80)) ;           // 等待外部晶振稳定
   OSCICN = 0x88;                       // 选择外部晶振,允许时钟丢失检测
}
void SLA_SEND(char chip, char wordadr, char word,char number)
{
  SENDMODE=0x01;
   sendnumber=number+1;
   while(SM_BUSY);               // 若SMBUS忙碌就等待
   SM_BUSY = 1;                  // 置SM_BUSY位(忙碌标志位)为1                
   SLAW = (chip| WRITE);         // COMMAND = 7 个地址位 + 一位WRITE.
   WORD = word;                  // WORD中存放要送到24C02中去的数据(8位)
   WORDADR = wordadr;            // OP_CODE 中存放被传送数据送入24C02的首地址.
   STO = 0;
   STA = 1;                         // 启动数据传输
   while(SM_BUSY);                  // 等待传输完成
}
char SLA_READ(char chip, char wordadr,char number){
   sendnumber=number;
  SENDMODE=0;
   while(SM_BUSY);                  // 若SMBUS忙碌就等待
   SM_BUSY = 1;                     // 置SM_BUSY位(忙碌标志位)为1 
   SLAR = (chip| READ);             // COMMAND = 7 个地址位 + 一位READ
   WORDADR = wordadr;                // OP_CODE 中存放从24C02读出数据的的首地址.
   STO = 0;
   STA = 1;                          // 启动传输
   while(SM_BUSY);                   // 等待传输完成 
   return WORD;                      //返回读出来的数据(一个字节)
}
void SMBUS_ISR (void) interrupt 7    //中断服务程序
{
   switch (SMB0STA){                 // 根据中断状态码跳转
                                     //(SMB0STA 是中断状态寄存器)
       case SMB_START:	             //0x08, (MT & MR) 发送起始位
         SMB0DAT = SLAW ;            // 装入被访问的从芯片的写地址
         STA = 0;                    // 人工清除 STA 位
         SI = 0;                     // 清除中断标志位
         break;
       case SMB_RP_START:	         //0x10,(MT & MR) 重复发送起始位
         SMB0DAT = SLAR;             // 装入被访问的从芯片的读地址
         STA = 0;                    // 人工清除 STA 位
         SI = 0;                     // 清除中断标志位
         break;
       case SMB_MTADDACK:            //0x18 ,(MT) 发送从地址 + W 后收到ACK
         SMB0DAT = WORDADR;
         SI = 0;                     // 清除中断标志位
         break;
       case SMB_MTADDNACK:     	    //0x20,(MT) 发送从地址 + W 后收到NACK
         STO = 1;
         STA = 1;
         SI = 0;                    // 清除中断标志位
         break;
      case SMB_MTDBACK:		        //0x28,(MT) 发送数据后收到ACK
         switch (SENDMODE){         // 检查低1位
       case 1:
			   sendnumber--;
			   if(sendnumber)
			   SMB0DAT = WORD;
			   else{
			   		STO=1;
				   	SM_BUSY=0;
				}
              break;             
       case 0:
			     STO = 0;
               STA = 1;
               break;            
       default:              
               STO = 1;
               SM_BUSY = 0;
               break;
         }
         SI = 0;
         break;
      case SMB_MTDBNACK:	//0x30
         STO = 1;
         STA = 1;
         SI = 0;                          // 清除中断标志
         break;
      case SMB_MRADDACK:	//0x40
         AA = 0;                        
         SI = 0;
         break;
   	  case SMB_MRADDNACK:	//0x48
         STO = 0;
         STA = 1;
         SI = 0;
         break;
     case SMB_MRDBNACK:	    //0x58
         WORD = SMB0DAT;
         STO = 1;
         SM_BUSY = 0;
         AA = 1;                          
         SI = 0;
         break;
      default:
         STO = 1;
         SM_BUSY = 0;
         break;
      }
}
/*延时子程序*/
void sleep_ms(unsigned int count)
{
  unsigned int ii,jj;
  for(ii=0;ii<count;ii++)
    {
      for(jj=0;jj<250;jj++)
	  _nop_();	
	   _nop_();	
	    _nop_();	
		 _nop_();			
    }	
}

⌨️ 快捷键说明

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