串行I2C总线E2PROM AT24CXXX的应用2

10.串行I2C总线E2PROM AT24CXXX的应用2
2008-04-03 18:28
先将源代码附上。前面部分LCD12864的代码基本不变,添加上AT24C16的代码。
//LCD12864
//**********************************************************
//连线表: CPU=89S51    SysClock=12MHz                     *
//RS=P2.0   R/W=P2.1    E=P2.2    CS1=P2.3    CS2=P2.4     *
//DB0-DB7=P3.0-P3.7       /Reset=InBoard                   *
//**********************************************************
//24c16
//**********************************************************
//连线表: CPU=89S51    SysClock=12MHz                     *
//SDA=P1.6   SCL=P1.7
//**********************************************************
#include <reg52.h>
#include <stdlib.h>
#include <intrins.h>
#include <stdio.h> 
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
/****************LCD12864引脚定义*****************/ 
#define DataPort P3     //LCD128*64 I/O 信号管脚
sbit    RS =P2^0;      //数据指令
sbit    RW =P2^1;      //读写
sbit    E   =P2^2;      //使能
sbit    CSL =P2^3;      //左片选
sbit    CSR =P2^4;      //右片选 
uchar Page;             //页 地址
uchar Col;              //列 地址 
uchar code BMP1[];      //一幅图
uchar code HZK_12[];    //12×12阵点字模
uchar code ASC_5x7[];   //5×7阵点字模
uchar str[4];
/**************AT24C16引脚定义*****************/ 
sbit    SDA =P1^6;      //数据
sbit    SCL =P1^7;      //时钟
/***********************************************/
/****************LCD12864函数定义*******************/
void BusyL(void);          //左屏检测忙
void BusyR(void);          //右屏检测忙
void CheckBusy(void);      //读取忙信号
void Delay(uint MS);       //延时
void Locatexy(void);       //将屏幕横向0-12纵向0-7转换成左、右屏的的X、Y
void WriteCommandL( uchar CommandByte );    //向左屏写入指令
void WriteCommandR( uchar CommandByte );    //向右屏写入指令
uchar ReadData( void );       //读数据
void WriteData( uchar DataByte );    //写数据
void LcmClear( void );       //清屏
void LcmInit( void );        //初始化
void LcmPutBMP( uchar *puts );      //显示一幅图
void LcmReverseBMP( void );         //将整屏反显
void LcmPutHZ_12( uchar x,uchar y,uchar HZcode ); //在屏幕上任意点显示一个12×12汉字
uchar * uchartostr(unsigned char unm);            //将值转成字符串
void LcmPutAsc( uchar asc );     //显示一个5×7的ASC字符
void LcmPutstr( uchar row,uchar y,uchar * str );       //在设定位置显示字符串
void LcmPutpoint( uchar ro,uchar lie,uchar colour );   //在设定位置显示一个点
/****************AT24C16函数定义*******************/
/****向总线上发送n字节数***/
bit write_nbyte(uchar block_addr,uchar addr,uchar *s,uchar numb);
/****从总线上读取n个字节数******/
bit read_nbyte(uchar block_addr,uchar addr,uchar *s,uchar numb);
/*****************************
说明:
block_addr   存储器的块地址选0-8
addr         存储器的存储地址
*s        一般是用在数组的首地址
numb      要写入的字节数
********************************/

/***************************/
/*检查Busy                 */
/***************************/
void BusyL(void)
{
        CSL= 1;
        CSR= 0;
        CheckBusy();

void BusyR(void)
{
        CSL= 0;
        CSR= 1;
        CheckBusy();

void CheckBusy(void)
{
        RS = 0;         //指令
        RW = 1;
DataPort= 0xFF;      //输出0xff以便读取正确
        E = 1;
        _nop_();
        while(0);//DataPort & 0x80);       //Status Read Bit7 = BUSY
        E = 0;
        _nop_();

/********************************************************/
/*根据设定的坐标数据,定位LCM上的下一个操作单元位置     */
/********************************************************/
void Locatexy(void)
{
        uchar x,y;
        switch (Col&0xc0)       /* col.and.0xC0        */
        {                       /*条件分支执行          */
                case 0:         {BusyL();break;}/*左区 */
                case 0x40:      {BusyR();break;}/*右区 */
        }
        x = Col&0x3F|0x40;      /* col.and.0x3f.or.Set Y Address*/
        y = Page&0x07|0xB8;     /* row.and.0x07.or.set Page     */
        CheckBusy();                /* waitting for enable */
        RS = 0;                 //指令
        RW = 0;                 //写
        DataPort = y;                 //设置页面地址
        E = 1;
        _nop_();
        E = 0;
        _nop_();
        CheckBusy();                /* waitting for enable */
        RS = 0;
        RW = 0;
        DataPort = x;                 //设置列地址
        E = 1;
        _nop_();
        E = 0;
        _nop_();

/***************************/
/*写指令                   */
/***************************/
void WriteCommandL( uchar CommandByte )
{
        BusyL();
        DataPort = CommandByte;
        RS = 0;         //指令
        RW = 0;
        E = 1;
        _nop_();
        E = 0;
        _nop_();

void WriteCommandR( uchar CommandByte )
{
        BusyR();
        DataPort = CommandByte;
        RS = 0;         //指令
        RW = 0;
        E = 1;
        _nop_();
        E = 0;
        _nop_();

/***************************/
/*读数据                   */
/***************************/
uchar ReadData( void )
{
        uchar DataByte;
        Locatexy();     /*坐标定位,返回时保留分区状态不变      */
        RS = 1;         /*数据输出*/
        RW = 1;         /*读入 */
        DataPort = 0xFF;              //输出0xff以便读取正确
        E = 1;         /*读入到LCM*/
        _nop_();
        DataByte = DataPort; /*数据读出到数据口P1 */
        E = 0;
        _nop_();
        return DataByte;

/***************************/
/*写数据                   */
/***************************/
void WriteData( uchar DataByte )
{
        Locatexy();     /*坐标定位,返回时保留分区状态不变      */
        RS = 1;         /*数据输出*/
        RW = 0;         /*写输出 */
        DataPort = DataByte; /*数据输出到数据口 */
        E = 1;         /*写入到LCM*/
        _nop_();
        E = 0;
        _nop_();

void LcmClear( void )
{
        Page = 0;
        Col = 0;
        for(Page=0;Page<8;Page++)
                for(Col=0;Col<128;Col++)
                        WriteData(0);

void LcmInit( void )
{
    Delay(200);     //等待复位
        WriteCommandL(0x3f);    //开显示
        WriteCommandR(0x3f);
        
        WriteCommandL(0xc0);    //设置起始地址=0
        WriteCommandR(0xc0); 
        WriteCommandL(0x3f);    //开显示
        WriteCommandR(0x3f); 
        LcmClear();
        Col = 0;
        Page= 0;
        Locatexy();
}
void LcmPutBMP( uchar *puts )
{
        uint X=0;
        Page = 0;
        Col = 0;
        for(Page=0;Page<8;Page++)
        {
                for(Col=0;Col<128;Col++)
                {
                        WriteData( puts[X] );
                        X++;
                }
        }

void LcmReverseBMP( void )
{
        uchar temp;
        Page = 0;
        Col = 0;
        for(Page=0;Page<8;Page++)
        {
                for(Col=0;Col<128;Col++)
                {
                        temp = ReadData();      //空读一次
                        temp = ReadData();
                        temp = ~temp;
                        WriteData(temp);
                }
        }

void LcmPutHZ_12( uchar x,uchar y,uchar HZcode )
{      
   uchar offset,Rd,Wt,m,tmp,i;
   uint n;
   if(x<117&y<53)
    {
    Page=(y & 0x38)>>3;
   Col=x;
      n = 0x18*HZcode;
   offset=y&0x07;
   if(offset<5)
   {
             for(i=12;i>0;i--)
              { 
                 Rd=ReadData();
       Rd=ReadData();
       m=HZK_12[n];
             Wt=Rd&(0xff>>(8-offset))|(m<<offset);
                 WriteData(Wt);
         Page++;
         n++;
         tmp=m;
         m=HZK_12[n];
         Rd=ReadData();
       Rd=ReadData();
         Wt=tmp>>(8-offset)|(m<<offset)|(Rd&(0xff<<(offset+4)));
                 WriteData(Wt);
                 Col++;
                 Page--;
       n++;
      }
   }
   else
   {
       for(i=12;i>0;i--)
                 {
                   Rd=ReadData();
       Rd=ReadData();
           m=HZK_12[n];
               Wt=Rd&(0xff>>(8-offset))|(m<<offset);
                   WriteData(Wt);
           Page++;
           n++;
           tmp=m;
           m=HZK_12[n];
       Wt=tmp>>(8-offset)|(m<<offset);
       WriteData(Wt);
       Page++;
       n++;
       Rd=ReadData();
       Rd=ReadData();
       Wt=m>>(8-offset)|(Rd&(0xff<<(offset-4)));
        WriteData(Wt);
       Page=Page-2;//恢复位置
       Col++; //修正下一个汉字的起始位置
       }
        }
   }
}
uchar * uchartostr(uchar unm)
{
uchar x00,xx,x0,x,n;
x00=unm/100;
xx=unm%100;
x0=xx/10;
x=xx%10;
n=0;
if(x00!=0)
{ str[n]=x00+48; //值加48即为字符
    n++;
}
if(!(x00==0&x0==0))
{ str[n]=x0+48;
    n++;
}
str[n]=x+48;
n++;
str[n]='\0';
   return str;
}
void LcmPutAsc( uchar asc )
{
        uchar j;
        uint x;
        x = 5*(asc-32);
            for(j=0;j<5;j++)
                {
                        WriteData(ASC_5x7[x]);
                        x++;
                        Col++;
                }
            WriteData(0x00); 
            Col++;
}
void LcmPutstr( uchar row,uchar y,uchar * str )
{ unsigned char * x;
   x=str;
Page=row;
Col=y;
while(*x!='\0')
{ LcmPutAsc( *x );
    x++;
}
}

void LcmPutpoint( uchar ro,uchar lie,uchar colour )   //画点函数
{
    if((ro<64)&(lie<128))
   {
        uchar modbyte,outByte;
        uchar offsetbit;
    Col=lie;                  //列等于lie
        Page=(ro & 0x38)>>3;     //页等于行数row与00111000B再右移3位
        offsetbit=ro&0x07;       //偏移量为行数与00000111
        modbyte=1;
    modbyte<<= offsetbit;     //输出位的模00000001左移offsetbit位
    outByte=ReadData();
    outByte=ReadData();
    if(colour==0)
    {
          modbyte=~modbyte;
      outByte=modbyte&outByte;     //输出位不影响其它位
    }
    else outByte=modbyte|ReadData();     //输出位不影响其它位
        WriteData(outByte);
   }
}

void Delay(uint MS)
{
        uchar us,usn;
        while(MS!=0)
        {
                usn = 2;        //for 12M
                while(usn!=0)
                {
                        us=0xf6;
                        while (us!=0){us--;};
                        usn--;
                }
                MS--;
        }
}

//下面是24c016的函数
//**********************************************************
//连线表: CPU=89C51    SysClock=12MHz                     *
//SDL=P1.6   SCL=P1.7
//**********************************************************

/********起始信号*********/
void start_iic()
{
SDA=1;
SCL=1;
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SCL=0;
}
/*************************/
/********停止信号*********/
void stop_iic()
{
SDA=0;
SCL=1;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
SCL=0;
}
/***********************/
/*******产生应答信号********/
void ack_iic()
{
SDA=0;
SCL=1;
_nop_();
_nop_();
SCL=0;
SDA=1;
}
/*************************/
/*****产生非应答信号******/
void nack_iic()
{
SDA=1;
SCL=1;
_nop_();
_nop_();
SCL=0;
SDA=0;
}
/************************/
/****向总线上发送一个字节数据****/
write_byte(uchar c)
{
uchar i;
for(i=0;i<8;i++)
    {
    if(c&0x80) SDA=1;
   else SDA=0;
   SCL=1;
   _nop_();
   _nop_();
   SCL=0;
   c=c<<1;
}
SDA=1;
SCL=1;
_nop_();
_nop_();
if(SDA==1) F0=0;
else F0=1;
SCL=0;
}
/*************************/
/*****从总线上读取一个字节数据*******/
uchar read_byte()
{
uchar i;
uchar r=0;
SDA=1;
for(i=0;i<8;i++)
    {
    r=r<<1;
   SCL=1;
   _nop_();
   _nop_();
   if(SDA==1) r++;
   SCL=0;
}
return r;
}
/*******************************/
/****向总线上发送n字节数据*****/
bit write_nbyte(uchar block_addr,uchar addr,uchar *s,uchar numb)
/*****************************
block_addr   存储器的块地址选0-8
addr         存储器的存储地址
*s        一般是用在数组的首地址
numb      要写入的字节数
********************************/
{
uchar i,slave;
start_iic();
slave=0xa0|(block_addr<<1);
write_byte(slave);
if(F0==0) return 0;
write_byte(addr);
if(F0==0) return 0;
for(i=0;i<numb;i++)
    {
    write_byte(*s);
   if(F0==0) return 0;
   s++;
}
stop_iic();
return (1);
}
/***************************/
/****从总线上读取n个字节数据***/
bit read_nbyte(uchar block_addr,uchar addr,uchar *s,uchar numb)
/******变量说明:
block_addr   存储器的块地址选0-8
addr         存储器的存储地址
*s        一般是用在数组的首地址
numb      要写入的字节数
*******/
{
uchar i,slave;
start_iic();
slave=0xa0|(block_addr<<1);
write_byte(slave);
if(F0==0) return 0;
write_byte(addr);
if(F0==0) return 0;
start_iic();
slave=0xa1|(block_addr<<1);
write_byte(slave);
if(F0==0) return 0;
for(i=0;i<numb-1;i++)
    {
    *s=read_byte();
   ack_iic();
   s++;
}
*s=read_byte();
nack_iic();
stop_iic();
return (1);
}
/**************************/


void Main( void )
{
        uchar x,i;
   uchar *ascii;
   uchar abcd[9];
        LcmInit();
        LcmClear();
        ascii=abcd;
    //write_nbyte(0,0,ascii,8);
    read_nbyte(0,0,ascii,8);
   while(1)
        {
          LcmClear();
              LcmPutBMP(BMP1);
              Delay(3000);
      LcmClear();
              //LcmReverseBMP();
              Delay(1000);
          //LcmClear();
     /*
      x=0;
      for(i=0;i<8;i++)
      {
                LcmPutHZ_12(x,i*7,i);
      x=x+16;
      }
      */
      LcmPutstr( 3,40,ascii );
      LcmPutstr( 5,40,"AT24C16!" );
              Delay(5000);
       
        }
}
程序接下篇。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值