在单片机开发中,假如时序联系不正确认的话,数据就不能正确的读写。因而,在程序中,怎么正确的操控时序联系,就显得特别的重要。
先来看以下的两个比如:
1.DS1302时钟芯片,选用SPI总线;
2.24C08存储芯片,选用I2C总线。
在对DS1302进行编程时,发现数码管只显现时刻的奇数值,而偶数值则不显现。
查看了下程序,问题定位在读出数据与写入数据的函数,原函数详细如下:
uchar ReadDs1302()
{
uchar dat,i;
SCLK=1;
Delayus(2);
for(i=0;i<8;i++)
{
dat>>=1;
if(DATA==1)
{
dat|=0x80;
}
SCLK=1;
Delayus(2);
SCLK=0;
Delayus(2);
}
return da;
}
将上面赤色字体的那行程序删去,或许改为:SCLK=0,再从头烧写后,数码管显现的时刻正常。
而写入数据的函数如下:
void WriteDs1302(uchar dat)
{
uchar i;
SCLK=0;
Delayus(2);
for(i=0;i<8;i++)
{
DATA=dat&0x01;
Delayus(2);
SCLK=1;
Delayus(2);
SCLK=0;
dat>>=1;
Delayus(2);
}
}
若只将上面蓝色部分的程序改为:
if(i<7)
{
SCLK=0;
}
从头烧写进去后,数码管也能正确的显现。
以蓝色那行程序的修正,剖析其原因:
先看下SPI总线的读操作时序,其为下降沿采样,如下图所示:
从时序图中,可看出,关于写数据,是在时钟的上升沿,而读数据,则是在时钟的下降沿。
程序修正前,在往DS1302中写入第八位数据后,时钟信号就变为低电平。尔后,进入读阶段,在DS1302还没将数据送到SDA线上时,时钟就变为高电平,此刻对应的SDA上的数据,仍是为写入的数据1。
而程序修正后,即在SDA写入数据后,在第八位数据时,SCLK就不降为低电平了,一向坚持为高电平,直到DS1302将数据送到SDA时,才变为低电平,在下降沿时对SDA上的数据进行采样。
即修正后的程序,在读写操作替换那个时钟,比及DS1302送数据到SDA线上后,才变为低电平,进行采样的。
关于24C08,其选用I2C总线技能,当程序烧写进入后,发现不能正常的作业。
问题定位在I2C完毕信号函数,详细如下所示:
void Stop()
{
SCL=1;
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
上面赤色两行程序的次序对调下,则能正确的读写24C08芯片内部的数据。
剖析其原因,则在于若履行Stop()这个函数之前时,若SDA上存在几个周期的高电平时,此刻履行SCL=1;SDA=0,相当于多出了个I2C的开端信号,导致过错。
在实践中,总结了下今后几点,期望能够尽量防止时序操作过错:
1. 特别注意单字节读,写函数刚开端或完毕时,时钟信号的凹凸电平;
2. 可确认1或许0为程序的默许电平。如关于DS1302的CLK,能够低电平;
3. 从节约功耗的视点动身,尽量确保默许电平功耗低。以I2C总线为例,因其有上拉电阻 的存在,故可确保默许电平为高;
4. 相同从功耗的视点动身,尽量确保各类信号少翻转;
5. 关于总线操控信号(如SPI总线的RST),全部信号都准备好之后,操控信号才敞开。当总线要停止作业时,先将操控信号关断,再作其他信号的处理;
6. 当然,得时刻警觉信号的树立时刻与坚持时刻。
当然,若在程序中查找不出问题时,可选用示波器,一起丈量时钟与数据信号,判别时序是否正确。