_奶咖君_ 发表于 2024-12-23 16:48:20

KNW123 发表于 2024-12-23 16:46
一定要加外部上拉吗?我感觉好多我都是用内部上拉程序也没问题的啊
理论上只要有上拉就行,用内部还是外部 就看外部电路是什么样的了,


要是还是不行的话,,,上示波器看看怎么回事吧

KNW123 发表于 2024-12-23 16:54:25

_奶咖君_ 发表于 2024-12-23 16:32
再者根据你说 准双向模式下,可以使用,,

开漏模式下不行,且要使用内部上拉电阻的操作,我是不是可以猜 ...

#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   P0M1    =   0x93;
sfr   P0M0    =   0x94;
sfr   P1M1    =   0x91;
sfr   P1M0    =   0x92;
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;

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 Delay()
{
    int i;

    for (i=0; i<3000; i++)
    {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    }
}

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 = 0xe0;                              //使能I2C主机模式
    I2CMSST = 0x00;

    Start();                                    //发送起始命令
    SendData(0xa2);                           //发送设备地址+写命令
    RecvACK();
    SendData(0x02);                           //发送存储地址
    RecvACK();
    SendData(0x00);                           //设置秒值
    RecvACK();
    SendData(0x00);                           //设置分钟值
    RecvACK();
    SendData(0x12);                           //设置小时值
    RecvACK();
    Stop();                                     //发送停止命令

    while (1)
    {
      Start();                              //发送起始命令
      SendData(0xa2);                         //发送设备地址+写命令
      RecvACK();
      SendData(0x02);                         //发送存储地址
      RecvACK();
      Start();                              //发送起始命令
      SendData(0xa3);                         //发送设备地址+读命令
      RecvACK();
      P0 = RecvData();                        //读取秒值
      SendACK();
      P2 = RecvData();                        //读取分钟值
      SendACK();
      P3 = RecvData();                        //读取小时值
      SendNAK();
      Stop();                                 //发送停止命令

      Delay();
    }
}


这个SDA被设置成双向IO,SCL被 设置成开漏

DebugLab 发表于 2024-12-23 16:56:04

KNW123 发表于 2024-12-23 16:46
是P14和P15啊

你改一下
内部4K上拉完全可以的

KNW123 发表于 2024-12-23 17:15:11

DebugLab 发表于 2024-12-23 16:56
你改一下
内部4K上拉完全可以的

void Wait()
{
    while (!(I2CMSST & 0x40));
    I2CMSST &= ~0x40;
}

现在卡在while() 这

DebugLab 发表于 2024-12-23 17:35:42

KNW123 发表于 2024-12-23 17:15
void Wait()
{
    while (!(I2CMSST & 0x40));


void I2C_Isr(void) interrupt 24
{
      _push_(P_SW2);
      P_SW2|=EAXFR;
      if(I2CMSST&MSIF)
      {
                I2CMSST&=~MSIF;
                I2C_Busy=0;
      }
      _pop_(P_SW2);
}

DebugLab 发表于 2024-12-23 17:37:53

KNW123 发表于 2024-12-23 17:15
void Wait()
{
    while (!(I2CMSST & 0x40));


这应该在中断里的
你抄一下我的程序好吗
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=13173&pid=133651

KNW123 发表于 2024-12-23 17:45:06

DebugLab 发表于 2024-12-23 17:37
这应该在中断里的
你抄一下我的程序好吗
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpos ...

STC的例程就是这样的啊,我准备加上拉电阻试下

DebugLab 发表于 2024-12-23 18:13:02

KNW123 发表于 2024-12-23 17:45
STC的例程就是这样的啊,我准备加上拉电阻试下

用中断还是查询
如果用中断,必须有中断函数,否则跑飞
如果用查询,不能开I2C中断

men007 发表于 2024-12-23 18:13:17

搞定了吗?学习一下{:4_245:}

KNW123 发表于 2024-12-23 20:02:25

men007 发表于 2024-12-23 18:13
搞定了吗?学习一下

没啊,你也有这个疑问?准备加两个外部上拉电阻
页: 1 [2] 3
查看完整版本: I2C卡死在发送起始信号