找回密码
 立即注册
查看: 52|回复: 4

发现一个STC32G做I2C从机的问题,IIC经验

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-10-29 22:49:01

2

主题

5

回帖

36

积分

等待验证会员

积分
36
发表于 5 天前 | 显示全部楼层 |阅读模式
我在STC32G12K128做I2C从机时发现 P_SW2 必须要使能访问XFR

即 P_SW2 |= 0x80 ; 否则从机不工作。
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-10-29 22:49:01

2

主题

5

回帖

36

积分

等待验证会员

积分
36
发表于 5 天前 | 显示全部楼层
以下是我的IIC从机代码,实验是可用的。

#include "stc32g.h"
#include "Uart.h"

unsigned char i2c_received_data = 0;

void main(void)
{
                WTST  = 0 ;
    EAXFR = 1 ;    // EAXSFR(); 伪装成函数,实际是  EAXFR = 1 ;
    CKCON = 0 ;       
       
                Uart1_Init();
                P_SW2 |= 0x80 ;                        //使用IIC必须使能访问XFR
                P_SW2 &= ~0x30;                        //把IIC针脚调置到 P14:SDA P15:SCL
    I2CCFG = 0x81;
    I2CSLADR = 0x06;
                I2CSLCR = 0x78;
   
                P1M0 |= 0x30;
    P1M1 |= 0x30;   //这里只定义了 P14和P15 用于I2C 开漏模式。
                P0M0 |= 0x01; P0M1 &= ~0x01;
                EA = 1;

    while(1)
    {
            // 处理接收到的数据
                        if ( i2c_received_data == 0x70 ){
                                //        SendData( i2c_received_data );
                                        i2c_received_data = 0xFF;
                                        P00 = ~P00 ;       
                        }
    }
}

void I2C_Slave_ISR(void) interrupt 24
{
    if ( I2CSLST & 0x40 ) {
        I2CSLST &= ~0x40 ;
    }
                else if ( I2CSLST & 0x20 ) {
        I2CSLST &= ~0x20 ;
        i2c_received_data = I2CRXD;
    }
                else if ( I2CSLST & 0x10 ) {
        I2CSLST &= ~0x10 ;
    }
                else if ( I2CSLST & 0x08 ) {
        I2CSLST &= ~0x08 ;       
    }
}
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-10-29 22:49:01

2

主题

5

回帖

36

积分

等待验证会员

积分
36
发表于 5 天前 | 显示全部楼层
以下是主机代码
#include "STC32G.h"
#include "I2C.h"
#include "Delay.h"

void main(void)
{
    WTST  = 0 ;
    EAXFR = 1 ;    // EAXSFR(); 伪装成函数,实际是  EAXFR = 1 ;
    CKCON = 0 ;
                P_SW2 |= 0x80 ;                        //使用IIC必须使能访问XFR
    I2C_Set ();

    while(1) {
                       
                        OpenDoor ( 0x03, 0x70 );
      Delay_ms( 1000 );
                       
    }
}


这是I2C.c 文件
#include "STC32G.h"
#include "I2C.h"

//----------------------------
//设置I2C针脚
//----------------------------
void I2C_Set (void)
{
                P_SW2 |= 0x80 ;                        //使用IIC必须使能访问XFR
                P_SW2 &= ~0x30;                        //把IIC针脚调置到 P14:SDA P15:SCL
    I2CCFG = 0xF5 ;
    I2CMSST = 0x00 ;

    P1M0 |= 0x30;
    P1M1 |= 0x30;   //这里只定义了 P14和P15 用于I2C 开漏模式。
}


//----------------------------
//等待I2C空闲
//----------------------------
void I2C_Wait(void)
{
    while (!(I2CMSST & 0x40 ));

    I2CMSST &= ~0x40 ;
}

//----------------------------
//开始命令
//----------------------------
void I2C_Start(void)
{
    I2CMSCR = 0x01;
    I2C_Wait();
}


//----------------------------
//发送数据
//----------------------------
void I2C_SendData( unsigned char dat )
{
    I2CTXD = dat ;
    I2CMSCR = 0x02;
    I2C_Wait();
}


//----------------------------
//读ACK
//----------------------------
void I2C_RecvACK( void )
{
    I2CMSCR = 0x03;
    I2C_Wait();
}

/*
//----------------------------
//接收数据
//----------------------------
        unsigned char I2C_RecvData ( void ){
                        I2CMSCR = 0x04;
                        I2C_Wait();
                        return I2CRXD ;
                }
*/

/*
//----------------------------
//发送ACK
//----------------------------
                void I2C_SendACK ( void ){
                                I2CMSST &= ~0x00 ;
                                I2CMSCR = 0x05;
                                I2C_Wait();
                }
*/

/*
//----------------------------
//发送NAK
//----------------------------
                void I2C_SendNAK ( void ){
                                I2CMSST &= ~0x01 ;
                                I2CMSCR = 0x05;
                                I2C_Wait();

                }
*/

//----------------------------
//发送Stop
//----------------------------
void I2C_Stop (void )
{
    I2CMSCR = 0x06;
    I2C_Wait();
}


//----------------------------
//I2C主机准备向从设备 写 数据,寻找从设备地址并请求从设备的ACK。(参数是从设备地址)
//----------------------------
void I2C_Start_Add_Write_ACK( unsigned char add )
{
    I2C_Start();
    I2C_SendData( add << 1 );
    I2C_RecvACK() ;
}

//----------------------------
//I2C主机向从设备写数据,并请求从设备的ACK。
//----------------------------
void I2C_SendData_ACK( unsigned char dat )
{
    I2C_SendData( dat );
    I2C_RecvACK( ) ;
}


/*
//----------------------------
//I2C主机准备向从设备 读 数据,寻找从设备地址并请求从设备的ACK. (参数是从设备地址 + 1 )
//----------------------------
                void I2C_Start_Add_Read_ACK( unsigned char add2 ){
                        I2C_Start();
                        I2C_SendData((unsigned char)(((unsigned int)add2<<1) || 0x01 ));   //为了不Warning 所以先转为unsigned int 再转为unsigned char。
                        I2C_RecvACK() ;
                }
*/



//向arduino副板发送I2C开门信号
void OpenDoor ( unsigned char add, unsigned char dat )
{
    I2C_Start_Add_Write_ACK( add )        ;        //I2C寻找从设备(设置为03)
    I2C_SendData_ACK( dat );                                        //I2C向从设置发送数据(0x70)
    I2C_Stop ();                                                                                        //I2C向从设置发送结束
}



#ifndef _I2C_H_
#define _I2C_H_


//----------------------------
//设置I2C针脚
//----------------------------
extern void I2C_Set (void);                        //设置I2C针脚

extern void I2C_Wait(void);                        //等待I2C空闲

extern void I2C_Start(void);                //开始命令

extern void I2C_SendData( unsigned char dat );                //发送数据

extern void I2C_RecvACK( void ) ;                                //读ACK

extern unsigned char I2C_RecvData ( void ) ;        //接收数据

//extern void I2C_SendACK ( void ) ; //发送ACK

//extern void I2C_SendNAK ( void ) ; //发送NAK

extern void I2C_Stop (void ) ; //发送Stop

extern void I2C_Start_Add_Write_ACK ( unsigned char add ) ; //I2C主机准备向从设备写数据,寻找从设备地址并请求从设备的ACK.(参数是从设备地址)

extern void I2C_SendData_ACK( unsigned char dat ) ; //I2C主机向从设备写数据,并请求从设备的ACK。

//extern void I2C_Start_Add_Read_ACK( unsigned char add ); //I2C主机准备向从设备读数据,寻找从设备地址并请求从设备的ACK.(参数是从设备地址)

extern void OpenDoor ( unsigned char add, unsigned char dat ) ;  //向arduino副板发送I2C开门信号( 0x03 , 0x70 )。



#endif
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:544
  • 最近打卡:2025-10-31 09:14:02
已绑定手机

48

主题

2300

回帖

8120

积分

论坛元老

积分
8120
发表于 4 天前 | 显示全部楼层
因为I2C的寄存器是扩展寄存器(地址不止一个字节的寄存器)
截图202510300912181495.jpg

所以访问前需要开启扩展寄存器访问使能
截图202510300913462893.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:602
  • 最近打卡:2025-11-02 20:35:20
已绑定手机

87

主题

6421

回帖

1万

积分

超级版主

积分
12104
发表于 4 天前 | 显示全部楼层
初始化先打开EAXFR,请阅读新手必读:
https://www.stcaimcu.com/thread-16535-1-1.html
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-11-3 02:57 , Processed in 0.123661 second(s), 73 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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