C51: 向24C02,写入n个数据,再读出n 个数据

发布者:tau29最新更新时间:2016-10-14 来源: eefocus关键字:C51  24C02 手机看文章 扫描二维码
随时随地手机看文章
//函数功能,

//写入n个数据,再读出n 个数据。用LCD1602 显示。


#include
#include 


//变量声明
#define uchar unsigned char
#define uint unsigned int

//延时 1ms
void delayms()
{
 uchar i;
 for(i=0;i<250;i++);
 for(i=0;i<80;i++);
}

void delaynms(uint s)
{
 uint tem;
 for(tem=0;tem  {
  delayms();
 }

}

 


//LCD 忙碌查询
sbit LCDbusy=P1^7;

//LCD 操作位 设置
sbit RS=P3^2;
sbit RW=P3^1;
sbit E=P3^0;
sbit BF=P1^7;

 

//------  LCD 程序 ----


//读LCD 状态
uchar BusyTest()
{
 bit result;

 //读LCD 状态
 RS=0;
 RW=1;
 E=1;

 _nop_();
 _nop_();
 _nop_();

 //指令
 result=BF;

 _nop_();
 _nop_();
 _nop_();

 E=0;

 return result;


}

//写 LCD 指令
void WriteInstruction(uchar instruction)
{
 //LCD 忙碌,等待。
 while(BusyTest()==1);

 //写指令
 RS=0;
 RW=0;
 E=0;

 _nop_();   //要求
 _nop_();
 _nop_();

 //指令
 P1=instruction;

 _nop_();
 _nop_();
 _nop_();

 E=1;

 _nop_();
 _nop_();
 _nop_();

 E=0;
}

//初始化 LCD
void InitLCD()
{
 delaynms(15); 
 WriteInstruction(0x38);//  显示模式设置
 delaynms(5);
 WriteInstruction(0x38);
 delaynms(5);
 WriteInstruction(0x38);

 delaynms(5);
 WriteInstruction(0x0d);//显示模式设置: 开显示,不显示光标,闪烁光标

 delaynms(5);
 WriteInstruction(0x06);//显示模式设置: 光标右移,文字不移动。

 delaynms(5);

}

 
//写LCD 数据
void WriteData(uchar d)
{
  //LCD 忙碌,等待。
 while(BusyTest()==1);

 //写数据
 RS=1;
 RW=0;
 E=0;

 _nop_();
 _nop_();
 _nop_();

 //指令
 P1=d;

 _nop_();
 _nop_();
 _nop_();

 E=1;

 _nop_();
 _nop_();
 _nop_();

 E=0;

}

//写地址,属于写指令
void WriteAdd(uchar ad)
{
 uchar addr=ad+0x80;
 WriteInstruction(addr);
 
}

//--- 24C02 ---

sbit SDA=P2^0;          //数据总线SDA位定义在P2^0引脚
sbit SCL=P2^1;         //时钟总线SCL位定义在P2^1引脚    

uchar wdeviceadd; //定义写入器件,寻址地址
uchar rdeviceadd;  // 定义读出器件,寻址地址


//函数功能:开始数据传送  
void start()
{
 SDA = 1;    //SDA初始化为高电平“1”
   SCL = 1;    //开始数据传送时,要求SCL为高电平“1”
 _nop_();    //等待一个机器周期
 _nop_();    //等待一个机器周期
 _nop_();    //等待一个机器周期
 _nop_();    //等待一个机器周期
 SDA = 0;    //SDA的下降沿被认为是开始信号
 _nop_();    //等待一个机器周期
 _nop_();    //等待一个机器周期
 _nop_();    //等待一个机器周期
 _nop_();    //等待一个机器周期
 SCL = 0;    //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)  
}

//函数功能:结束数据传送 
void stop()
{
 SDA = 0;     //SDA初始化为低电平“0” _n
 SCL = 1;     //结束数据传送时,要求SCL为高电平“1”
 _nop_();     //等待一个机器周期
 _nop_();     //等待一个机器周期
 _nop_();     //等待一个机器周期
 _nop_();     //等待一个机器周期
 SDA = 1;    //SDA的上升沿被认为是结束信号
 _nop_();     //等待一个机器周期
 _nop_();     //等待一个机器周期
 _nop_();     //等待一个机器周期
 _nop_();     //等待一个机器周期
 SDA=0;
 SCL=0;
}         

//应答检查
bit testack()
{
 bit ack_bit;
 SDA = 1;     // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,
                 //以让SDA线转由接收设备(AT24Cxx)控制
 _nop_();        //等待一个机器周期 
 _nop_();        //等待一个机器周期 
 SCL = 1;       //根据上述规定,SCL应为高电平
 _nop_();       //等待一个机器周期 
 _nop_();       //等待一个机器周期 
 _nop_();       //等待一个机器周期 
 _nop_();       //等待一个机器周期 
 ack_bit = SDA; //接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节
                //若送高电平,表示没有接收到,传送异常
 SCL = 0;       //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)
 return  ack_bit; 
}

//应答
void ack()
{
 SDA=0;
 _nop_();
 _nop_();
 SCL = 1;
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 SCL = 0;
 _nop_();
 _nop_();
 SDA=1;
 _nop_();
 _nop_(); 
}

//非应答
void noack()
{
 SDA=1;
 _nop_();
 _nop_();
 SCL = 1;
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 SCL = 0;
 _nop_();
 _nop_();
 
}

//函数功能:从AT24Cxx读取一个字节
unsigned char ReadData()
{
 uchar i;
 uchar x;   //储存从AT24Cxx中读出的数据
 for(i = 0; i < 8; i++)
 {
  SCL = 1;                //SCL置为高电平
  x<<=1;                  //将x中的各二进位向左移一位
  x|=(unsigned char)SDA;  //将SDA上的数据通过按位“或“运算存入x中
  SCL = 0;                        //在SCL的下降沿读出数据
 }
 return(x);                //将读取的数据返回
}

 

//写入一个字节
void  WriteCurrent(unsigned char y)
{
 unsigned char i;
    for(i = 0; i < 8; i++)  // 循环移入8个位
 {
     SDA = (bit)(y&0x80);   //通过按位“与”运算将最高位数据送到S
                                    //因为传送时高位在前,低位在后
  _nop_();            //等待一个机器周期   
    SCL = 1;            //在SCL的上升沿将数据写入AT24Cxx      
    _nop_();            //等待一个机器周期 
   _nop_();             //等待一个机器周期       
  
    SCL = 0;            //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲
  y <<= 1;           //将y中的各二进位向左移一位
 }
   
}

//在器件指定地址 写 n 个字节
//参数(数据地址,器件内存地址 ,写字节数)
void writeI2C(uchar *wdata,uchar add,uchar bytes)
{
 start();               //开始数据传递
 WriteCurrent(wdeviceadd);  //选择要操作的AT24Cxx芯片,并告知要对其写入数据
 testack();
 WriteCurrent(add);       //写入指定地址0x36
 testack();
 
 //进入循环
 for(;bytes!=0;bytes--)
 {
  WriteCurrent(*wdata);       //向当前地址(上面指定的地址)写入数据 0x00 
  testack();  //应答检查
  wdata++;

 }
 stop();                //停止数据传递
 delaynms(4);

 
}

//在器件指定地址 读出 n 个字节
//参数(接收读出数据缓存地址,读数据器件内存地址 ,读出字节数)
void readI2C(uchar *rdata,uchar add,uchar bytes)
{
 /*读出数据
 流程:
 启动-写芯片寻址-应答检查-写数据首址-应答检查- 进入读数据程序段 */
 start();                      
 WriteCurrent(wdeviceadd);       //选择要操作的AT24Cxx芯片,并告知要对其写入数据
 testack();
 WriteCurrent(add);       //读出数据地址
 testack();

 /*读数据程序段流程:
 启动-写芯片寻址-应答检查- 进入读数据程序段*/  
 start();              
 WriteCurrent(rdeviceadd);   //选择要操作的AT24Cxx芯片,并告知要读其数据
 testack();

 /*读数据程序段
 条件判断-读数据-应答-指针操作-循环,
 最后一个字节退出循环-读最后一个字节-非应答-停止  */ 
 while(bytes!=1)
 {
  *rdata=ReadData(); 
  ack();  //应答
  rdata++;
  bytes--;
 }
 *rdata=ReadData();    //读出最后一个字节    
 noack();      //最后一个数据  非应答  
 stop();                //停止数据传递


}

 


//main 程序
void main() 
{
    //将此字符串存入24C02,再读出。
 uchar str[14]="this is a 2402" ;
 uchar *p;

 //读出缓存
 uchar readbuf[50];

 //定义器件地址
 wdeviceadd=0xa0; //写入器件,寻址地址
 rdeviceadd=0xa1;  // 读出器件,寻址地址

 
 //
 //
 writeI2C(str,0x00,14);

 readI2C(readbuf,0x00,14);

 //初始化LCD
 InitLCD();
 WriteAdd(0x00);           
 //写数据

 p=readbuf;
 
 while(*p!='\0')
 {
  WriteData(*p);
  p++;
 }

 delaynms(1000);

 

 

}

关键字:C51  24C02 引用地址:C51: 向24C02,写入n个数据,再读出n 个数据

上一篇:C51: 2块 24C02 的读写
下一篇:c51: 24C02 多字节读、写

推荐阅读最新更新时间:2024-03-16 15:15

LCD12864的串口驱动(asm/c51)
串行数据传送共分三个字节完成: 第一字节:串口控制 格式 11111ABC A 为数据传送方向控制:H 表示数据从LCD 到MCU,L 表示数据从MCU 到LCD B 为数据类型选择:H 表示数据是显示数据,L 表示数据是控制指令 C 固定为0 第二字节:(并行)8 位数据的高4 位 格式 DDDD0000 第三字节:(并行)8 位数据的低4 位 格式 0000DDDD 串行接口时序参数:(测试条件:T=25℃ VDD=4.5V) ////////////////////////////////////////////////////////////////////////////
[单片机]
LCD12864的串口驱动(asm/<font color='red'>c51</font>)
C51成功读写AT24C32(EEPROM)
#include reg52.h #include D:\C51_H\LCD1602.H //我的自定义LCD1602头文件 /*--------------------------------------------------------------- 24C32可存储4K(1024*4)个字节(8bit),因此寻址地址最大为0x0FFF,24C32为从机。 ----------------------------------------------------------------*/ #define WriteDeviceAddress 0x0A2 //定义器件在I2C总线中的写地址(注意:根据自定义
[单片机]
C51/C52的定时器计数器与中断
一、定时器/计数器简介 设置等待时间,到达等待时间之后执行指定的硬件操作。 定时器最基本的功能就是定时,比如说定时发送串口数据,定时采集AD数据,如果将定时器和IO结合起来就可以实现非常丰富的功能,可以测量输入信号的脉冲宽度,可以产生PWM方波,定时器产生PWM控制电机状态是工业控制的普通。 ----------------------------------------------------------------------------------------------------------------------------------------------------------- 二、定时器/计数
[单片机]
<font color='red'>C51</font>/C52的定时器计数器与中断
KEILC51编译问题ERRORL104:MULTIPLEPUBLICDEFINITIONS重复定义
今天小学妹程序有BUG,原因是因为两个c文件中用了同一个变量,但是声明有错误。 找到问题后,肯定是用extern进行全局变量声明,但是还是会报错。我记得以前这样用没问题的。 把变量放在头文件中声明,还是会报错。最后找到解决方法。 如果在头文件中定义,则编译的时候会出现重复定义的错误。如果只有头文件中声明就会出现没有定义有警告。 *** ERROR L104: MULTIPLE PUBLIC DEFINITIONS SYMBOL: K MODULE: 222.obj (222) 出现上述错误则是因为变量k重复定义,把你的头文件中的变量定义前加extern(只是变量声明不用初始化),再在某一个你要调用
[单片机]
C51单片机头文件和启动文件
STARTUP.A51//启动文件. 清理RAM.设置堆栈等.即执行完start.a51后跳转到.c文件的main函数 reg51.h //特殊寄存器的字节地址和位地址,sfr定义字节变量、sbit定义位变量,用通俗名作为变量名,并赋地址值,从而用名称来使用这些特殊寄存器。 intrins.h //定义了一些外部函数,在 C51 单片机编程中,头文件INTRINS.H的函数使用起来,就会让你像在用 汇编 时一样简便. /*-- REG51.H Header file for generic 80C51 and 80C31 microcontroller. Copyright (c) 1988-2002 Keil Ele
[单片机]
51单片机24c02的使用
#include reg52.h #include intrins.h #define AddWr 0xae //Write Address #define AddRd 0xaf //Read Address //全局变量 sbit Sda=P1^2; //定义总线连接端口 sbit Scl=P1^1; sbit WP=P1^0;//No connect here void mDelay(unsigned char j)//A normal delay { unsigned int i; for(;j 0;j--) { for(i=0;i 125;i++) {;} } } //启动 IIC总线 void
[单片机]
C51单片机发光二极管实例程序集
1、 程序实现功能:让8个排列的LED来回流动着亮1—》...——》8 1《——...《——8 箭头代表LED流动方向,先从1-8然后从8到1依次循环。程序已经测试过,运行正常//大家如果用此代码测试的话注意你的LED接在单片机的那个端口,本代码用的是P2口 #include reg52.h #define uint unsigned int #define uchar unsigned char uchar a,b; uchar code led_array ={ 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f }; //led显示编码数组,从0xfe——0x7f为从第一个led管到第8个
[单片机]
各种花样的流水灯c51程序
/*----------------------------------------------- 功能:流水灯对称移动闪烁(双闪烁) 作者:fei yu 日期:2010-6-14 ------------------------------------------------*/ #include REG52.H #define uint unsigned int void delay(uint); main() { uint comp1=0xfe; uint comp2=0x80; P1=0x7e; delay(30000); while(1) { P1=0xff;
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved