细数,从买下模块到现在,已经过了一个月有多。但中间的辛酸苦楚远比这时间难熬。但总结下来,只有这么一句话:
今天对细节的置之不理,造就明天的抓耳挠腮。
若想看我如何犯下一个个不可饶恕的错误,请听我慢慢道来。
先说明一下自己的情况:工作电压为5V的STC89C52RC LED模块 自己的想法是把模块的收发信息或工作状态反映在LED上
起初自己一边看模块说明书,一边尝试去写代码。
if(DR) LED=0x55;
但后来辛辛苦苦把12根模块上的管脚通过杜邦线连到单片机上是,发现LED并没有亮,无论是发送端还是接收端。我能在这好一段时间,一直怀疑是电路的问题,如 STC89C52到底属不属于51系列单片机(因为如果是别的单片机,管脚输出电流会烧坏模块,说明书有提),是否需要在模块上加几个电阻等。闷了几天,当时还正以为模块被烧坏,想着寄回厂家检修(在淘宝买,回寄不便)。
我还真天真地去中工再买了两个质量好的模块回来试。当然,结果同上。这时才逼出一个想法,SPI写Config进去,再读出来,将任何一个字节反映在LED模块上,试试模块能否工作。
void SpiWrite(uchar send){
uchar j;
DATA_BUF=send;
for(j=0;j<8;j++){
SCK=1;
if((DATA_BUF&0x80)!=0){
MOSI=1;
}else{
MOSI=0;
}
DATA_BUF<<=1;
SCK=0;
}
}
( 已知nRF905的SPI通信工作在模式0下)
SPI写入代码如上。实验发现,LED全灭,说明压根没写进去,或没读出来。这又让我纠结了好久。百度百科了一下,有了发现。
让我们来关注SCK的第一个时钟周期,根据SPI的通信原理知,在时钟的上升沿采样数据,时钟的下降沿输出数据(相对从机而言)。因此,按照上面的代码,在第一次循环中SCK=1时,MOSI为0,这样就造成了字节的错位。当然写不进去,更不要读出来了。
正确写法应该是把 SCK=1; 移至 SCK=0;上方。
SPI问题解决了,我以为收发也就顺理成章,轻松加愉快。但天真了。
SPI写入已经可以保证不会出错。因此,只要发送代码正确,根据说明书所说,数据准备管脚DR将置高。
void TxPacket(unsigned char *Txbuf)
{
uchar i;
//Config905();
CSN=0;
SpiWrite(WTP); // Write payload command
for (i=0;i<4;i++)
{
SpiWrite(Txbuf); // Write 4 bytes Tx data
}// Spi enable for write a spi command
CSN=1;
Delay(1); // Spi disable
CSN=0; // Spi enable for write a spi command
SpiWrite(WTA); // Write address command
for (i=0;i<4;i++) // Write 4 bytes address
{
SpiWrite(TxAddress);
}
CSN=1; // Spi disable
TRX_CE=1; // Set TRX_CE high,start Tx data transmission
Delay(5);
while (DR!=1) P0=0x55;
TRX_CE=0; // Set TRX_CE low
P0=0x0f;
}
理应来说,DR置高,然后程序顺利运行下去,跳过 while (DR!=1); ,但令人头痛的事,LED始终亮暗相间,P0=0x55.
这时我一直想是否是延时的长短有问题。不得不去看看原版DataSheet中的时序图。
其实我看这图时,有些疑问。DR 的时序变化图在那,如果要画的话,应该画哪。
TRX_CE=1; // Set TRX_CE high,start Tx data transmission
Delay(5);
while (DR!=1) P0=0x55;
TRX_CE=0;
如果真像代码所写,DR的置高应该是在T0于T1之间。但数据的发送却又是在T2开始,这让我不知该把while 语句放哪,并且还怀疑说明书上的代码有没有错。我把上述的语句排列组合了许多次,但总是老样子。
又因此烦恼了数个夜晚。后来想着为啥不是着把管脚于管脚间的线断开,用万用表测测分开的管脚的电平。经测试,发现单片机上的IO口管脚电平始终为低,而nRF905模块上的DR管脚却有着令人兴奋的 3.38V .这就找到路子了,一定是IO口的问题,但具体问题在哪,及如何解决还的再看看.
直到在 电子工程师论坛的Q群里,咨询了一些技术人员才得出了答案。问题出现在我的程序初始化。
void nRF905Init(void)
{
CSN=1; // Spi disable
SCK=0; // Spi clock line init low
DR=0; // Init DR for input
AM=0; // Init AM for input
CD=0; // Init CD for input
PWR=1; // nRF905 power on
TRX_CE=0; // Set nRF905 in standby mode
TXEN=0; // set radio in Rx mode
}
如上,我把DR设为了低电平,根据电路基础知识知道,高电平于低电平线与得 低电平,高电平只有与高电平线与才能得高电平。所以现在人们都是通过初始化设管脚为高来设置不需 设输入输出的IO口。由此看来,DR设为高便可。果然,发送成功。
当然,接受端的nRF905模块DR管脚也有3V以上。但接收端的单片机却识别不了。这就诡异了,几乎是相同的电路布置,理应都一样,除了P3口有一个未拆除的排阻。问题也正是在这排阻上。
不实践不会注意到 排阻上不光 1和2 有电阻,2,3,4,5,6,7,8,9 两两之间也有电阻,而且不小。这样一来,单片机识别错误也不足为怪了。
问题月月有,这次特别多。好的方法是,认真打好基础,明年好好学习电学的基础知识,对待好细节。
用户377235 2013-7-13 15:19
如何实现双工呢??