码迷,mamicode.com
首页 > 其他好文 > 详细

ANT无线通信技术(5) ANT与MCU的SPI通信时序分析及相关程序设计

时间:2015-02-16 01:39:01      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

ANT与MCU可以使用异步UART或同步SPI两种方式连接。异步通信与同步通信的各自特点这里不赘述,总之我们选择使用同步方式进行连接。

 

一、SPI简介

      SPI(Serial Peripheral Interface),串行外设接口。是摩托罗拉公司开发的一种同步全双工通信协议。依靠收发两端的移位寄存器,以及主机master提供的时钟信号,双方可以实现较高速率的同步全双工传输。

标准的SPI是3/4根线,分别用于一主一从/多主从的情况。4根线分别是:

 

    1. MOSI 主机发,从机收 master out slave in 
    2. MISO 主机收,从机发 master in slave out 
    3. SCLK 主机时钟输出,从机时钟输入
    4. CS   片选信号,用于多主从情况 

有些命名可能有区别,不过意思相同。

 

二、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通信机制基本描述如下:

    • 半双工模式的SPI,ANT为主,MCU为从
    • MRDY,EN,外加SRDY,共同完成握手以及流控
    • nRF24AP2作主节点时,自动转发所有收到的消息至MCU
    • MCU使用串口,必须在请求得到nRF24AP2回应后才可以

 

 

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!