STM32
直播中

陈伟

7年用户 1487经验值
私信 关注
[问答]

求助,请大师帮忙看看这I2C读写PCF8563怎么不对?这是stms单片机在stvd环境下进行编程?

  请大师帮忙看看这I2C读写PCF8563怎么不对?这是stms单片机在stvd环境下进行编程?
_Bool I2C_SDA  @PC_ODR:1;//SDA管脚定义定义
_Bool I2C_SDAM @PC_IDR:1;//SDA管脚定义定义
_Bool I2C_SCL  @PC_ODR:2;//SCL管脚定义
#define SET_SCL_OUT()    {PC_DDR|=0X04; PE_CR1 |= 0X04;}
#define SET_SDA_OUT()    {PC_DDR|=0X02; PE_CR1 |= 0X02;}
#define SET_SDA_IN()     {PC_DDR =0XFD; PE_CR1 |= 0X02;}
//US带参数延时函数
void delayus(unsigned int us)
{
while(us--);//for(;;){;}//
}
void Delay_5us(void)
{
  unsigned int i;
for(i=10;i>0;i--);
}
/* void Delay_5us(void)
{
   uchar i;                   //fcpu 8MHz 时
   for (i=30; i>0; i--);
}*/
//ms延时函数
void delay_ms(unsigned int ms)
{
unsigned int i,j;
  for(i=ms;i>0;i--)
for(j=880;j>0;j--);
}
//串口定义
/*void USAT_k(voiv)
{
UART2_DDR1=0x08;
UART2_DDR2=0x09;
UART2_DDR3=0xaa;
}*/
//I2C初始化
void I2C_Init(void)
{
//        PC_DDR|=0x06;//0000 0110
//  PC_IDR|=0X06;//0000 0110
  SET_SDA_OUT();
SET_SCL_OUT();
I2C_SCL=HIGH;
//        I2C_SDA=HIGH;//SDA高电平
Delay_5us();//delay();//delayus(4);//延时2us
I2C_SDA=HIGH;//SDA高电平
//        I2C_SCL=HIGH;//SCL高电平
Delay_5us();//delay();//delayus(4);//延时2us
}
//--------------------------------------------------------------
// Prototype      : void I2C_Start(void)
// Calls          : Delay_5us()
// Description    : Start Singnal
//--------------------------------------------------------------
void I2C_Start(void)
{
    // SDA 1->0 while SCL High
SET_SDA_OUT();
SET_SCL_OUT();
I2C_SDA=HIGH;
  Delay_5us();
I2C_SCL=HIGH;
Delay_5us();
I2C_SDA=LOW;
Delay_5us();
}


//--------------------------------------------------------------
// Prototype      : void I2C_Stop(void)
// Calls          : Delay_5us()
// Description    : Stop Singnal
//--------------------------------------------------------------
void I2C_Stop(void)
{
    // SDA 0->1 while SCL High
SET_SDA_OUT();
SET_SCL_OUT();
  I2C_SCL=LOW;         
I2C_SDA=LOW;/*STOP:when CLK is high DATA change form low to high*/         
  Delay_5us();
  I2C_SCL=HIGH;        
//        Delay_5us();
I2C_SDA=HIGH;        
  Delay_5us();
}

//--------------------------------------------------------------
// Prototype      : void I2C_SendACK(uchar ack);
// Calls          : Delay_5us()
// Parameters     : bit ack:1-noack, 0-ack
// Description    : Master device send ACK to slave device.
//--------------------------------------------------------------
void I2C_SendACK(uchar ack)
{
uchar i=0;
SET_SCL_OUT();
I2C_SCL=HIGH;
Delay_5us();
SET_SDA_IN();
while((I2C_SDAM==1)  (i<255))
  i++;
I2C_SCL=LOW;
Delay_5us();
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uchar IIC_Wait_Ack(void)
{
uchar ucErrTime=0;
I2C_SDA=HIGH;Delay_5us();
I2C_SCL=HIGH;Delay_5us();
SET_SDA_IN();
while(I2C_SDAM)
{
  ucErrTime++;
if(ucErrTime>250)
{
  I2C_Stop();
return 1;
}
}
I2C_SCL=LOW;
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
I2C_SCL=LOW;
SET_SDA_OUT();
I2C_SDA=LOW;
Delay_5us();
I2C_SCL=HIGH;
Delay_5us();
I2C_SCL=LOW;
}
//不产生ACK应答              
void IIC_NAck(void)
{
I2C_SCL=LOW;
SET_SDA_OUT();
I2C_SDA=HIGH;
Delay_5us();
I2C_SCL=HIGH;
Delay_5us();
I2C_SCL=LOW;
}        

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(unsigned char txd)
{
unsigned char t;
SET_SDA_OUT();
I2C_SCL=LOW;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
  I2C_SDA=(txd 0x80)>>7;
txd<<1;
Delay_5us();
I2C_SCL=HIGH;
Delay_5us();
I2C_SCL=LOW;
Delay_5us();
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
unsigned char IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
  SET_SDA_IN();//SDA设置为输入
for(i=0;i<8;i++)
  {
   I2C_SCL=LOW;
Delay_5us();
I2C_SCL=HIGH;
receive<<=1;
if(I2C_SDAM)receive++;
Delay_5us();
  }
if(!ack)
  IIC_NAck();//发送NACK
else
IIC_Ack();//发送ACK
return receive;
}
//PCF8563写函数
//address:地址
//dat:参数
void write_Data(unsigned char address,unsigned char dat)
{
I2C_Start();
IIC_Send_Byte(0xa2);
IIC_Wait_Ack();
IIC_Send_Byte(address);//发送地址        
IIC_Wait_Ack();
IIC_Send_Byte(dat);//发送字节
IIC_Wait_Ack();
I2C_Stop();//产生一个停止条件  
}
//PCF8563读函数
//有返回值
//带入参数
unsigned char receive_Data(unsigned char regadd)
{
unsigned char temp=0;
I2C_Start();
IIC_Send_Byte(0xa2);//发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(regadd);
IIC_Wait_Ack();
I2C_Start();
IIC_Send_Byte(0xa3);//进入接收模式         
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
I2C_Stop();//产生一个停止条件
return temp;
}


回帖(1)

陈存楼

2024-5-14 18:13:58
I2C通信是一种常见的串行通信协议,用于在微控制器和其他设备之间传输数据。在STM32单片机中,I2C通信通常通过硬件I2C接口实现。在您提供的代码中,您似乎正在尝试使用GPIO引脚手动实现I2C通信。虽然这是可能的,但通常不推荐这样做,因为硬件I2C接口可以提供更高的可靠性和性能。

然而,如果您仍然希望使用GPIO引脚实现I2C通信,以下是一些建议和可能的问题:

1. 确保您的GPIO引脚配置正确。在您的代码中,您已经定义了SDA和SCL引脚,但是您需要确保它们被正确地配置为开漏输出(open-drain output)或准双向(quasi-bidirectional)模式。这可以通过设置GPIO引脚的输出类型和速度来实现。

2. 在您的代码中,您使用了宏定义来设置SCL和SDA引脚的输出。请确保这些宏定义正确地设置了GPIO寄存器。例如,`SET_SCL_OUT()` 和 `SET_SDA_OUT()` 宏定义应该正确地设置PC_DDR和PE_CR1寄存器。

3. 在I2C通信中,SCL和SDA引脚需要在高电平(高)和低电平(低)之间切换。在您的代码中,您需要实现这些切换逻辑。通常,这可以通过设置GPIO引脚的输出电平来实现。例如,要将SDA设置为高电平,您可以使用类似`I2C_SDA = 1;`的语句。

4. 在I2C通信中,主设备(通常是微控制器)负责生成时钟信号(SCL),而从设备(如PCF8563)则在SCL的上升沿读取或写入数据。因此,您需要在代码中实现时钟信号的生成和数据的读取/写入。

5. 在您的代码中,您提到了一个延时函数`delayus`。在I2C通信中,确保时序正确非常重要。请确保您的延时函数能够提供足够的时间,以便在SCL和SDA引脚之间切换。

6. 最后,确保您的STM32单片机和PCF8563之间的连接正确。这包括确保SDA和SCL引脚正确连接,以及确保它们之间存在适当的上拉电阻。

总之,虽然使用GPIO引脚实现I2C通信是可能的,但这通常比使用硬件I2C接口更复杂且容易出错。如果您的STM32单片机具有硬件I2C接口,建议使用它来实现I2C通信。这将使您的代码更简洁、更可靠,并且更容易调试。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分