找回密码
 立即注册
查看: 62|回复: 0

28-I2C主机模式访问AT24C02程序AI8051U实验箱演示程序

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:274
  • 最近打卡:2026-07-21 08:44:27
已绑定手机

292

主题

1027

回帖

3313

积分

超级版主

积分
3313
QQ
发表于 2026-6-30 13:39:45 | 显示全部楼层 |阅读模式
28-I2C主机模式访问AT24C02程序AI8051U实验箱演示程序

主程序main.C代码如下(汇编版本在附件中):

/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/

/*************  功能说明    **************


本例程基于AI8051U为主控芯片的实验箱进行编写测试。

使用Keil C51编译器,为了达到比较高的效率,一般建议选择"Small"模式。

当编译器出现 "error C249: 'DATA': SEGMENT TOO LARGE" 错误时,则需要手动将部分比较大的数组通过"xdata" 强制分配到 XDATA 区域(例如: char xdata buffer [256];)

通过硬件I2C接口读取AT24C02前8个字节数据,通过串口打印读取结果.

将读取的数据加1后写回AT24C02前8个字节.

重新读取AT24C02前8个字节数据,通过串口打印读取结果.

MCU上电后执行1次以上动作,可重复断电/上电测试AT24C02前8个字节的数据内容.

串口配置UART1(P3.0,P3.1): 115200,N,8,1.

下载时, 选择时钟 24MHZ (用户可自行修改频率).

******************************************/

#include "..\comm\AI8051U.h"
#include "stdio.h"
#include "intrins.h"

/***********************************************************/

typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

/****************************** 用户定义宏 ***********************************/

#define MAIN_Fosc       24000000L   //定义主时钟
#define Baudrate        115200L
#define TM              (65536 -(MAIN_Fosc/Baudrate/4))
#define PrintUart       1        //1:printf 使用 UART1; 2:printf 使用 UART2
#define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer 0 中断频率, 1000次/秒

/*****************************************************************************/

sbit SDA = P3^3;
sbit SCL = P3^2;

/*************  本地常量声明    **************/

#define SLAW        0xA0
#define SLAR        0xA1

/*************  本地变量声明    **************/


/*************  本地函数声明    **************/
void WriteNbyte(u8 addr, u8 *p, u8 number);
void ReadNbyte( u8 addr, u8 *p, u8 number);
void delay_ms(u8 ms);
void UartInit(void);

/**********************************************/
void main(void)
{
    u8  i;
    u8  tmp[8];

    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXSFR(); //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
   
    UartInit();

    P_SW2 |= I2C_S1;//I2C功能脚选择,00:P2.4,P2.3;01:P1.5,P1.4;11:P3.2,P3.3
    P_SW2 |= I2C_S0;
    I2CCFG = 0xc2;  //使能I2C主机模式
    I2CPSCR = 0x00; //MSSPEED[13:6]
    I2CMSST = 0x00;

    EA = 1;         //打开总中断
   
    ReadNbyte(0, tmp, 8);
    printf("Read1 = ");     //打印第一次读取内容
    for(i=0; i<8; i++)
    {
        printf("%02x ",tmp);
        tmp++;
    }
    printf("\r\n");

    WriteNbyte(0, tmp, 8);  //写入新的内容
    delay_ms(250);
    delay_ms(250);

    ReadNbyte(0, tmp, 8);
    printf("Read2 = ");     //打印第二次读取内容
    for(i=0; i<8; i++)
    {
        printf("%02x ",tmp);
    }
    printf("\r\n");

    while(1);
}

//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-3-9
// 备注:
//========================================================================
void delay_ms(u8 ms)
{
     u16 i;
     do{
          i = MAIN_Fosc / 6000;
          while(--i);
     }while(--ms);
}

/********************** I2C函数 ************************/
void Wait()
{
    while (!(I2CMSST & 0x40));
    I2CMSST &= ~0x40;
}

void Start()
{
    I2CMSCR = 0x01;                         //发送START命令
    Wait();
}

void SendData(char dat)
{
    I2CTXD = dat;                           //写数据到数据缓冲区
    I2CMSCR = 0x02;                         //发送SEND命令
    Wait();
}

void RecvACK()
{
    I2CMSCR = 0x03;                         //发送读ACK命令
    Wait();
}

char RecvData()
{
    I2CMSCR = 0x04;                         //发送RECV命令
    Wait();
    return I2CRXD;
}

void SendACK()
{
    I2CMSST = 0x00;                         //设置ACK信号
    I2CMSCR = 0x05;                         //发送ACK命令
    Wait();
}

void SendNAK()
{
    I2CMSST = 0x01;                         //设置NAK信号
    I2CMSCR = 0x05;                         //发送ACK命令
    Wait();
}

void Stop()
{
    I2CMSCR = 0x06;                         //发送STOP命令
    Wait();
}

void WriteNbyte(u8 addr, u8 *p, u8 number)  /*  WordAddress,First Data Address,Byte lenth   */
{
    Start();                                //发送起始命令
    SendData(SLAW);                         //发送设备地址+写命令
    RecvACK();
    SendData(addr);                         //发送存储地址
    RecvACK();
    do
    {
        SendData(*p++);
        RecvACK();
    }
    while(--number);
    Stop();                                 //发送停止命令
}

void ReadNbyte(u8 addr, u8 *p, u8 number)   /*  WordAddress,First Data Address,Byte lenth   */
{
    Start();                                //发送起始命令
    SendData(SLAW);                         //发送设备地址+写命令
    RecvACK();
    SendData(addr);                         //发送存储地址
    RecvACK();
    Start();                                //发送起始命令
    SendData(SLAR);                         //发送设备地址+读命令
    RecvACK();
    do
    {
        *p = RecvData();
        p++;
        if(number != 1) SendACK();          //send ACK
    }
    while(--number);
    SendNAK();                              //send no ACK       
    Stop();                                 //发送停止命令
}

/******************** 串口打印函数 ********************/
void UartInit(void)
{
#if(PrintUart == 1)
    P_SW1 &= ~S1_S1;      //UART1 switch to, 0x00: P3.0 P3.1, 0x40: P3.6 P3.7, 0x80: P1.6 P1.7, 0xC0: P4.3 P4.4
    P_SW1 &= ~S1_S0;
        SCON = (SCON & 0x3f) | 0x40;
        AUXR |= (1<<6);      //定时器时钟1T模式
        AUXR &= ~S1BRT;      //串口1选择定时器1为波特率发生器
        TL1  = TM;
        TH1  = TM>>8;
        TR1 = 1;        //定时器1开始计时

//        SCON = (SCON & 0x3f) | 0x40;
//        T2L  = TM;
//        T2H  = TM>>8;
//        AUXR |= 0x15;   //串口1选择定时器2为波特率发生器
#else
        P_SW2 |= S2_S;       //UART2 switch to: 0: P1.2 P1.3,  1: P4.2 P4.3
    S2CFG |= 0x01;  //使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
        S2CON = (S2CON & 0x3f) | 0x40;
        T2L  = TM;
        T2H  = TM>>8;
        AUXR |= 0x14;              //定时器2时钟1T模式,开始计时
#endif
}

void UartPutc(unsigned char dat)
{
#if(PrintUart == 1)
        SBUF = dat;
        while(TI==0);
        TI = 0;
#else
        S2BUF  = dat;
        while((S2CON & S2TI)==0);
        S2CON &= ~S2TI;    //Clear Tx flag
#endif
}

char putchar(char c)
{
        UartPutc(c);
        return c;
}

28-I2C主机模式访问AT24C02程序.zip (8.65 KB, 下载次数: 3)
热线19952583534
www.STCAI.com
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-7-22 10:24 , Processed in 0.069532 second(s), 43 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表