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 ; }

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
313668972
1楼-- · 2019-10-16 19:39
回复【4楼】qingtian305:
---------------------------------
楼主,您的代码是调试完成后的吗?我前一段也是用3231,调了好久也没搞定,51上运行好好的,一到ARM上就没反应了
qingtian305
2楼-- · 2019-10-16 20:43
 精彩回答 2  元偷偷看……
qingtian305
3楼-- · 2019-10-16 22:06
回复【6楼】jinfahua:
---------------------------------
好哇 好哇
alisa
4楼-- · 2019-10-17 01:51
回复【2楼】狼烟四起:
---------------------------------
我现在遇见和你一样的问题,也是只能读不能写,请问你是调了那里的延时?调大还是调小?谢谢
axing78
5楼-- · 2019-10-17 04:29
能给个程序的例子吗?
2557046847
6楼-- · 2019-10-17 05:19
同在调试DS32321

一周热门 更多>