标签:
ANT与MCU可以使用异步UART或同步SPI两种方式连接。异步通信与同步通信的各自特点这里不赘述,总之我们选择使用同步方式进行连接。
一、SPI简介
SPI(Serial Peripheral Interface),串行外设接口。是摩托罗拉公司开发的一种同步全双工通信协议。依靠收发两端的移位寄存器,以及主机master提供的时钟信号,双方可以实现较高速率的同步全双工传输。
标准的SPI是3/4根线,分别用于一主一从/多主从的情况。4根线分别是:
有些命名可能有区别,不过意思相同。
二、ANT中的SPI
SPI固然很强大,然而,由于协议中缺少流控,面对后来出现的各种各样的外设,他渐渐开始力不从心了。例如,在一些高速应用中,收发双发需要进行严格的握手确认机制,已保证可靠的数据传输,然而标准SPI协议中,通过仅有的几根数据线,master甚至无法知道slave的存在!再比如,万一MOSI线和MISO线短路到一起了,主机有可能仍然正常工作,而无法发觉从机已挂!这正是我们在调试单机SPI的时候那种做法。因此,现实的情况是,我们所见的很多的SPI设备,其实都并没有使用标准的SPI协议,而是纷纷开发了多种多样的SPI兼容的传输方式。ANT就是这样,甚至把全双工简化成了半双工。
在连接MCU与ANT时,可以使用硬件SPI接口。借助另外三根信号线SRDY,MRDY,EN,便可以完成与ANT模块的所有通信。当然,对于没有硬件SPI的低成本单片机,也可以使用软件模拟SPI来完成通信。
需要指出的是,虽然在功能上十分类似,但由于一些细小的差异,这里的SRDY不能使用SPI中的CS信号线来代替。所以说,我们使用SPI的3pin从模式就可以了。ANT模块作为SPI主机,MCU做SPI从机。(官方文档中说到EPSON有一个系列的单片机可以用硬件SPI的片选信号直接作SRDY,我猜测很可能就是那款单片机内置了ANT的这种SPI兼容协议)
我的Launchpad是MSP430G2553,恰好具有一个硬件SPI,所以接下来这里我们实现硬件SPI接口的连接。既然是同步通信,自然少不了时序。TIME IS MONEY!
nRF24AP2的SPI通信机制基本描述如下:
1.同步
ANT模块上电后,需要与MCU进行一次同步操作,才能正常开始SPI通信。同步可以通过两种方式完成,一种是拉一下ANT上面的RESET-Pin,简单可靠,但需要设计硬件按钮,或者占用一个MCU的接口。另一种就是通过MRDY和SRDY,EN三根线完成一个握手,纯软件实现,成本低廉。下面的图描述了完成一次SPI同步初始化握手的时序图,我们也可以认为这个过程是实现了一个同步序列Synchronous Sequence。
蓝色的箭头标明了数据的流向,下同。我简洁地表述下同步的整个过程:
a) 最初,MCU拉高MRDY,SRDY
b) 首先,MCU拉低SRDY
c) 间隔至少250us,然后MCU拉低MRDY
d) 若SEN为低,等待ANT拉高SEN
e) ANT拉高SEN后会再次拉低SEN,表示同步完成
f) MCU最后拉高SRDY,同步结束
2.MCU接收 (SYNC=0xA4)
通过此过程,ANT得以发送消息至MCU。须知,一个消息的完整传输,第一个字节也就是SYNC字节,总是由ANT发起。SYNC字节(的最低位)标明了后续字节的流向。
简洁描述如下:
a) ANT自动拉低SEN,提示MCU有消息给你
b) MCU发觉后,待自己准备好了,便发送一个SRDY的负脉冲告诉ANT,脉冲持续至少2.5us
c) ANT感知到负脉冲,随后将发送SCLK信号,一个字节的数据也从MOSI中随之而来
d) MCU再次准备好后,便可继续来一发SRDY负脉冲,进行后续字节的通信
3.MCU发送 (SYNC=0xA5)
当MCU有消息要发送给ANT模块的时候,进行这个操作。同样的,第一个SYNC字节仍是来自ANT。正确的SYNC,标明ANT已经准备好接收消息。
简洁描述如下:
a) MCU拉低MRDY,表示自己有消息要给ANT
b) ANT发觉后,拉低SEN回应
c) MCU得到回应,准备完毕便发送一个SRDY负脉冲,至少2.5us
d) ANT听到负脉冲,便发出SCLK信号,SYNC字节随之而来
e) 确认SYNC字节无误后,MCU再次给出一个SRDY负脉冲,表示自己随时可以发送数据
f)ANT听到负脉冲,便发出SCLK信号,指引MCU发送下一个字节的数据
e) MCU根据SCLK的节奏,随即发出下一个字节
g) 后续操作相同
三、基本程序设计
根据以上过程,可以归纳出大致的程序流程图。
接下来是CODE TIME!
1.先是同步的部分。
1 /////////////////////////////////////////////////////////////////////////////////// 2 //完成同步序列的发送 3 //返回值: IS_EN_ASSERTED() 4 BOOL ByteSyncSerial_SyncSequenceReset(void) 5 { 6 SYNC_SRDY_DEASSERT(); //先拉高SRDY,MRDY 7 SYNC_MRDY_DEASSERT(); 8 Timer_DelayTime(300); //等待ANT初始化,约1ms 9 10 //正式开始同步序列 11 SYNC_SRDY_ASSERT(); //先拉低SRDY 12 13 Timer_DelayTime(10); //等待10*30us=300us》250us 14 15 SYNC_MRDY_ASSERT(); //再拉低MRDY 16 17 Timer_DelayTime(1000); //等待ANT拉低EN响应 18 19 SYNC_SRDY_ASSERT(); //拉低SRDY 20 //同步结束 21 22 return IS_EN_ASSERTED(); //返回EN是否已拉低 23 }
2.然后是接收和发送消息的部分。
1 //////////////////////////////////////////////////////////////////////////////////// 2 //用于接收消息或发送消息,发送的消息用指针引自发送缓存pucTxMsgBuffer,接收的消息用指针保存至接收缓存pucRxMsgBuffer 3 //参数: pucTxMsgBuffer 4 // pucRxMsgBuffer 5 //返回值: bRxMessage 6 BOOL ByteSyncSerial_Transaction(UCHAR *pucTxMsgBuffer, UCHAR *pucRxMsgBuffer) 7 { 8 BOOL bRxMessage = FALSE; //成功接收消息标志 9 UCHAR ucCheckSum; 10 UCHAR ucMesgLen; 11 UCHAR ucIndex; 12 UCHAR ucByte; 13 14 if (pucTxMsgBuffer != NULL) //MCU有消息发给ANT 15 { 16 SYNC_MRDY_ASSERT(); //拉高MRDY通知ANT 17 18 { 19 UCHAR ucEnTimeout = EN_ASSERT_TIMEOUT; 20 21 do //循环等待ANT拉低EN来响应 22 { 23 if (!(ucEnTimeout--)) 24 { 25 ucEnTimeout = EN_ASSERT_TIMEOUT; 26 27 SYNC_MRDY_DEASSERT(); //重试拉低MRDY 28 TIMER_EN_DELAY(); 29 SYNC_MRDY_ASSERT(); 30 } 31 32 TIMER_EN_DELAY(); //等待10us 33 } 34 while (!IS_EN_ASSERTED()); //直到EN拉低 35 } 36 } 37 38 while (IS_MRDY_ASSERTED() || (IS_EN_ASSERTED() && (!bRxMessage))) //MCU有消息至ANT,或者ANT已响应即将有个消息要发过来且还没收到 39 { 40 while (!IS_EN_ASSERTED()); 41 42 ucByte = ReadByte(); //读取SYNC字节 43 ucCheckSum = ucByte; //初始化校验和 44 45 if (ucByte == MESG_RX_SYNC) //若SYNC=0xA5 MCU->ANT 46 { 47 SYNC_MRDY_DEASSERT(); //拉高MRDY信号,MCU有话要说 48 49 ucMesgLen = pucTxMsgBuffer[0] + MESG_SAVED_FRAME_SIZE; //读取待发送信息的长度,并根据DataLength位和ID位+2 50 ucIndex = 0; 51 52 SYNC_SRDY_ASSERT(); //准备好了可以开始写了 53 54 do //循环写完信息(不含校验和),并更新校验和 55 { 56 WriteByte(pucTxMsgBuffer[ucIndex]); 57 ucCheckSum ^= pucTxMsgBuffer[ucIndex]; 58 } 59 while (++ucIndex < ucMesgLen); 60 61 WriteByte(ucCheckSum); //写出校验和 62 } 63 else if (ucByte == MESG_TX_SYNC) //若SYNC=0xA4 MCU<-ANT 64 { 65 SYNC_SRDY_ASSERT(); //确认完毕,准备好接受下一个字节 66 ucByte = ReadByte(); //第二个字节发过来的就是DataLength 67 ucMesgLen = ucByte + MESG_SAVED_FRAME_SIZE; //DataLength+2得到整体长度 68 ucIndex = 0; 69 70 do //循环读完剩下的消息 71 { 72 pucRxMsgBuffer[ucIndex] = ucByte; //存入接收缓存 73 ucCheckSum ^= ucByte; //更新校验和 74 ucByte = ReadByte(); 75 } 76 while (++ucIndex < ucMesgLen); 77 78 if (ucCheckSum == ucByte) //确认校验和无误 79 { 80 bRxMessage = TRUE; //置位成功接收标志 81 SYNC_SRDY_ASSERT(); //处理完毕,等待下一个字节到来 82 } 83 } 84 } 85 86 return bRxMessage; //返回接收信息标志 87 }
ANT无线通信技术(5) ANT与MCU的SPI通信时序分析及相关程序设计
标签:
原文地址:http://www.cnblogs.com/npwhere/p/4293633.html