cc2530入门与串口中断处理

阅读: 评论:0

cc2530⼊门与串⼝中断处理
注:转载请注明出处。
做毕业设计的时候⽤到了cc2530开发板,⽤协议栈编程实现智能家居的功能。现在总结⼀下:
先从Z_Stack的main()函数开始。 main函数在ZMain.c中,总体来说,它⼀共做了两项⼯作,⼀项是系统初始化,即由启动代码来初始化硬件系统和软件架构需要的各个模块;另外⼀项就是开始执⾏操作系统实体。
先引⼊⼀下概念性的东西:
反应烧结碳化硅端点(EndPoint):是协议栈应⽤层的⼊⼝,即⼊⼝地址,也可以理解应⽤对象(
Application Object)存在的地⽅,它是为实现⼀个设备描述⽽定义的⼀组集
端点0 :⽤于整个ZigBee设备的配置和管理
端点255:⽤于向所有的端点进⾏⼴播
端点241~254:保留端点
其他端点:映射应⽤对象,并使得应⽤程序可以跟ZigBee堆栈其他层进⾏通信。
簇(Cluster):⼀个具体的应⽤(例如智能家居系统)有⼤量细节上的⼩规范(例如
电灯的控制:开灯、关灯等),这个规范即成为簇(cluster)
协调器:协调器是整个⽹络的核⼼,它最主要的作⽤是启动⽹络,其⽅法是其⽅法是选择⼀个相对空闲的信道,形成⼀个PANID。
路由器:路由器的主要功能是提供接⼒作⽤,能扩展信号的传输范围,因此⼀般情况下应该⼀直处于活动状态,不应休眠。
终端设备可以睡眠也可以唤醒,因此可以⽤电池来供电。
信道:  2.4GHz的射频频段被分为16个独⽴的信道。每⼀个设备都有⼀个默认的信道集(DEFAULT_CHANLIST)。协调器扫描⾃⼰的默认信道并选择噪声最⼩的信道作为⾃⼰所建的⽹络信道。设备节点和路由器也要扫描默认信道集并选择信道上已经存在的⽹络加⼊。
PANID :  PANID指⽹络编号,⽤于区分不同的⽹络设备,PANID值与ZDAPP_CONFIG_PAN_ID的值设定有关。如果协调器的ZDAPP_CONFIG_PAN_ID设置为0xFFFF,则协调器将产⽣⼀个随机的P
ANID,如果路由器和终端节点的ZDAPP_CONFIG_PAN_ID设置为0xFFFF,路由器和终端节点将会在⾃⼰默认信道上随机的选择⼀个⽹络加⼊,⽹络协调器的PANID即为⾃⼰的PANID。如果协调器的ZDAPP_CONFIG_PAN_ID设置为⾮0xFFFF值,则协调器根据⾃⼰的⽹络长地址(IEEE地址)或ZDAPP_CONFIG_PAN_ID随机产⽣PANID的值。不同的是如果路由器和终端节点的ZDAPP_CONFIG_PAN_ID 的值设置为⾮0xFFFF,则会以ZDAPP_CONFIG_PAN_ID值作为PANID。如果协调器的值设为⼩于等于0x3FFF的有效值,协调器就会以这个特定的PANID值建⽴⽹络,但是如果在默认信道上已经有了该PANID值的⽹络存在,则协调器会继续搜寻其它的PANID,直到到不冲突的⽹络为⽌,这样就可能产⽣⼀个问题如果协调器在默认信道上发⽣PANID冲突⽽更换PANID,终端节点并不知道协调器已经更换了PANID,还会继续加⼊到PANID为ZDAPP_CONFIG_PAN_ID值的⽹络中。
协议栈的⽂件包层次结构:
App:应⽤层⽬录,这是⽤户创建各种不同⼯程的区域,在这个⽬录中包含了应⽤层的内容和
这个项⽬的主要内容,在协议中⼀般是以操作系统的任务实现的
HAL:硬件层⽬录,包含有与硬件相关的配置和驱动及操作函数
MAC:MAC层⽬录,包含了MAC层的参数配置⽂件及其MAC的LIB库的函数接⼝⽂件
MT:实现通过串⼝可控制各层,并与各层进⾏直接交互
NWK:⽹络层⽬录,包含⽹络层配置参数⽂件⽹络层库的函数接⼝⽂件及APS层库的函数接⼝
OSAL:协议栈的操作系统
Profile:AF(Application framework应⽤框架)层⽬录
Security:安全层⽬录,包含安全层处理函数,⽐如加密函数等
Services:地址处理函数⽬录,包括地址模式的定义及地址处理函数
Tools:⼯程配置⽬录,包括空间划分及Z-Stack相关配置信息
ZDO:ZDO⽬录
ZMac:MAC层⽬录,包括MAC层参数配置及MAC层LIB库函数回调处理函数
ZMain:主函数⽬录,包括⼊⼝函数及硬件配置⽂件
Output:输出⽂件⽬录,由IAR IDE⾃动⽣成
1. 系统初始化
系统启动代码需要完成初始化硬件平台和软件架构所需要的各个模块,位操作系统的运⾏做好准备⼯作,主要分为初始化系统时钟, 检测芯⽚的⼯作电压,初始化堆栈,初始化各个硬件模块,初始化flash存储,形成芯⽚MAC地址,初始化⾮易失变量,初始化MAC层协议,初始化应⽤帧协议,初始化操作从系统等。
启动代码为操作系统的执⾏做好准备⼯作后,就开始执⾏操作系统⼊⼝程序,并由此彻底将控制权交给操作系统。其实操作系统的实体只有⼀⾏代码:                              osal_start_system(); // No Return from here
根据这句代码的注释,即本函数不会返回,也就是说它是⼀个死循环,永远不可能执⾏完。这个函数就是轮转查询操作系统的主体部分,它所做的就是不断的查询每个任务是否有事件发⽣,如果发⽣,则执⾏相应的函数,如果没有发⽣,就查询下⼀个任务。
函数的主体部分代码如下:
for(;;)  // Forever Loop  ⽆限循环
#endif
{
玉米面条加工机械uint8 idx = 0;
osalTimeUpdate();
Hal_ProcessPoll();  // This replaces MT_SerialPoll() and osal_check_timer().
do {
if (tasksEvents[idx])  // Task is highest priority that is ready.  准备好具有最⾼优先权的任务
{
break;
}
} while (++idx < tasksCnt);//得到了待处理的具有最⾼优先级的任务索引号idx
if (idx < tasksCnt)//确认本次有任务需要处理
{
uint16 events;
halIntState_t intState;
//进⼊/退出临界区,来提取出需要处理的任务中的事件
HAL_ENTER_CRITICAL_SECTION(intState);
events = tasksEvents[idx];
tasksEvents[idx] = 0;  // Clear the Events for this task.  清除任务中的事件
HAL_EXIT_CRITICAL_SECTION(intState);
//通过指针调⽤执⾏对应的任务处理函数
events = (tasksArr[idx])( idx, events );
//进⼊/退出临界区,保存尚未处理的事件
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events;  // Add back unprocessed events to the current task. //增加下⼀个任务
HAL_EXIT_CRITICAL_SECTION(intState);
//本次事件处理函数执⾏完,继续下⼀个循环
砭石枕}
操作系统专门分配了所有任务时间的taskEvents[]这样⼀个数组,每⼀个单元对应存放着⼀个任务的所有事件。在这个函数中,⾸先通过⼀个do-while循环来遍历tasksEvents[],到第⼀个具有事件的任务(即具有待处理事件的优先级最⾼的任务,因为序号低的优先级⾼),然后跳出循环此时就得到了有事件待处理的具有最⾼优先级的任务序号idx,然后通过events = tasksEvents[idx]语句,将这个当前具有最⾼优先级任务的时间取出,接着就调出(tasksArr[idx])hdpe线性排水沟
(idx,events)函数来执⾏具体的处理函数了。下⾯以例⼦GeneralApp为例看⼀下taskArr函数数组(这个数组在Osal_GeneralApp.c中,前缀Osal表明这是和操作系统接⼝⽂件,Osal_start_system()函数中通过函数指针(task[idx])(idx,events)调⽤具体的相应任务处理函数)。
项⽬GeneralApp中的tasksArr函数数组代码如下:
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,                                    //MAC层事件处理进程
nwk_event_loop,                                  //⽹络层事件处理进程
Hal_ProcessEvent,                                //物理层事件处理进程
#if defined( MT_TASK )
MT_ProcessEvent,                                //调试任务处理进程
#endif
APS_event_loop,                                  //APS层事件处理进程,可选
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,                            //ZDApp层事件处理进程
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
GenericApp_ProcessEvent                    //⽤户应⽤层处理进程,⽤户⾃⼰⽣成
};
这些任务的优先级从⾼到低,即MAC层任务优先级最⾼。⼀般情况下⽆需修改这些函数,只需按照⾃⼰的需求编写应⽤层的任务及事件处理函数即可。⼀般情况下,⽤户只需在⼯程⾥外加三个⽂件就可以完成⼀个项⽬,⼀个是主⽂件,存放具体的任务事件处理函数(如:SampleApp_ProcessEvent);⼀个是这个主⽂件的头⽂件(以Osal开头),是专门存放任务处理函数数组tasksArr[]的⽂件。对于GeneralApp来说,主⽂件是GeneralApp.c,头⽂件是GeneralApp.h,操作系统接⼝⽂件是Osal_GeneralApp.c;
系统开始的时候的初始化流程:
根据上图,执⾏完⾃定义事件
SampleApp_ProcessEvent()函数(注:这⾥的⾃定义事件是⾃⼰根据需求定义的,不明⽩的话先不⽤理会)后
并不代表主函数结束,程序将会⼀
直待在osal_start_system()进⾏
任务轮询
Zigbee组⽹流程:
协调器的组⽹,终端设备和路由设备发现⽹络以及加⼊⽹络
1. Z-Stack 由 main()函数开始执⾏
2. osal_init_system()函数,执⾏操作系统初始化
3. 进⼊osalInitTasks()函数,执⾏操作系统任务初始化
智能卡制作4. ZDApp层,初始化,执⾏ZDApp_init函数后,如果是协调器将建⽴⽹络
,如果是终端设备将加⼊⽹络。
5. 执⾏ZDOInitDevice()函数,执⾏设备初始化
6. 执⾏ZDApp_NetworkInit函数,完成⽹络初始化
7. ZDApp_event_loop()函数
8. 执⾏ZDO_StartDevice()函数,启动设备
协调器和路由器组建⽹络
if ( ZG_BUILD_COORDINATOR_TYPE && logicalType ==
NODETYPE_COORDINATOR ) //当设备作为协调器时,执⾏这个
条件语句。
执⾏NLME_NetworkFormationRequest()向⽹络层发送⽹络形成
请求,当⽹络层建⽴⽹络后,将给予 ZDO层反馈信息;
接着去执⾏ZDApp层的 ZDO_NetworkFormationConfirmCB()
函数
if ( ZG_BUILD_JOINING_TYPE && (logicalType ==
NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE) )
//当为终端设备或路由时,执⾏这个条件语句,发出加⼊⽹络请求,
// 继⽽转到ZDO_NetworkDiscoveryConfirmCB()函数
Zstack协议栈函数
向操作系统分配任务事件⽚函数
uint8 osal_start_timerEx( uint8 taskID, uint16 event_id,
uint16 timeout_value )
这个定时器只是为发送周期信息开启的,设备启动初始化后从
这⾥开始触发第⼀个周期信息的发送,然后周⽽复始下去
Zigbee数据通信
Zigbee发送数据时调⽤函数AF_DataRequest()
若Zigbee接收到数据,则进⼊⾃定义事件
SampleApp_ProcessEvent()后,会触发能接收及处理数
据包的函数SampleApp_MessageMSGCB()
发送数据函数AF_DataRequest
afStatus_t AF_DataRequest(
afAddrType_t *dstAddr,//发送⽬的地址+端点地址和传送模式endPointDesc_t *srcEP,//源终端的描述(如:操作系统任务ID)
uint16 cID, //⽤于接收器识别的标号(簇ID)
uint16 len, //发送数据长度
uint8 *buf, //发送数据缓冲区(即发送的数据)
uint8 *transID, //任务ID号
uint8 options, //有效位掩码的发送选项
uint8 radius //最⼤传送跳数
);
afIncomingMSGPacket_t
typedef struct {
osal_event_hdr_t hdr; /* OSAL Message header */
uint16 groupId; /*组号(若未设置则为0)*/
uint16 clusterId; /*⽤于识别的标号(簇ID),应该与数据发送函数中的簇ID⼀致*/ afAddrType_t srcAddr;
uint16 macDestAddr; /* MAC header destination short address */
uint8 endPoint; /*端点号*/
uint8 wasBroadcast; /*判断是否为⼴播地址,若是返回TRUE*/
uint8 LinkQuality; /* The link quality of the received data frame */
uint8 correlation; /* The raw correlation value of the received data frame */ int8 rssi; /* 接收到的射频功率单位dBm */
uint8 SecurityUse; /* deprecated */
uint32 timestamp; /* receipt timestamp from MAC */ afMSGCommandFormat_t cmd; /* 接收到的数据 */
} afIncomingMSGPacket_t;
Zstack简单串⼝通信调试:
在SampleApp.c添加头⽂件
#include "MT_UART.h"
#include "MT_APP.h"
#include "MT.h"
在SampleApp_Init()函数开始部分编写如下代码:
/***********串⼝初始化************/
MT_UartInit();//初始化
MT_UartRegisterTaskID(task_id);//登记任务号
HalUARTWrite(0,"Hello World\n",12);
进⼊MT_UartInit()函数,修改MT_UART_DEFAULT_BAUDRATE为
HAL_UART_BR_115200
MT_UART_DEFAULT_OVERFLOW 为FALSE
⼯程名->右键->Options->C/C++ Compiler->Preprocessor->Defined
symbols:
修改为ZTOOL_P1 xMT_TASK xMT_SYS_FUNC xMT_ZDO_FUNC
xLCD_SUPPORTED=DEBUG
接通串⼝调试助⼿,进⾏串⼝测试
Zigbee的通讯⽅式
主要有三种:⼴播、点播、组播
⼴播就是⽹络中任意⼀节点设备发出⼴播数据,⽹络中其它的任
意节点都能收到
点播(也叫点对点)就是⽹络中任意⼀节点对另⼀个已知⽹络地
址(即短地址)的节点进⾏数据发送的过程
组播(也叫组⽹)就是⽹络中所有节点设备被分组后,⽹络中任
意组的任意⼀节点都可以对某⼀已知组号(包扩⾃⾝所属的组号)
的组进⾏数据发送的过程
在这⾥只给出单播实现的例⼦,以SimpleApp为例,其它两个⽅式原理和这个差不多,读者可⾃⾏设置:参数配置
注:以下代码都需要进⾏粘贴(在SampleApp.c中)
⽂件开头定义 afAddrType_t Point_To_Point_DstAddr;
SampleApp_Init中添加参数配置
Point_To_Point_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //点播
Point_To_dPoint = SAMPLEAPP_ENDPOINT;
Point_To_Point_DstAddr.addr.shortAddr = 0x0000; //发给协调器
添加点对点发送函数
⽂件后⾯添加:
void SampleApp_SendPointToPointMessage( void )
{
uint8 data[10]={0,1,2,3,4,5,6,7,8,9};
if ( AF_DataRequest( &Point_To_Point_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_Point_To_Point_CLUSTERID,
10,
data,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
修改参数
在SampleApp.h中,添加 #define SAMPLEAPP_Point_To_Point_CLUSTERID 5
SampleApp_ClusterList列表⾥⾯添加SAMPLEAPP_Point_To_Point_CLUSTERID,如:
const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] =
{
SAMPLEAPP_PERIODIC_CLUSTERID,
SAMPLEAPP_FLASH_CLUSTERID,
SAMPLEAPP_Point_To_Point_CLUSTERID
};
修改SAMPLEAPP_MAX_CLUSTERS 值为 3
(该部分修改内容可选)
在if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )中,替换
SampleApp_SendPeriodicMessage()为
SampleApp_SendPointToPointMessage(),后⾯添加“LED1 闪烁提⽰”代码
HalLedBlink( HAL_LED_1, 2,50, 500 );
修改参数
修改SampleApp_MessageMSGCB中簇ID为
SAMPLEAPP_Point_To_Point_CLUSTERID,并添加如下代码:
HalUARTWrite(0,"I get data\n",11); //提⽰接收到数据
for(i=0;i<10;i++)
HalUARTWrite(0,&asc_16[pkt->cmd.Data[i]],1);//ASCII码发给PC机
HalUARTWrite(0,"\n",1); // 回车换⾏
定义变量:
uint8 asc_16[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'},i;
修改参数
屏蔽掉(SampleApp_NwkState == DEV_ZB_COORD),如:
if ( /*(SampleApp_NwkState == DEV_ZB_COORD)|| */(SampleApp_NwkState ==
DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) )
到SampleApp_MessageMSGCB( MSGpkt );
后⾯添加“LED1 闪烁提⽰”代码 HalLedBlink( HAL_LED_1, 2,50, 500 );
在⽂件开头声明void SampleApp_SendPointToPointMessage(void);
分别以协调器、终端或路由器的⽅式下载到2-3个设备中,连接串⼝
注:HalLedBlink( HAL_LED_1, 2,50, 500 ); //LED1 闪烁提⽰进⾏指⽰
单播通信时,收发双⽅的端点号必须相同。到这⾥单播通信⽅式就实现了。
再此说⼀下串⼝:
1.在z_stack中,可以通过预编译和#define来选择是⽤DMA⽅式或中断⽅式进⾏数据传输。
⾸先打开hal_board_cfg.h⽂件,确定有以下语句:
/
* Set to TRUE enable DMA usage, FALSE disable it */
#ifndef HAL_DMA
#define HAL_DMA TRUE
#endif
这段语句定义了编译器编译有关DMA的函数
这⾥引⽤⼀下:任⼀权,刘童的协议栈中的MT包实现UART的发送与接收
Zigbee协议栈已经把使⽤串⼝的条件准备好了,从应⽤⾓度讲,利⽤协议栈现有平台即ZStack⾃带的MT包来实现⾃⼰的串⼝应⽤,只需对协议栈做⼀些修改就可以实现URAT发送与接收的功能。
关键函数的解析
MT_UartInit () ①
这是为UART串⼝传输数据⽽初始化的MT函数包,在其中定义了串⼝的波特率,最⼤接收发送数据量,传输模式等相关配置。在这⾥的各项参数不需要改变,保持系统默认即可。
三丝光棉MT_UartProcessZToolData()②
这是MT程序包中URAT接收数据的代码,在这⾥⾯需要修改的地⽅是,在数据接收完毕后需要添加⼀个回车,便于我们区分不同传输数据,具体的代码为UartRxBuf.RxBuf[count]='\n';此
段代码需要添加在count++;后,这⾥注意⼀下count,⼀会还会⽤到。
hal_board_cfg.h ③
⾸先说明⼀下,串⼝接收发送数据的⽅式有两种:⼀种是中断模式,另⼀种是DMA模式,这⾥是使⽤中断模式。⽽在hal_board_cfg.h中,DMA模式的优先级要⾼于中断模式的,这⾥最
简单的解决⽅案就是将DMA的那段预编译注释掉,即仅留⼀种模式——中断。
void Sampleapp_Init ④
这是应⽤层函数初始化,即对我们⾃⼰的具体应⽤进⾏初始化,在这⾥⾯需要添加两段代码MT_UartInit() 和MT_UartRegisterTaskID(SampleApp_TaskID);这两端代码要添加在Sampl Init()中。

本文发布于:2023-05-29 03:40:47,感谢您对本站的认可!

本文链接:https://patent.en369.cn/patent/3/118081.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:函数   任务   发送   需要   代码   协调
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图