z-stack调试之ZDApp_init

本文介绍了Z-Stack 1.43-1.2.1版本中SimpleApp的调试过程,重点分析了osal_init_system()函数内部ZDApp_init()的实现原理及流程,包括ZDO层的初始化、设备状态控制等内容。

协议栈版本z-stack1.43-1.2.1,SimpleApp

本人一般调试程序一般习惯自上而下的原则,在调试z-stack的过程中,在osal_init_system()就卡住了。进入osal_init_system()发现问题出在ZDApp_init().

ZDApp_init()是ZD层的初始化函数。首先,我找到了ZD层的定义。ZDO即zigbee device object(zigbee设备对象,用来描述设备的状态)TI的ZDO层的API函数提供了创建网络,发现网络,假如网络,绑定应用终节点和管理安全的功能。ZDO层所有功能的定义和调用都在ZDProfile里面。

ZDProflie描述了zigbee设备在ZDO执行的每一个细节,它定义了设备的description和cluster(簇就是一组应用的命令和回复的集合),通过定义消息结构体ZDProfile提供:设备建立网络,设备和服务发现,终端绑定、绑定和不绑定,网络管理服务 功能。(从TI提供的官方文档上面,我们获得了如上信息。)

默认startup a network是在ZDApp_init()里面。但是,application可以不用理会这个默认习惯。条件编译选项选择了HOLD_AUTO_START、NV_RESTORE,application就能控制设备网络的开始,通过调用ZDOInitDevice()。

void ZDApp_Init( byte task_id )
{
  uint8 capabilities;

  // Save the task ID
  ZDAppTaskID = task_id;  //分配任务ID

  // Initialize the ZDO global device short address storage
  ZDAppNwkAddr.addrMode = Addr16Bit;
  ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;//初始化短地址
  (void)NLME_GetExtAddr();  // Load the saveExtAddr pointer.

  // Check for manual "Hold Auto Start"
  ZDAppCheckForHoldKey();//检测SW5是否按下,如果按下设置标志位devState = DEV_HOLD

  // Initialize ZDO items and setup the device - type of device to create.
  ZDO_Init();

  // Register the endpoint description with the AF
  // This task doesn't have a Simple description, but we still need
  // to register the endpoint.

  afRegister( (endPointDesc_t *)&ZDApp_epDesc );

#if defined( ZDO_USERDESC_RESPONSE )
  ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE

  // set broadcast address mask to support broadcast filtering
  NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities);
  NLME_SetBroadcastFilter( capabilities );

  // Start the device?
  if ( devState != DEV_HOLD )
  {
    ZDOInitDevice( 0 );
  }
  else
  {
    // Blink LED to indicate HOLD_START
    HalLedBlink ( HAL_LED_4, 0, 50, 500 );
  }

  ZDApp_RegisterCBs();
} /* ZDO_Init() */

这里启动网络,在条件编译里面设置了hold——auto——start的话,检测到按键SW5后系统才会继续运行


以上代码是在IAR环境下超声波代码下面是main函数代码#include "iocc2530.h" #include "AF.h" #include "DNUI_SampleApp.h" #include "OnBoard.h" #include "string.h" #include "hal_uart.h" #include "OSAL.h" #include "ZGlobals.h" #include "aps_groups.h" #include "ZDApp.h" #include "OnBoard.h" /* HAL */ #include "hal_lcd.h" #include "hal_led.h" #include "hal_key.h" #include "stdio.h" #include "Temperature.h" #include "SmartUltra.h" #include "hal_uart.h" #include "SmartDHT11.h" #include "SmartLightSensor.h" // 氝樓嫖鏗換覜け芛恅璃 #include "ultrasonic.h" // 添加超声波传感器支持 #include "hal_mcu.h" typedef unsigned char uint8; typedef unsigned short uint16; cId_t DNUI_SampleApp_ClusterIDS[DNUI_SAMPLEAPP_CLUSTER_NUM] = { DNUI_SAMPLEAPP_DATATEST_CLUSTER_ID }; SimpleDescriptionFormat_t DNUI_Sample_SimpleDesc = { DNUI_SAMPLEAPP_ENDPOINT, DNUI_SAMPLEAPP_PROFILE_ID, DNUI_SAMPLEAPP_DEVICE_ID, DNUI_SAMPLEAPP_DEVICE_VER, 0, DNUI_SAMPLEAPP_CLUSTER_NUM, (cId_t*)DNUI_SampleApp_ClusterIDS, DNUI_SAMPLEAPP_CLUSTER_NUM, (cId_t*)DNUI_SampleApp_ClusterIDS }; uint8 DNUI_SampleAppTaskID; devStates_t DNUI_SampleApp_NwkState; //悵湔厙釐袨怓 uint8 DNUI_SampleApp_TransID; //悵湔秏洘ID afAddrType_t Broadcast_Addr, Coor_Addr; //狟俴杅擂華硊 endPointDesc_t DNUI_SampleApp_epDesc; //傷萸鏡扴睫 uint8 DHT11DataBuf[20]; uint8 DHT11BufLen = 0; // 氝樓嫖桽ッ僅遣喳Е uint8 LightDataBuf[10]; uint8 LightBufLen = 0; void DNUI_SampleApp_Init(uint8 task_id); uint16 DNUI_SampleApp_ProcessEvent(uint8 task_id, uint16 events); void DNUI_SampleApp_Init(uint8 task_id) { //--start--基本变量初始化--- DNUI_SampleAppTaskID = task_id; DNUI_SampleApp_NwkState = DEV_INIT; DNUI_SampleApp_TransID = 0; //--end--基本变量初始化--- //--start--注册端点描述符-- DNUI_SampleApp_epDesc.endPoint = DNUI_SAMPLEAPP_ENDPOINT; DNUI_SampleApp_epDesc.task_id = &DNUI_SampleAppTaskID; DNUI_SampleApp_epDesc.latencyReq = noLatencyReqs; DNUI_SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t*)&DNUI_Sample_SimpleDesc; afRegister(&DNUI_SampleApp_epDesc); //--end--注册端点描述符-- UartInit(NULL); SmartLightSensor_Init(); //--start--设置协调器地址-- Coor_Addr.addrMode = (afAddrMode_t)Addr16Bit; Coor_Addr.endPoint = DNUI_SAMPLEAPP_ENDPOINT; Coor_Addr.addr.shortAddr = 0x0; // 协调器地址 // 添加超声波模块初始化 // 初始化引脚 // 在DNUI_SampleApp_Init中添加 P1SEL &= ~0x02; // 确保P1.1是GPIO模式 P1DIR &= ~0x02; // P1.1设为输入 P1INP &= ~0x02; // 使能上拉电阻 P2INP &= ~0x20; // 选择上拉而非下拉 (bit5=0) // 配置定时器1 (分频128, 16MHz/128 = 125kHz -> 8us/计数) T1CTL = 0x0E; // 分频128, 自由运行模式 T1CCTL0 = 0x00; // 通道0比较模式禁用 //--end--设置协调器地址-- } uint16 DNUI_SampleApp_ProcessEvent(uint8 task_id, uint16 events) { afIncomingMSGPacket_t* MSGpkt; uint16 distance = Measure_Distance(); if (events & SYS_EVENT_MSG) { MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive(task_id); while (MSGpkt) { switch (MSGpkt->hdr.event) { case AF_INCOMING_MSG_CMD: if (DNUI_SampleApp_NwkState == DEV_ZB_COORD) { //--start--衪覃け諉彶杅擂腔揭燴軀憮 // 眻諉蛌楷埻宎杅擂善揹諳 UartSendString(0, MSGpkt->cmd.Data, MSGpkt->cmd.DataLength); // 褫恁ㄩ氝樓遙俴睫 uint8 newline[2] = {'\r', '\n'}; UartSendString(0, newline, 2); // LED硌尨 HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE); } else if (DNUI_SampleApp_NwkState == DEV_END_DEVICE) { //--start--笝傷扢掘諉彶杅擂腔揭燴軀憮 } else if (DNUI_SampleApp_NwkState == DEV_ROUTER) { //--start--繚蚕け諉彶杅擂腔揭燴軀憮 } break; case ZDO_STATE_CHANGE://郪厙 DNUI_SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if (DNUI_SampleApp_NwkState == DEV_END_DEVICE)//笝傷誹萸樓?厙釐 { //--start--笝傷扢掘諉彶杅擂腔揭燴軀憮 osal_start_timerEx(task_id,DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT,1000);//笚ヽ俶腔隅奀¦昢 HalLedSet(HAL_LED_1,HAL_LED_MODE_ON); SmartDHT11_Init(task_id); } else if (DNUI_SampleApp_NwkState == DEV_ZB_COORD) { //--start--衪覃け諉彶杅擂腔揭燴軀憮 HalLedSet(HAL_LED_1, HAL_LED_MODE_ON); } else if (DNUI_SampleApp_NwkState == DEV_ROUTER) { //--start--繚蚕け諉彶杅擂腔揭燴軀憮 } break; default: break; } osal_msg_deallocate((uint8*)MSGpkt); MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive(DNUI_SampleAppTaskID); } return (events ^ SYS_EVENT_MSG); } if(events & DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT) { // 黍?DHT11 uint8 status = SmartDHT11_GetVal(DHT11DataBuf, &DHT11BufLen); // 黍?嫖桽ッ僅 uint16 lightValue = SmartLightSensor_GetVal(); uint8 lightBuf[10]; uint8 lightLen = sprintf((char*)lightBuf, "%d", lightValue); // 添加超声波距离测量 uint16 distance = Measure_Distance(); // 获取超声波距离 uint8 distBuf[10]; uint8 distLen = sprintf((char*)distBuf, "%d", distance); // 组合所有传感器数据 (格式: "温度,湿度,光照,距离") uint8 combinedBuf[50]; uint8 combinedLen ; if(distance == 0xFFFF) { combinedLen = sprintf((char*)combinedBuf, "%d,%d,%d,ERR", DHT11DataBuf[0], DHT11DataBuf[1], lightValue); } else { combinedLen = sprintf((char*)combinedBuf, "%d,%d,%d,%d", DHT11DataBuf[0], DHT11DataBuf[1], lightValue, distance); } AF_DataRequest(&Coor_Addr, &DNUI_SampleApp_epDesc, DNUI_SAMPLEAPP_DATATEST_CLUSTER_ID, combinedLen, combinedBuf, &DNUI_SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); osal_start_timerEx(task_id, DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT, 1000); return (events ^ DNUI_SAMPLEAPP_ENDDEVICE_PERIODIC_MSG_EVT); } return 0; } void UartSendString(uint8 port, uint8 *buf, uint8 len) { // 妏蚚Z-Stack腔HalUARTWrite滲杅妗珋揹諳楷冞 HalUARTWrite(port, buf, len); } 现在超声波接受不到数据解决这个问题
最新发布
07-10
<think>首先,用户的问题是:“我想解决超声波传感器在IAR环境下无法接收数据的问题 请问IAR环境下超声波传感器无法接收数据的故障排查与解决方案”。这是一个具体的技术问题,涉及到超声波传感器在IAR Embedded Workbench环境下的故障排查。 我的角色是提供结构清晰、真实可靠的回答。回答必须遵循系统级指令:使用$...$格式的行内数学表达式,$$...$$格式的独立公式,正确LaTeX语法,中文回答,生成相关问题,并在引用段落末尾添加引用标识如[^1]。 参考提供的引用: - 引用[1]:关于超声波测距技术的应用,包括机器人导航、自动停车系统、液位测量和工业距离测量。提到了基于STM32F103C8T6的硬件设计。 - 引用[2]:关于外设初始化失败的问题,原因是电源问题,如滤波电容不当导致电源纹波过大。 - 引用[3]:关于优化措施,包括选择合适的MCU、合理布局传感器、使用高效算法。 这些引用可能与问题相关,因为超声波传感器通常涉及硬件设计、电源管理和微控制器编程。用户的问题集中在IAR环境下无法接收数据,所以焦点应在软件和硬件集成上。 回答结构: 1. **逐步解决问题**:从简单到复杂,覆盖常见原因。 2. **真实可靠**:基于通用知识,避免猜测。IAR是嵌入式开发环境,常用于ARM Cortex-M微控制器如STM32。 3. **引用标识**:在回答中自然地引用提供的段落,如果相关。 4. **生成相关问题**:在末尾添加相关问题部分。 关键点: - **硬件排查**:检查传感器连接、电源、信号线。 - **软件排查**:IAR项目设置、代码调试、中断处理、定时器配置。 - **常见原因**:电源问题(如引用[2])、初始化错误、通信协议问题。 结构化回答: - **引言**:简述问题。 - **故障排查步骤**: - 1. 检查硬件连接。 - 2. 验证电源稳定性(参考引用[2])。 - 3. 检查IAR环境设置。 - 4. 调试代码:确保传感器初始化正确,中断或轮询机制工作。 - 5. 测试传感器独立。 - **解决方案**:基于排查。 - **总结**。 - **相关问题**:生成3-5个相关问题。 使用数学表达式: - 可能涉及超声波测距公式:距离 = (速度 × 时间) / 2,其中速度是声速约340 m/s。行内格式:$d = \frac{v \times t}{2}$。 - 独立公式:如果需要,如声速方程。 引用标识: - 例如,提到电源问题时,引用[^2]。 - 提到优化时,引用[^3]。 最终回答用中文。</think>### IAR环境下超声波传感器无法接收数据的故障排查与解决方案 超声波传感器在嵌入式系统中常用于距离测量,如机器人导航或工业控制[^1]。在IAR Embedded Workbench环境下,无法接收数据可能由硬件、软件或配置问题引起。以下我将逐步引导您进行故障排查和解决,确保回答真实可靠,基于常见嵌入式开发实践。排查过程从简单到复杂,优先检查硬件再深入软件。 #### 1. **硬件排查(优先步骤)** - **检查传感器连接**: - 确保超声波传感器(如HC-SR04)的VCC、GND、Trig和Echo引脚正确连接到STM32微控制器(如STM32F103C8T6)。常见错误是引脚反接或虚焊。使用万用表测试连通性。 - 验证电源稳定性:电源纹波过大会干扰传感器工作。参考引用[2],检查电源滤波电容是否合适(例如,使用100nF陶瓷电容并联10μF电解电容)。如果纹波超过50mV,可能导致传感器不响应[^2]。 - 测试传感器独立工作:将传感器连接到5V电源和示波器,触发Trig引脚,观察Echo输出。正常时,Echo应返回高电平脉冲,脉冲宽度与距离成正比,公式为$d = \frac{v \times t}{2}$,其中$v$是声速(约340 m/s),$t$是时间差。 - **优化传感器布局**: - 传感器位置影响信号质量。确保传感器面向空旷区域,避免障碍物干扰。引用[3]建议合理布局传感器以提升精度[^3]。 #### 2. **软件排查(IAR环境设置与代码调试)** - **验证IAR项目配置**: - 在IAR中,检查工程设置:确保目标MCU型号匹配(如STM32F103C8T6),时钟源正确(例如8MHz晶振),并启用必要的外设(如GPIO和定时器)。常见错误是未启用TIM或EXTI中断。 - 编译选项:确认优化级别适中(如-O1),避免过度优化导致代码异常。引用[3]提到使用高效算法减少资源占用[^3]。 - 调试工具:使用IAR的C-SPY调试器,设置断点在传感器初始化代码处,检查寄存器值。 - **检查传感器驱动代码**: - 初始化代码:确保正确配置GPIO(Trig为输出,Echo为输入)和定时器(用于测量Echo脉冲宽度)。示例代码片段(基于STM32 HAL库): ```c // 初始化Trig引脚(输出模式) HAL_GPIO_Init(GPIOA, &(GPIO_InitTypeDef){.Pin = GPIO_PIN_1, .Mode = GPIO_MODE_OUTPUT_PP}); // 初始化Echo引脚(输入模式,启用中断) HAL_GPIO_Init(GPIOA, &(GPIO_InitTypeDef){.Pin = GPIO_PIN_2, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_NOPULL}); HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI2_IRQn); ``` - 常见错误:未处理中断或定时器溢出。Echo引脚应使用外部中断(EXTI)捕获上升沿/下降沿。 - 测量逻辑:使用定时器计算Echo高电平时间。公式为$t = \frac{\text{TIM\_Counter} \times \text{时钟周期}}{1}$,确保时钟频率正确(例如72MHz)。如果时间$t$为0,表示未收到数据。 - 测试代码:添加日志输出(通过UART或IAR的Terminal I/O),打印测量值。如果输出无效数据,检查算法逻辑。 #### 3. **常见问题与解决方案** - **电源问题**:如引用[2]所述,电源纹波是常见原因。解决方案:添加LC滤波电路或使用稳压模块。如果传感器电压要求5V而STM32输出3.3V,需电平转换器[^2]。 - **初始化失败**:确保外设时钟已启用(例如在STM32 CubeMX中配置RCC)。错误代码示例:`HAL_TIM_Base_Start()`返回HAL_ERROR。 - **环境干扰**:超声波易受噪音影响。在代码中添加软件滤波(如多次采样取平均)。 - **IAR特定问题**:更新IAR到最新版本,检查链接器脚本是否包含所有必要段。如果使用RTOS,确保任务优先级正确。 #### 4. **总结与建议** 通过以上步骤,大多数问题可解决:先硬件后软件,优先检查电源和连接。如果问题持续,示波器捕获信号是关键。优化时,参考引用[3]选择高效算法[^3]。最终,确保系统整体可靠,如机器人导航应用中的实时性[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值