STM32 IO口模拟I2C控制DS3231 一直调不通

2019-10-15 19:13发布

 一直 无法接收到ACK信号  从设备一直无反应  我单独给SDA拉高 置低 IDR是有反应的  我买了5个DS3231的时钟模块 那个模块式5V供电 经过一个稳压二极管 变成3.3v给芯片供电的  SDA SCL 上拉电阻都是10K 附件里有 DS3231的驱动程序 和 模块的原理图 从昨天到今天 在网上下了3个修改后都不行 昨天晚上 自己又重写了一个 从设备的ACK 信号一直没有响应  所以对时钟模块的读写操作 都是无效的 后来感觉是时钟芯片拽不动STM32的IO口 所以 就换了下上拉电阻  1K 4.7K 10K都换过 还是不好使 群里有朋友说 实在不行 就换成STM32的外设I2C   小弟实在是晕菜了 之前搞24c系列的模拟I2C也没这么困难过  求大家 给小弟支支招 
附件里 有 程序和模块原理图
我主程序里是这样写的
 GPIOA->CRL&=0x00ffffff;
 GPIOA->CRL|=0x22000000;//0x22000000; //SCK SDA
 delay_ms(100);
   I2cByteWrite(0xD0,0x0e,0); 
   I2cByteWrite(0xD0,0x0f,0);
后面就是读 时分秒


//////////////驱动程序
#include <stm32f10x_lib.h>
#include "delay.h"
#include "DS3231new.h"  #define SCL_H  GPIOA->ODR|=1<<7
#define SCL_L  GPIOA->ODR&=~(1<<7) #define SDA_H  GPIOA->ODR|=(1<<6)
#define SDA_L  GPIOA->ODR&=~(1<<6) #define SDA   (GPIOA->IDR & 1<<6) extern u8 year,month,date,hour,minute,second;   u8 BCD2HEX(u8 val)   //BCD转换为Byte
{
    u8 i;
    i= val&0x0f;
    val >>= 4;
    val &= 0x0f;
    val *= 10;
    i += val;
   
    return i;
} u8 B_BCD(u8 val)//B码转换为BCD码
{
  u8 i,j,k;
  i=val/10;
  j=val%10;
  k=j+(i<<4);
  return k;
} void delay(u16 us)
{
   delay_us(us*7);
}
/************************START***************************/
void Start(void)
{
  SDA_H;
  delay(5);
  SCL_H;
  delay(5);
  SDA_L;
  delay(5);
}
/********************************************************/
/************************STOP****************************/
void Stop(void)
{
  SDA_L;
  delay(5);
  SCL_H;
  delay(5);
  SDA_H;
  delay(5);
}
/********************************************************/
/***********向I2C总线发送一个字节+接收一个ACK************/
void SendByte(u8 Dat)
{
  u8 i=0;
  u8 T_Data=0;
 
  setsda();//DDRD|=(1<<1);//输出
  SCL_L;
  delay(10);
  T_Data=Dat;
  for(i=0;i<8;i++)
    {          
 
          if(T_Data&0x80)
            SDA_H;
          else
            SDA_L;
          delay(5);
         SCL_L;
          delay(5);
          SCL_H;
          delay(5);
          T_Data=T_Data<<1;
          SCL_L;
          delay(5);
   }
  SDA_H;//释放总线
  delay(5);
  SCL_L;     /*********************/
  delay(5);//接收一个ACK,不做处理
  SCL_H;     /*********************/
  delay(5);   SCL_L;
}
/********************************************************/
/**********从I2C总线上读取一个字节+发送一个ACK***********/
u8 ReceiveByte(u8 b)
{
  u8 i;
  u8 temp;
  u8 Dat=0;
/*
  SDA_H;
  delay(5);
  SCL_L;
  delay(5);
*/
  clrsda();//DDRD&=~(1<<1);//输入
  for(i=0;i<8;i++)
    {
          SCL_H;
      delay(5);           Dat=Dat<<1;
          delay(5);
    if(SDA){temp=1;}
    else{temp=0;}
          if(temp)
            Dat|=0x01;
          else
            Dat|=0x00;
         delay(5);
         SCL_L;
          delay(5);
    }
  setsda();//DDRD|=(1<<1);//输出
 
  if(b)//每收一个数后发送ACK或nACK
    SDA_H;
  else
    SDA_L;
       
  delay(5);
  SCL_H;
  delay(5);
  SCL_L;
  delay(5);
  SDA_H;        //释放总线
  delay(100);
  return Dat;
}
/****************************************************/
/***********将一个字节写入DS3231指定的地址***********/
void I2cByteWrite(u8 device,u8 addr,u8 bytedata)
{
  Start();
  delay(5);
  SendByte(device);
  delay(5);
  SendByte(addr);
  delay(5);
  SendByte(bytedata);
  delay(5);
  Stop();
}
/****************************************************/
/************从DS3231指定的地址读一个字节************/
u8 I2cByteRead(u8 device,u8 addr)
{
  u8 Dat=0;
 
  Start();
  SendByte(device);
  delay(5);
  SendByte(addr);
  delay(5);
  Start();//Restart
  SendByte(0xd1);//读数
  delay(5);
  Dat=ReceiveByte(1);//只接收一个字节,所以发nACK
  Stop();
  return Dat;
}
/***************************************************/
/*********************读取时间**********************/
void Readtime(void)
{
  year=I2cByteRead(0xd0,0x06);  //年
  month=I2cByteRead(0xd0,0x05); //月
  date=I2cByteRead(0xd0,0x04);  //日
  hour=I2cByteRead(0xd0,0x02);  //时
  minute=I2cByteRead(0xd0,0x01);//分
  second=I2cByteRead(0xd0,0x00);//秒
}
/***************************************************/
/****************修改时间,BCD码输入*****************/
void ModifyTime(u8 yea,u8 mon,u8 da,u8 hou,u8 min,u8 sec)
{
  u8 temp=0;
 
  temp=B_BCD(yea);
  I2cByteWrite(0xD0,0x06,temp);//修改年
 
  temp=B_BCD(mon);
  I2cByteWrite(0xD0,0x05,temp);//修改月
  
  temp=B_BCD(da);
  I2cByteWrite(0xD0,0x04,temp);//修改日
 
  temp=B_BCD(hou);
  I2cByteWrite(0xD0,0x02,temp);//修改时
 
  temp=B_BCD(min);
  I2cByteWrite(0xD0,0x01,temp);//修改分
 
  temp=B_BCD(sec);
  I2cByteWrite(0xD0,0x00,temp);//修改秒
} /****************************************************/
/****************读取时间 计算 并显示****************/
void get_show_time(void)
{
//year,month,date,hour,minute,second; year=I2cByteRead(0xd0,0x06);  //年
year=BCD2HEX(year);
month=I2cByteRead(0xd0,0x05);  //月
month=BCD2HEX(month);
date=I2cByteRead(0xd0,0x04);  //日
date=BCD2HEX(date);
  hour=I2cByteRead(0xd0,0x02);  //时 24小时制
hour&=0x3f;                  
hour=BCD2HEX(hour);
minute=I2cByteRead(0xd0,0x01);  //分
minute=BCD2HEX(minute);
 
 
second=I2cByteRead(0xd0,0x00);  //秒
second=BCD2HEX(second);
} void setsda(void)
{
GPIOA->CRL&=0xf0ffffff;
GPIOA->CRL|=0x02000000;
}
void clrsda(void)
{
GPIOA->CRL&=0xf0ffffff;
GPIOA->CRL|=0x04000000 ; }

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。