_奶咖君_
发表于 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
搞定了吗?学习一下
没啊,你也有这个疑问?准备加两个外部上拉电阻