项目中需要使用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;
}
完全没有道理会这样子呀,试了无数次都不行。准备换模拟了!
还是不想死心。
请高手 批点在下
|