导航: 老古网老古论坛XMOS公共讨论区XMOS开源项目区单片机程序设计嵌入式系统广告区域
→C51编程:请问谁有24c04的程序.p2.1(sDA)P2[whf68]

 *第7565篇: C51编程:请问谁有24c04的程序.p2.1(sDA)P2.0(SCL).用P1口来显示出来.???请大侠帮忙:_))

  
楼 主:whf68 2003年1月10日16:34
 C51编程:请问谁有24c04的程序.p2.1(sDA)P2.0(SCL).用P1口来显示出来.???请大侠帮忙:_))

//单主器件I2C总线模拟子程序//

#include <at89x51.h>
#include <intrins.h>

#define uchar unsigned char
sbit VSDA=P2^1;        //将p1.0口模拟数据口
sbit VSCL=P2^0;        //将p1.1口模拟时钟口

uchar idata SLA;       //从器件地址
uchar idata SLAW;      //从器件写地址
uchar idata SLAR;      //从器件读地址
uchar idata NUMBYT;    //数据传送字节
uchar idata MTD[10]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};    //数据发送缓冲

uchar idata MRD[10];    //数据接收缓冲区
bit   bdata NACK;      //器件坏或错误标志位

//启动I2C总线子程序//
void STA(void)
{
  VSDA=1;              //启动I2C总线
  VSCL=1;
  _nop_();             //延时4.7us,根据晶振频率调整空操作个数,这里以fosc=12MHz,
下同
  _nop_();
  _nop_();
  _nop_();
  VSDA=0;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  VSCL=0;
 }


//停止I2C总线数据传送子程序//
void STOP(void)
{
  VSDA=0;              //停止I2C总线数据传送
  VSCL=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  VSDA=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  VSCL=0;
}


//发送应答位子程序//
void MACK(void)
{VSDA=0;               //发送应答位
  VSCL=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  VSDA=1;
  VSCL=0;
}


//发送非应答位子程序//
void MNACK(void)
{
  VSDA=1;              //发送非应答位
  VSCL=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  VSDA=0;
  VSCL=0;
}


//应答位检查子程序//
void CACK(void)
{
  VSDA=1;              //应答位检查(将p1.0设置成输入,必须先向端口写1)
  VSCL=1;
  F0=0;
  if (VSDA==1) F0=1;   //若VSDA=1表明非应答,置位非应答标志F0
  VSCL=0;
}


//发送一个字节数据子程序,程序入口p为发送缓冲区地址//
void WRBYT(p)
uchar idata *p;
{
  uchar idata n=8;     //向VSDA上发送一位数据字节,共八位
  uchar idata temp;
  temp=*p;
  while (n--) {
                if  ((temp&0x80)==0x80)    //若要发送的数据最高位为1则发送位1
                {  VSDA=1;      //传送位1
                   VSCL=1;
                    _nop_();
                    _nop_();
                   _nop_();
                   _nop_();
                    VSDA=0;
                     VSCL=0;
                 }
       else    {
                   VSDA=0;      //否则传送位0
                   VSCL=1;
                    _nop_();
                    _nop_();
                   _nop_();
                   _nop_();
                    VSCL=0;
                }
               temp=temp<<1;      //数据左移一位,或_crol_(*p,1)
              }
}


//接收一字节子程序,入口参数p为接收缓冲区地址//
void RDBYT(p)
uchar idata *p;
{
  uchar idata n=8;      //从VSDA线上读取一上数据字节,共八位
  uchar idata temp=0;
    while (n--)  {   VSDA=1;
                     VSCL=1;
                     temp=temp<<1;//左移一位,或_crol_(temp,1)
                     if (VSDA==1) 
temp=temp|0x01;//若接收到的位为1,则数据的最后一位置1
                           else temp=temp&0xfe;//否则数据的最后一位置0
                     VSCL=0;
                   }
    *p=temp;
}


//发送n位数据子程序//
void WRNBYT(sla,n)
uchar  *sla;
uchar   n;
{
    uchar idata *p;
    STA();             //启动I2C
    WRBYT(sla);        //发送一上位数据
    CACK();            //检查应答位
    if (F0==1) {
                 NACK=1;return;  //若非应答表明器件错误或已坏,
置错误标志位NACK
                }
    p=MTD;
    while(n--){
                WRBYT(p);
                CACK();//检查应答位
                if (F0==1) {
                             NACK=1;return;  //若非应答
表明器件错误或已坏,置错误标志位NACK
                             }
                p++;
               }
               STOP(); //全部发完则停止
}


//接收n位数据子程序
void RDNBYT(sla,n)
uchar idata *sla;
uchar  n;
{
    uchar idata *p;
    STA();
    WRBYT(sla);
    CACK();
    if  (F0==1) {
                  NACK=1;return;
                  }
    p=MRD;
     while (n--) {
                  RDBYT (p);
                  MACK();   //收到一个字节后发送一个应答位
                  p++;
                  }
    MNACK();                //收到最后一个字节后发送一个非应答位
    STOP();
}


delay(int t)
{
int i,j;
for(i=0;i<t;i++)
for(j=0;j<125;j++);
}

 main()
 {
 P2_2=0;
 delay(20);
 P2_2=1;

 SLAW=0xA0;
 SLA=SLAW;
 NUMBYT=0x09;
 WRNBYT(MRD,9);
 if (MRD[5]==0x55) P1=0x55;
 P2_3=0;
 }


whf68cn_cn@sina.com.cn
谢谢


  
2楼:mdizi 2009年5月24日09:07
 24C01-16程序,能读写:24C01、24C02、24C04、24C08、24C16[原创]
/**************************************************
    伟维电子单片机工作室
  
    Copyright 2009 mdizi McuStudi    
   All rights Reserved
作者:周洵名  QQ:491069539  13528913615


本程序在以下型号的单片机学习板上调试完成:
 
型号:TL-SST89E、TL-AT89S51、TL-SST89H、TL-SST89A、TL-STC89C、TL-Min51

AT89S52 晶振频率为11.0592MHz   指令周期:1.0852us

功能说明:24C01-16程序,能读写:24C01、24C02、24C04、24C08、24C16
读出的数据 送 P1 口显示
;***************************************************************/
#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#define uint  unsigned int
 
sbit sda=P3^7;//;模拟I2C 数据传送位
sbit scl=P3^6;//;模拟I2C 时钟控制状态标志

void  delay1(uint z)//延时为 1ms

 uchar x,x1;
 for(;z>  0;z--)
 {
   for(x=0;x  <114;x++)
   {
    for(x1=0;x1  <1;x1++);
   }
 }

void delay()//5us延时
{
 _nop_();
 _nop_();
 _nop_();
}

void star()//开始
{
 sda=1;
    delay();//5us延时
 scl=1;
    delay();//5us延时
 sda=0;
 delay();//5us延时
 
}

void stop()//停止
{
 sda=0;
 delay();//5us延时
 scl=1;
 delay();//5us延时
 sda=1;
 delay();//5us延时
 
}

void ack()//应答
{ uchar z=0;
 while((sda==1)&&(z  <50))z++;//条件判断, sda=1,则没有应答。如果没有应答则延时:z  <50,z++;后返回
    scl=0;
 delay();//5us延时
}

///写一个数据函数
//器件写地址 slave_write_address
//字节地址 byte_address
//待写入数据 data_data
void write(uchar slave_write_address,uchar byte_address,uchar data_data)//写一个数据
{
 uchar temp,temp1,i,ii;

 star();//开始

 for(ii=0;ii  <3;ii++)//根据 24CXX文档资料,和时序图,按顺序送:器件写地址,字节地址,数据
 { 
  if(ii==0)
  {
   temp=slave_write_address;//送 器件写地址
   temp1=slave_write_address;
  }
  else if(ii==1)
  {
   temp=byte_address;//送 字节地址
   temp1=byte_address;
  }
  else if(ii==2)
  {
   temp=data_data;//送 数据
   temp1=data_data;
  }


           for(i=0;i  <8;i++)
   {
    scl=0;
    delay();//5us延时
    temp=temp1;
    temp=temp&0x80;// 相 与 后,把不相关的位清零

    if(temp==0x80)//根据前面 相 与 后,判断 temp是否等于0x80,是则该位为 1
   
     sda=1;    
    else
     sda=0;
    
     delay();//5us延时
     scl=1;
     delay();//5us延时
     scl=0;
     delay();//5us延时
     temp1=temp1  <  <1;//向左移出1位
   
   }
   sda=1;
   delay();//5us延时
   scl=1;
   delay();//5us延时
   ack();
 }
 stop();//停止
}

///读一个数据函数
//器件写地址 slave_write_address
//器件读地址 slave_read_address
//字节地址 byte_address
//读出的数据 data_data

read(uchar slave_write_address,uchar byte_address,uchar slave_read_address)//读一个数据
{
  uchar temp,temp1,i,ii,x,data_data;

 star();//开始

 for(ii=0;ii  <3;ii++)//根据 24CXX文档资料,和时序图,按顺序送:器件写地址,字节地址,器件读地址
 { 
  if(ii==0)
  {
   temp=slave_write_address;//送 器件写地址
   temp1=slave_write_address;
  }
  else if(ii==1)
  {
   temp=byte_address;//送 字节地址
   temp1=byte_address;
  }
  else if(ii==2)
  {   
   star();//开始

   temp=slave_read_address;//送 器件读地址
   temp1=slave_read_address;
  }

           for(i=0;i  <8;i++)//开始读数据
   {
    scl=0;
    delay();//5us延时
    temp=temp1;
    temp=temp&0x80;// 相 与 后,把不相关的位清零

    if(temp==0x80)//根据前面 相 与 后,判断 temp是否等于0x80,是则该位为 1
   
     sda=1;    
    else
     sda=0;
    
     delay();//5us延时
     scl=1;
     delay();//5us延时
     scl=0;
     delay();//5us延时
     temp1=temp1  <  <1;//向左移出1位
   }
   sda=1;
   delay();//5us延时
   scl=1;
   delay();//5us延时
   ack();//应答
 }

 for(x=0;x  <8;x++)
 {
  data_data=data_data  <  <1;//向左移入1位

  sda=1;
  delay();//5us延时
  scl=0;
  delay();//5us延时
  scl=1;
  delay();//5us延时

  if(sda==1)//判断 数据线是否是高电平
  data_data|=0x01;//把读到的数据 或 0X01 
  //else  
     //data_data|=0x00;
 }
    ack();//应答
 stop();//停止
 return data_data;//返回读到的数据

}

void main()

 write(0xa0,0xff,0x66);//向器件写一个数据:(0xa0 是器件写地址;0xff 是字节地址;0x66 是待写入的数据)

 delay1(5);//写与读的时间间隔应大于5ms,取决于器件 24C02的响应速度

//向器件读一个数据
//把读出的数据送 P1口显示
 P1=read(0xa0,0xff,0xa1);//向器件读一个数据:(0xa0 是器件写地址;0xff 是字节地址;0xa1 是器件读地址)

 while(1);//跳转,相当于汇编指令 JUMP $
}

//0x66==亮 灭 灭 亮 亮 灭 灭 亮


>>>>>>对该主题发表你的看法

本主题贴数2,分页: [第1页]


[上一篇主题]:C51编程:老古

[下一篇主题]:C51编程:请问AT89C51的I/O口在MCU 上电时是输入状态还是输出状态,如果是输出