打印
[STM32F1]

STM32 I2C奇怪的问题,请高手指导

[复制链接]
1167|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
项目中需要使用I2C与时钟芯片通讯,原来使用了库函数来做的,由于某种原因,需要改成寄存器来做,我就按库函数的代码,一条一条改成 寄存器 方式,结果,至最后一条诗句时,出现了非常奇怪的问题。将代码写下来,大师给讨论一下:芯片是 STM32F107VCT 时钟芯片是:DS3231M
多字节读操作,时种芯片上的时序时:
定义以了下内容
#define START   I2C1->CR1 |= 0x0100
#define STOP    I2C1->CR1 |= 0x0200
#define ACK_EN  I2C1->CR1 |= 0x0400
#define ACK_NO  I2C1->CR1 &=~0x0400
#define WT_EV5   while(((I2C1->SR1|(I2C1->SR2<<16))&0x00030001)!=0x00030001)
#define WT_EV6   while(((I2C1->SR1|(I2C1->SR2<<16))&0x00070082)!=0x00070082)       
#define WT_EV62  while(((I2C1->SR1|(I2C1->SR2<<16))&0x00030002)!=0x00030002)
#define WT_EV7   while(((I2C1->SR1|(I2C1->SR2<<16))&0x00030040)!=0x00030040)
#define WT_EV8   while(((I2C1->SR1|(I2C1->SR2<<16))&0x00070084)!=0x00070084)//实际是 EV8_2
#define WT_BUSY  while((I2C1->SR2 & 0x0002)>0)


改后的多字节读是这样子的

void DS3231_BytesRead(u8* pBuffer, u8 ReadAddr,u8 length)
{
  u8 pda;
    ACK_EN;                
  printf("ACK_EN \r\n");       
    STOP;
  printf("WT_BUSY:%.4X \r\n",I2C1->SR2);
    WT_BUSY;
  printf("WT_BUSY OK \r\n");
        START;
  printf("START \r\n");
        WT_EV5;
  printf("EV5 OK \r\n");
    I2C1->DR = DS3231_ADDRESS;
        WT_EV6;
  printf("EV6 OK \r\n");
    I2C1->DR =ReadAddr;
        WT_EV8;
  printf("EV8 OK \r\n");
    START;
  printf("START \r\n");
        WT_EV5;
  printf("EV5 OK \r\n");
    I2C1->DR = DS3231_ADDRESS|0x01;
        WT_EV62;
  printf("EV62 OK \r\n");
       
        while(length)
        {
                                if(length==1)
                                {
                                        ACK_NO;
                                printf("ACK_NO \r\n");
                                }
                  WT_EV7;
                  *(pBuffer++) = I2C1->DR;//         I2C_ReceiveData(I2C1);//
         length--;
        }
STOP;

}


只要这么改了,程序就运行不了了,在第  WT_BUSY; 时 死机了,发现  跳不出 忙来。
但如果 将 蓝色的字 *(pBuffer++) = I2C1->DR; 修改成 使用库函数
*(pBuffer++) =I2C_ReceiveData(I2C1);//
那就可以跳出   WT_BUSY; 来了,
这里非常奇怪,因为 蓝色字或是 红色字 根本在程序里面没有运行。
而且 I2C_ReceiveData()  也只是调用了返回函数,根本 没有其它的,如下述
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
{
  /* Check the parameters */
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  /* Return the data in the DR register */
  return (uint8_t)I2Cx->DR;
}

完全没有道理会这样子呀,试了无数次都不行。准备换模拟了!
还是不想死心。
请高手 批点在下


沙发
wowow| | 2015-3-5 13:33 | 只看该作者
*(pBuffer++) = I2C1->DR;//   
这句前加断点跑看正不正常,如果正常,加几个nop在前面试试。

使用特权

评论回复
板凳
小浣熊| | 2015-3-5 20:31 | 只看该作者
时钟芯片的时序没有问题吗

使用特权

评论回复
地板
lujin49|  楼主 | 2015-3-6 07:40 | 只看该作者
小浣熊 发表于 2015-3-5 20:31
时钟芯片的时序没有问题吗

一旦 不死机 过去了,再不会出现 死机的情况 时序应该没有问题

使用特权

评论回复
5
小浣熊| | 2015-3-7 00:00 | 只看该作者
lujin49 发表于 2015-3-6 07:40
一旦 不死机 过去了,再不会出现 死机的情况 时序应该没有问题

哦哦

使用特权

评论回复
6
zbchengfei| | 2015-3-11 14:21 | 只看该作者
本帖最后由 zbchengfei 于 2015-3-11 14:38 编辑

(pBuffer++) = &(I2C1->DR);

使用特权

评论回复
7
cool_coder| | 2015-3-11 16:39 | 只看该作者
F10x 的 I2C 操作对时序要求很严格吧? 你的这段程序在执行过程中会被中断打断吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

4

帖子

0

粉丝