找回密码
 立即注册
查看: 285|回复: 25

第1篇_8H1K17 I2C从机如何/何时发送ACK/NACK

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 16:46:53 | 显示全部楼层 |阅读模式
我的8H1K17 I2C作为从机,如果主机要读寄存器,是直接将数据赋值给I2CTXD,它就会自动启动发送数据给主机,是吗?还是说要做其他设置
STC8H1K17-I2C.png
花有重开日,人无再少年
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2025-05-02 08:32:59

717

主题

1万

回帖

1万

积分

管理员

积分
15617
发表于 2025-3-18 21:10:25 | 显示全部楼层
1, I/O 设置成开漏,外部加10K 上拉电阻,或提前打开内部上拉电阻
2,这有现成的参考程序
截图202503182110044082.jpg

#include "reg51.h"
#include "intrins.h"

sfr     P_SW2   =   0xba;

#define I2CCFG      (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR     (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST     (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR     (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST     (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR    (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD      (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD      (*(unsigned char volatile xdata *)0xfe87)

sfr     P1M1    =   0x91;
sfr     P1M0    =   0x92;
sfr     P0M1    =   0x93;
sfr     P0M0    =   0x94;
sfr     P2M1    =   0x95;
sfr     P2M0    =   0x96;
sfr     P3M1    =   0xb1;
sfr     P3M0    =   0xb2;
sfr     P4M1    =   0xb3;
sfr     P4M0    =   0xb4;
sfr     P5M1    =   0xc9;
sfr     P5M0    =   0xca;

sbit    SDA     =   P1^4;
sbit    SCL     =   P1^5;

bit isda;                                       //设备地址标志
bit isma;                                       //存储地址标志
unsigned char addr;
unsigned char pdata buffer[256];

void I2C_Isr() interrupt 24
{
    _push_(P_SW2);
    P_SW2 |= 0x80;

    if (I2CSLST & 0x40)
    {
        I2CSLST &= ~0x40;                       //处理START事件
    }
    else if (I2CSLST & 0x20)
    {
        I2CSLST &= ~0x20;                       //处理RECV事件
        if (isda)
        {
            isda = 0;                           //处理RECV事件(RECV DEVICE ADDR)
        }
        else if (isma)
        {
            isma = 0;                           //处理RECV事件(RECV MEMORY ADDR)
            addr = I2CRXD;
            I2CTXD = buffer[addr];
        }
        else
        {
            buffer[addr++] = I2CRXD;            //处理RECV事件(RECV DATA)
        }
    }
    else if (I2CSLST & 0x10)
    {
        I2CSLST &= ~0x10;                       //处理SEND事件
        if (I2CSLST & 0x02)
        {
            I2CTXD = 0xff;                      //接收到NAK则停止读取数据
        }
        else
        {
            I2CTXD = buffer[++addr];            //接收到ACK则继续读取数据
        }
    }
    else if (I2CSLST & 0x08)
    {
        I2CSLST &= ~0x08;                       //处理STOP事件
        isda = 1;
        isma = 1;
    }

    _pop_(P_SW2);
}

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    P_SW2 = 0x80;

    I2CCFG = 0x81;                              //使能I2C从机模式
    I2CSLADR = 0x5a;                            //设置从机设备地址寄存器I2CSLADR=0101_1010B
                                                //即I2CSLADR[7:1]=010_1101B,MA=0B。
                                                //由于MA为0,主机发送的的设备地址必须与
                                                //I2CSLADR[7:1]相同才能访问此I2C从机设备。
                                                //主机若需要写数据则要发送5AH(0101_1010B)
                                                //主机若需要读数据则要发送5BH(0101_1011B)
    I2CSLST = 0x00;
    I2CSLCR = 0x78;                             //使能从机模式中断
    EA = 1;

    isda = 1;                                   //用户变量初始化
    isma = 1;
    addr = 0;
    I2CTXD = buffer[addr];

    while (1);
}


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-3-18 17:30:19 | 显示全部楼层
从机是把数据放到寄存器然后等主机来读,通信需要时钟,从机又不能主动发时钟
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 17:42:44 | 显示全部楼层
Debu*** 发表于 2025-3-18 17:30
从机是把数据放到寄存器然后等主机来读,通信需要时钟,从机又不能主动发时钟 ...

我设置的是主机先发送设备地址,再发送寄存器地址,然后读取I2CTXD的值,那主机要怎么读I2CTXD?STC8H将值赋值给I2CTXD,它什么时候会把逻辑值推送到SDA引脚?收到起始信号,就把I2CTXD的逻辑值推送到SDA引脚吗?
花有重开日,人无再少年
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 17:45:55 | 显示全部楼层
主机发送完设备地址,寄存器地址,之后再发送起始信号,然后呢?从机通过什么方式把数据放到SDA引脚上?
I2C_Read_Byte.png

点评

只有这一张截图吗?操作SCL是主机代码啊,你的从机代码呢? “等我再发寄存器地址(此时主机在发SCL)时,从机就会和主机抢SDA线的控制权” 这句话又是什么意思呢,从机发什么寄存器地址,从机直接发数据么,主机此  详情 回复 发表于 2025-3-18 19:41
花有重开日,人无再少年
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2940

积分

荣誉版主

无情的代码机器

积分
2940
发表于 2025-3-18 17:56:21 | 显示全部楼层
参考手册例程:
截图202503181756004032.jpg
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 18:05:48 | 显示全部楼层
erci*** 发表于 2025-3-18 17:56
参考手册例程:

我发的图就是手册的这一部分
花有重开日,人无再少年
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2940

积分

荣誉版主

无情的代码机器

积分
2940
发表于 2025-3-18 18:11:59 | 显示全部楼层
图里不是收到主机事件,将数据放到寄存器了嘛,放了SDA引脚应该就有反应了。
截图202503181808381033.jpg

你是想问怎么绑定SDA引脚?
截图202503181810487464.jpg
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 18:13:58 | 显示全部楼层
按照一楼的说法,看来STC8H1K17不支持寄存器读取的操作,因为你一发读写操作,就要给I2CTXD赋值,此时我主机还没把寄存器地址发送过去呢,但即使是这种情况,仍然可以实现我的目的,我只需要将MA设置为1,设置从机接受所有设备地址,然后把我的不同的寄存器地址统统设置为不同的设备地址,这样只要我一读设备地址,从机就给我发数据
花有重开日,人无再少年
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 18:16:23 | 显示全部楼层
erci*** 发表于 2025-3-18 18:11
图里不是收到主机事件,将数据放到寄存器了嘛,放了SDA引脚应该就有反应了。

I2C中读数据分三步,第一步发送设备地址,第二步发送寄存器地址,第三步发送时钟信号,此时主机去读SDA线上的电平。我想问的就是第三步,我要怎么操作STC单片机(从机),它会在第三步把逻辑电平推送到SDA引脚
花有重开日,人无再少年
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-05-02 08:06:31
已绑定手机

12

主题

29

回帖

320

积分

中级会员

积分
320
发表于 2025-3-18 18:21:01 | 显示全部楼层
按照你数据手册从机中断的代码例程,当我发送完设备地址后(读寄存器),此时给I2CTXD赋值,等我再发寄存器地址(此时主机在发SCL)时,从机就会和主机抢SDA线的控制权

点评

赋值完这个时候按我理解SDA线控制权应该在从机,从机回数据用呀。你上传下你测试用的主从机代码和电路图么  详情 回复 发表于 2025-3-18 18:47
花有重开日,人无再少年
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 08:49 , Processed in 0.151810 second(s), 115 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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