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

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 }
时间: 2024-08-07 16:47:56

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

ANT无线通信技术(3) 数据类型及拓扑结构

Previously,我们说了配置ANT通道相关的几个参数,但想要完成节点的通道配置与配对的全过程,我们还有几个概念与参数需要提前了解. 一.典型的ANT节点结构 这里我并不会过多地介绍ANT模块的硬件模块,但要说明的是,ANT作为一种高度集成且精简高效的商用私有协议,nordic提供了完整SoC无线解决方案.比如nRF24APx系列,nRF51xxx系列等,都是常用的ANT模块.只需要配合极少数的外部MCU资源就可以完成应用的开发.下图是一个典型的ANT节点结构图,ANT模块通过一个异步或同步

ANT无线通信技术(2) 通道配置

一.ANT通道介绍 ANT通道的配置是ANT应用开发中的关键.官方文档中的叫法是“channel”,之所以我翻译为“通道”,而不是“信道”或者“频段”,是因为后两词是常用于电子通信领域中的一个专有概念,往往带有许多的技术背景与色彩.而ANT技术灵活多变的组网通讯方式,使得ANT channel拥有了更为丰富的逻辑含义,使用汉语中意义最广泛的“通道”一词能更好得描述这个抽象的逻辑概念. 一个ANT通道用于连接至少两个节点,使其能够交换信息.每个通道至少有一个主节点(Master Node)和一个从

ANT无线通信技术(4) 配对实例

了解了有关通道配置的概念之后,接下来我们通过实例进行ANT配对的学习. 一.配对 在两个节点间建立一个ANT通道的过程,叫做配对(pairing).具体操作是,一个从节点获取一个主节点广播的唯一的通道ID,并储存或暂存在存储器中,然后节点间便可以开始通信.配对可以是永久的,半永久,或者暂时的.ANT提供多种功能,以满足不同的配对要求,但并非所有模块都能支持这些功能,具体情况可以参考模块手册. 配对位(pairing bit) 包含/排除列表(in/exclusion list) 临近搜索(pro

windows+ant+git+tomcat中ant直接获取git项目部署注意点

最近项目搬迁到公司的"GitHub"上面原来的SVN的ant发布脚本要改下,于是百度ant获取git的方法太少了,windows平台上更是没有所以搞了两天,今天终于有点成果分享给大家. 1.服务器上也要安装git,还要配置git环境,在Path中加上C:\Program Files (x86)\Git\cmd(你的路径可能不同,就是Git\cmd路径) 2.GitHub上有两种路径http的那个要用户密码,我是没研究出来bat脚本自动输入密码,所以用git开头的路径 3.把公钥.ssh

ant的高级使用,ant命令详解,ant打包,ant编译后打包去掉jar文件

在日常的项目开发中,我们可以经常性的需要打包测试,尤其是开发环境是windows,而实际环境则是linux. 这样的话,很多程序员要一会打一个包,一会打一个包,这些包可能会很大,实际上只有代码部分会变动,而jar包基本则不动. 当然很多人可能会说,自动化测试.很好的,我们今天要做的就是自动化测试的第一步. 这个时候我是可以使用ant来打包,去掉项目中的所有的jar文件.然后在项目的tomcat启动时到特定的地点去加载jar文件. 这样做,war包可能会只有几M,什么更小.具体如何动态的加载jar

个域网通讯协议 ZigBee - 另一个不老的短距离、低功耗无线通信技术

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 本来没想发此篇,对于 zigbee 的兴趣没这么深刻,可是看到下面截取百度百科原文的最后一句"2009年开始,Zigbee采用了IETF

[51单片机] SPI nRF24L01无线 [可以放在2个单片机里实现通信]

main.c 1 #include<reg51.h> 2 #include"2401.h" 3 4 #define uint unsigned int 5 #define uchar unsigned char 6 7 sbit KEY8=P3^7; //发送按键 8 sbit beep=P2^3;//喇叭 9 sbit LED6=P1^6; ////接收到数据后的功能实现灯 10 11 void delay_ms(uint z) //延时函数 12 { 13 uint x

jenkins , ant ctomcat+shell报ant: command not foun.

#!/bin/sh # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements.  See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file

推荐一个学通信技术的网站,百度“51学通信”第一个就是

推荐一个学通信技术的网站www.51xuetongxin.com,百度"51学通信"第一个就是.这个网站有大量的通信技术在线视频,都是从业很多年的通信人士录制的.并且针对入门者设置了有通信技术入门学习课程.包括IMS.IP网络技术.EPC.2/3/4G技术等等.非常全面.强烈推荐.而且是免费的哦.