This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1310PWM驱动打开失败

Other Parts Discussed in Thread: CC1310

请教大家一个问题:

我将simplelink_cc13x0_sdk_1_60_00_版本SDK中PWM例程移植到Sensor例程中,发现PWM打开失败。最终发现,程序停在了这里

pwm1 = PWM_open(Board_PWM0, &params);
if (pwm1 == NULL) {
/* Board_PWM0 did not open */
while (1);
}、

进入到pwm_open函数中调试。

/* Get handle for this driver instance */
handle = (PWM_Handle) &(PWM_config[index]);

这是handle还不为空,,但执行了下边这个,handle就变成了空。

handle = handle->fxnTablePtr->openFxn(handle, params);

请问问题出在了哪

  • handle为空的可能性有很多,是否能提供更详细描述或完整程序?另外排查一下你是否使用了其他driver及相关引脚,是否配置正确
  • 您好:

    1、我在sensor.c中定义了全局变量

    uint16_t pwmPeriod = 3000;
    uint16_t duty = 0;
    uint16_t dutyInc = 100;

    /* Sleep time in microseconds */
    uint32_t time = 50000;
    PWM_Handle pwm1 = NULL;
    PWM_Handle pwm2 = NULL;
    PWM_Params params;

    在Sensirinit()函数的最后增加了

    /* Call driver init functions. */
    PWM_init();
    PWM_Params_init(&params);
    params.dutyUnits = PWM_DUTY_US;
    params.dutyValue = 0;
    params.periodUnits = PWM_PERIOD_US;
    params.periodValue = pwmPeriod;
    pwm1 = PWM_open(CC1310_LAUNCHXL_PWM0, &params);
    if (pwm1 == NULL) {
    /* Board_PWM0 did not open */
    while (1);
    }

    PWM_start(pwm1);

    PWM接的IO接的是LED, 对应5*5封装IOID_9。其余管脚配置为PIN_UNASSIGNED

    /* PWM Outputs */
    #define CC1310_LAUNCHXL_PWMPIN0     IOID_9
    #define CC1310_LAUNCHXL_PWMPIN1     PIN_UNASSIGNED
    #define CC1310_LAUNCHXL_PWMPIN2     PIN_UNASSIGNED
    #define CC1310_LAUNCHXL_PWMPIN3     PIN_UNASSIGNED
    #define CC1310_LAUNCHXL_PWMPIN4     PIN_UNASSIGNED
    #define CC1310_LAUNCHXL_PWMPIN5     PIN_UNASSIGNED
    #define CC1310_LAUNCHXL_PWMPIN6     PIN_UNASSIGNED
    #define CC1310_LAUNCHXL_PWMPIN7     PIN_UNASSIGNED

    2、其他的driver我用到了UART,对应的IO是0 和 1,没有和PWM冲突,UART之前一直在用,没问题。这次只是增加了PWM。

  • 你单独在测试PWM时时正常的对吧?
    你有按照你pwm的demo的板级文件去配置你sensor的板级文件?
  • 您好:
    我移植了board.h 和CC1310LAUNCHXL的.c和.h文件,但只是移植了PWM对应的部分。
  • 5x5 io没那么多,你对应手册把IO设置一下试试。
  • 您好:
    IO的配置我已改成5*5的了,而且已经跑通了。没用的IO已全部注释掉,现在是有一个用到PWM的需求。所以加上了这个
  • pwm1 = PWM_open(Board_PWM0, &params);
    设置为上面这样试试,CC1310LAUNCHXL.c中改一下io就可以。
  • Hello,

    你如果向修改IO

    就在CC1310LAUNCHXL.c 修改。

    /* PWM Outputs */

    #define CC1310_LAUNCHXL_PWMPIN0               CC1310_LAUNCHXL_PIN_RLED

    #define CC1310_LAUNCHXL_PWMPIN1               CC1310_LAUNCHXL_PIN_GLED

    代码和侧视图:

    sensor.c
    /******************************************************************************
    
     @file sensor.c
    
     @brief TIMAC 2.0 Sensor Example Application
    
     Group: WCS LPC
     $Target Device: DEVICES $
    
     ******************************************************************************
     $License: BSD3 2016 $
     ******************************************************************************
     $Release Name: PACKAGE NAME $
     $Release Date: PACKAGE RELEASE DATE $
     *****************************************************************************/
    
    /******************************************************************************
     Includes
     *****************************************************************************/
    #include <string.h>
    #include <stdint.h>
    #include "mac_util.h"
    #include "api_mac.h"
    #include "jdllc.h"
    #include "ssf.h"
    #include "smsgs.h"
    #include "sensor.h"
    #include "config.h"
    #include "board_led.h"
    /* Driver Header files */
    #include <ti/drivers/PWM.h>
    #ifdef FEATURE_NATIVE_OAD
    #include "oad_client.h"
    #endif /* FEATURE_NATIVE_OAD */
    
    #ifdef OSAL_PORT2TIRTOS
    #include <ti/sysbios/knl/Clock.h>
    #else
    #include "icall.h"
    #endif
    /******************************************************************************
     Constants and definitions
     *****************************************************************************/
    
    #if !defined(CONFIG_AUTO_START)
    #if defined(AUTO_START)
    #define CONFIG_AUTO_START 1
    #else
    #define CONFIG_AUTO_START 0
    #endif
    #endif
    
    /* default MSDU Handle rollover */
    #define MSDU_HANDLE_MAX 0x1F
    
    /* App marker in MSDU handle */
    #define APP_MARKER_MSDU_HANDLE 0x80
    
    /* App Message Tracking Mask */
    #define APP_MASK_MSDU_HANDLE 0x60
    
    /* App Sensor Data marker for the MSDU handle */
    #define APP_SENSOR_MSDU_HANDLE 0x40
    
    /* App tracking response marker for the MSDU handle */
    #define APP_TRACKRSP_MSDU_HANDLE 0x20
    
    /* App config response marker for the MSDU handle */
    #define APP_CONFIGRSP_MSDU_HANDLE 0x60
    
    /* Reporting Interval Min and Max (in milliseconds) */
    #define MIN_REPORTING_INTERVAL 1000
    #define MAX_REPORTING_INTERVAL 360000
    
    /* Polling Interval Min and Max (in milliseconds) */
    #define MIN_POLLING_INTERVAL 1000
    #define MAX_POLLING_INTERVAL 10000
    
    /* Blink Time for Identify LED Request (in milliseconds) */
    #define IDENTIFY_LED_TIME 1000
    
    /* Inter packet interval in certification test mode */
    #if CERTIFICATION_TEST_MODE
    #if ((CONFIG_PHY_ID >= APIMAC_MRFSK_STD_PHY_ID_BEGIN) && (CONFIG_PHY_ID <= APIMAC_MRFSK_GENERIC_PHY_ID_BEGIN))
    /*! Regular Mode */
    #define SENSOR_TEST_RAMP_DATA_SIZE   75
    #define CERT_MODE_INTER_PKT_INTERVAL 50
    #elif ((CONFIG_PHY_ID >= APIMAC_MRFSK_GENERIC_PHY_ID_BEGIN + 1) && (CONFIG_PHY_ID <= APIMAC_MRFSK_GENERIC_PHY_ID_END))
    /*! LRM Mode */
    #define SENSOR_TEST_RAMP_DATA_SIZE   20
    #define CERT_MODE_INTER_PKT_INTERVAL 300
    #else
    #error "PHY ID is wrong."
    #endif
    #endif
    
    /******************************************************************************
     Global variables
     *****************************************************************************/
    
    /* Task pending events */
    uint16_t Sensor_events = 0;
    
    /*! Sensor statistics */
    Smsgs_msgStatsField_t Sensor_msgStats =
        { 0 };
    extern bool initBroadcastMsg;
    extern bool parentFound;
    #ifdef POWER_MEAS
    /*! Power Meas Stats fields */
    Smsgs_powerMeastatsField_t Sensor_pwrMeasStats =
        { 0 };
    #endif
    /******************************************************************************
     Local variables
     *****************************************************************************/
    
    static void *sem;
    
    /*! Rejoined flag */
    static bool rejoining = false;
    
    /*! Collector's address */
    static ApiMac_sAddr_t collectorAddr = {0};
    
    /* Join Time Ticks (used for average join time calculations) */
    static uint_fast32_t joinTimeTicks = 0;
    
    /* End to end delay statistics timestamp */
    static uint32_t startSensorMsgTimeStamp = 0;
    
    /*! Device's Outgoing MSDU Handle values */
    STATIC uint8_t deviceTxMsduHandle = 0;
    
    STATIC Smsgs_configReqMsg_t configSettings;
    
    /*!
     Temp Sensor field - valid only if Smsgs_dataFields_tempSensor
     is set in frameControl.
     */
    STATIC Smsgs_tempSensorField_t tempSensor =
        { 0 };
    
    /*!
     Light Sensor field - valid only if Smsgs_dataFields_lightSensor
     is set in frameControl.
     */
    STATIC Smsgs_lightSensorField_t lightSensor =
        { 0 };
    
    /*!
     Humidity Sensor field - valid only if Smsgs_dataFields_humiditySensor
     is set in frameControl.
     */
    STATIC Smsgs_humiditySensorField_t humiditySensor =
        { 0 };
    
    STATIC Llc_netInfo_t parentInfo = {0};
    
    STATIC uint16_t lastRcvdBroadcastMsgId = 0;
    /******************************************************************************
     Local function prototypes
     *****************************************************************************/
    static void initializeClocks(void);
    static void dataCnfCB(ApiMac_mcpsDataCnf_t *pDataCnf);
    static void dataIndCB(ApiMac_mcpsDataInd_t *pDataInd);
    static uint8_t getMsduHandle(Smsgs_cmdIds_t msgType);
    static void processSensorMsgEvt(void);
    #if SENSOR_TEST_RAMP_DATA_SIZE
    static void processSensorRampMsgEvt(void);
    #endif
    static bool sendSensorMessage(ApiMac_sAddr_t *pDstAddr,
                                  Smsgs_sensorMsg_t *pMsg);
    static void processConfigRequest(ApiMac_mcpsDataInd_t *pDataInd);
    static void processBroadcastCtrlMsg(ApiMac_mcpsDataInd_t *pDataInd);
    static bool sendConfigRsp(ApiMac_sAddr_t *pDstAddr, Smsgs_configRspMsg_t *pMsg);
    static uint16_t validateFrameControl(uint16_t frameControl);
    
    static void jdllcJoinedCb(ApiMac_deviceDescriptor_t *pDevInfo,
                              Llc_netInfo_t  *pStartedInfo);
    static void jdllcDisassocIndCb(ApiMac_sAddrExt_t *extAddress,
                                   ApiMac_disassocateReason_t reason);
    static void jdllcDisassocCnfCb(ApiMac_sAddrExt_t *extAddress,
                                   ApiMac_status_t status);
    static void jdllcStateChangeCb(Jdllc_states_t state);
    static void readSensors(void);
    /* Example/Board Header files */
    #include "Board.h"
    
    void PWM_Test(void);
    /******************************************************************************
     Callback tables
     *****************************************************************************/
    
    /*! API MAC Callback table */
    STATIC ApiMac_callbacks_t Sensor_macCallbacks =
        {
          /*! Associate Indicated callback */
          NULL,
          /*! Associate Confirmation callback */
          NULL,
          /*! Disassociate Indication callback */
          NULL,
          /*! Disassociate Confirmation callback */
          NULL,
          /*! Beacon Notify Indication callback */
          NULL,
          /*! Orphan Indication callback */
          NULL,
          /*! Scan Confirmation callback */
          NULL,
          /*! Start Confirmation callback */
          NULL,
          /*! Sync Loss Indication callback */
          NULL,
          /*! Poll Confirm callback */
          NULL,
          /*! Comm Status Indication callback */
          NULL,
          /*! Poll Indication Callback */
          NULL,
          /*! Data Confirmation callback */
          dataCnfCB,
          /*! Data Indication callback */
          dataIndCB,
          /*! Purge Confirm callback */
          NULL,
          /*! WiSUN Async Indication callback */
          NULL,
          /*! WiSUN Async Confirmation callback */
          NULL,
          /*! Unprocessed message callback */
          NULL
        };
    
    STATIC Jdllc_callbacks_t jdllcCallbacks =
        {
          /*! Network Joined Indication callback */
          jdllcJoinedCb,
          /* Disassociation Indication callback */
          jdllcDisassocIndCb,
          /* Disassociation Confirm callback */
          jdllcDisassocCnfCb,
          /*! State Changed indication callback */
          jdllcStateChangeCb
        };
    
    /******************************************************************************
     Public Functions
     *****************************************************************************/
    
    /*!
     Initialize this application.
    
     Public function defined in sensor.h
     */
    #ifdef OSAL_PORT2TIRTOS
    void Sensor_init(uint8_t macTaskId)
    #else
    void Sensor_init(void)
    #endif
    {
        PWM_Test();
        uint32_t frameCounter = 0;
    
        /* Initialize the sensor's structures */
        memset(&configSettings, 0, sizeof(Smsgs_configReqMsg_t));
    #if defined(TEMP_SENSOR)
        configSettings.frameControl |= Smsgs_dataFields_tempSensor;
    #endif
    #if defined(LIGHT_SENSOR)
        configSettings.frameControl |= Smsgs_dataFields_lightSensor;
    #endif
    #if defined(HUMIDITY_SENSOR)
        configSettings.frameControl |= Smsgs_dataFields_humiditySensor;
    #endif
        configSettings.frameControl |= Smsgs_dataFields_msgStats;
        configSettings.frameControl |= Smsgs_dataFields_configSettings;
    
        if(!CERTIFICATION_TEST_MODE)
        {
            configSettings.reportingInterval = CONFIG_REPORTING_INTERVAL;
        }
        else
        {
            /* start back to back data transmission at the earliest */
            configSettings.reportingInterval = 100;
        }
        configSettings.pollingInterval = CONFIG_POLLING_INTERVAL;
    
        /* Initialize the MAC */
    #ifdef OSAL_PORT2TIRTOS
        sem = ApiMac_init(macTaskId, CONFIG_FH_ENABLE);
    #else
        sem = ApiMac_init(CONFIG_FH_ENABLE);
    #endif
    
        /* Initialize the Joining Device Logical Link Controller */
        Jdllc_init(&Sensor_macCallbacks, &jdllcCallbacks);
    
        /* Register the MAC Callbacks */
        ApiMac_registerCallbacks(&Sensor_macCallbacks);
    
        /* Initialize the platform specific functions */
        Ssf_init(sem);
    
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_phyCurrentDescriptorId,
                               (uint8_t)CONFIG_PHY_ID);
    
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_channelPage,
                               (uint8_t)CONFIG_CHANNEL_PAGE);
    
        Ssf_getFrameCounter(NULL, &frameCounter);
    
    #ifdef FEATURE_MAC_SECURITY
        /* Initialize the MAC Security */
        Jdllc_securityInit(frameCounter);
    #endif /* FEATURE_MAC_SECURITY */
    
        /* Set the transmit power */
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_phyTransmitPowerSigned,
                               (uint8_t)CONFIG_TRANSMIT_POWER);
        /* Set Min BE */
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_backoffExponent,
                                  (uint8_t)CONFIG_MIN_BE);
        /* Set Max BE */
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxBackoffExponent,
                                  (uint8_t)CONFIG_MAX_BE);
        /* Set MAC MAX CSMA Backoffs */
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxCsmaBackoffs,
                                  (uint8_t)CONFIG_MAC_MAX_CSMA_BACKOFFS);
        /* Set MAC MAX Frame Retries */
        ApiMac_mlmeSetReqUint8(ApiMac_attribute_maxFrameRetries,
                                  (uint8_t)CONFIG_MAX_RETRIES);
    #ifdef FCS_TYPE16
        /* Set the fcs type */
        ApiMac_mlmeSetReqBool(ApiMac_attribute_fcsType,
                               (bool)1);
    #endif
        /* Initialize the app clocks */
        initializeClocks();
    
        if(CONFIG_AUTO_START)
        {
            /* Start the device */
            Util_setEvent(&Sensor_events, SENSOR_START_EVT);
        }
    }
    
    /*!
     Application task processing.
    
     Public function defined in sensor.h
     */
    void Sensor_process(void)
    {
        /* Start the collector device in the network */
        if(Sensor_events & SENSOR_START_EVT)
        {
            ApiMac_deviceDescriptor_t devInfo;
            Llc_netInfo_t parentInfo;
    
            if(Ssf_getNetworkInfo(&devInfo, &parentInfo ) == true)
            {
                Ssf_configSettings_t configInfo;
    #ifdef FEATURE_MAC_SECURITY
                ApiMac_status_t stat;
    #endif /* FEATURE_MAC_SECURITY */
    
                /* Do we have config settings? */
                if(Ssf_getConfigInfo(&configInfo) == true)
                {
                    /* Save the config information */
                    configSettings.frameControl = configInfo.frameControl;
                    configSettings.reportingInterval = configInfo.reportingInterval;
                    configSettings.pollingInterval = configInfo.pollingInterval;
    
                    /* Update the polling interval in the LLC */
                    Jdllc_setPollRate(configSettings.pollingInterval);
                }
    
                /* Initially, setup the parent as the collector */
                if(parentInfo.fh == true && CONFIG_RX_ON_IDLE)
                {
                    collectorAddr.addrMode = ApiMac_addrType_extended;
                    memcpy(&collectorAddr.addr.extAddr,
                           parentInfo.devInfo.extAddress, APIMAC_SADDR_EXT_LEN);
                }
                else
                {
                    collectorAddr.addrMode = ApiMac_addrType_short;
                    collectorAddr.addr.shortAddr = parentInfo.devInfo.shortAddress;
                }
    
    #ifdef FEATURE_MAC_SECURITY
                /* Put the parent in the security device list */
                stat = Jdllc_addSecDevice(parentInfo.devInfo.panID,
                                          parentInfo.devInfo.shortAddress,
                                          &parentInfo.devInfo.extAddress, 0);
                if(stat != ApiMac_status_success)
                {
                    Ssf_displayError("Auth Error: 0x", (uint8_t)stat);
                }
    #endif /* FEATURE_MAC_SECURITY */
    
                Jdllc_rejoin(&devInfo, &parentInfo);
                rejoining = true;
            }
            else
            {
                /* Get Start Timestamp */
    #ifdef OSAL_PORT2TIRTOS
                joinTimeTicks = Clock_getTicks();
    #else
                joinTimeTicks = ICall_getTicks();
    #endif
                Jdllc_join();
            }
    
            /* Clear the event */
            Util_clearEvent(&Sensor_events, SENSOR_START_EVT);
        }
    
        /* Is it time to send the next sensor data message? */
        if(Sensor_events & SENSOR_READING_TIMEOUT_EVT)
        {
            /* In certification test mode, back to back data shall be sent */
            if(!CERTIFICATION_TEST_MODE)
            {
                /* Setup for the next message */
                Ssf_setReadingClock(configSettings.reportingInterval);
            }
    
    
    #if SENSOR_TEST_RAMP_DATA_SIZE
            processSensorRampMsgEvt();
    #else
            /* Read sensors */
            readSensors();
    
            /* Process Sensor Reading Message Event */
            processSensorMsgEvt();
    #endif
    
            /* Clear the event */
            Util_clearEvent(&Sensor_events, SENSOR_READING_TIMEOUT_EVT);
        }
    
    #ifdef DISPLAY_PER_STATS
        if(Sensor_events & SENSOR_UPDATE_STATS_EVT)
        {
            Ssf_displayPerStats(&Sensor_msgStats);
            /* Clear the event */
            Util_clearEvent(&Sensor_events, SENSOR_UPDATE_STATS_EVT);
        }
    #endif /* DISPLAY_PER_STATS */
    
        /* Process LLC Events */
        Jdllc_process();
    
        /* Allow the Specific functions to process */
        Ssf_processEvents();
    
        /*
         Don't process ApiMac messages until all of the sensor events
         are processed.
         */
        if(Sensor_events == 0)
        {
            /* Wait for response message or events */
            ApiMac_processIncoming();
        }
    }
    
    /*!
     * @brief   Send MAC data request
     *
     * @param   type - message type
     * @param   pDstAddr - destination address
     * @param   rxOnIdle - true if not a sleepy device
     * @param   len - length of payload
     * @param   pData - pointer to the buffer
     *
     * @return  true if sent, false if not
     */
    bool Sensor_sendMsg(Smsgs_cmdIds_t type, ApiMac_sAddr_t *pDstAddr,
                        bool rxOnIdle, uint16_t len, uint8_t *pData)
    {
        bool ret = false;
        ApiMac_mcpsDataReq_t dataReq;
    
        /* Timestamp to compute end to end delay */
    #ifdef OSAL_PORT2TIRTOS
        startSensorMsgTimeStamp = Clock_getTicks();
    #else
        startSensorMsgTimeStamp = ICall_getTicks();
    #endif
        /* Fill the data request field */
        memset(&dataReq, 0, sizeof(ApiMac_mcpsDataReq_t));
    
        memcpy(&dataReq.dstAddr, pDstAddr, sizeof(ApiMac_sAddr_t));
    
        if(pDstAddr->addrMode == ApiMac_addrType_extended)
        {
            dataReq.srcAddrMode = ApiMac_addrType_extended;
        }
        else
        {
            dataReq.srcAddrMode = ApiMac_addrType_short;
        }
    
        if(rejoining == true)
        {
            ApiMac_mlmeGetReqUint16(ApiMac_attribute_panId,
                                    &(parentInfo.devInfo.panID));
        }
    
        dataReq.dstPanId = parentInfo.devInfo.panID;
    
        dataReq.msduHandle = getMsduHandle(type);
    
        dataReq.txOptions.ack = true;
    
        if(CERTIFICATION_TEST_MODE)
        {
            dataReq.txOptions.ack = false;
        }
    
        if(rxOnIdle == false)
        {
            dataReq.txOptions.indirect = true;
        }
    
        dataReq.msdu.len = len;
        dataReq.msdu.p = pData;
    
    #ifdef FEATURE_MAC_SECURITY
        Jdllc_securityFill(&dataReq.sec);
    #endif /* FEATURE_MAC_SECURITY */
    
        if(type == Smsgs_cmdIds_sensorData || type == Smsgs_cmdIds_rampdata)
        {
            Sensor_msgStats.msgsAttempted++;
        }
        else if(type == Smsgs_cmdIds_trackingRsp)
        {
            Sensor_msgStats.trackingResponseAttempts++;
        }
        else if(type == Smsgs_cmdIds_configRsp)
        {
            Sensor_msgStats.configResponseAttempts++;
        }
    
        /* Send the message */
        if(ApiMac_mcpsDataReq(&dataReq) == ApiMac_status_success)
        {
            ret = true;
        }
        else
        {
            /* handle transaction overflow by retrying */
            if(type == Smsgs_cmdIds_sensorData || type == Smsgs_cmdIds_rampdata)
            {
                Ssf_setReadingClock(configSettings.reportingInterval);
                Sensor_msgStats.msgsAttempted++;
            }
        }
    
        return (ret);
    }
    
    
    #ifdef IDENTIFY_LED
    /*!
     Send LED Identify Request to collector
    
     Public function defined in sensor.h
     */
    void Sensor_sendIdentifyLedRequest(void)
    {
        uint8_t cmdBytes[SMSGS_INDENTIFY_LED_REQUEST_MSG_LEN];
    
        /* send the response message directly */
        cmdBytes[0] = (uint8_t) Smsgs_cmdIds_IdentifyLedReq;
        cmdBytes[1] = (uint8_t) IDENTIFY_LED_TIME;
        Sensor_sendMsg(Smsgs_cmdIds_IdentifyLedReq,
                &collectorAddr, true,
                SMSGS_INDENTIFY_LED_REQUEST_MSG_LEN,
                cmdBytes);
    }
    #endif
    /******************************************************************************
     Local Functions
     *****************************************************************************/
    
    /*!
     * @brief       Initialize the clocks.
     */
    static void initializeClocks(void)
    {
        /* Initialize the reading clock */
        Ssf_initializeReadingClock();
    }
    
    /*!
     * @brief      MAC Data Confirm callback.
     *
     * @param      pDataCnf - pointer to the data confirm information
     */
    static void dataCnfCB(ApiMac_mcpsDataCnf_t *pDataCnf)
    {
        uint16_t endToEndDelay = 0;
        /* Record statistics */
        if(pDataCnf->status == ApiMac_status_channelAccessFailure)
        {
            Sensor_msgStats.channelAccessFailures++;
        }
        else if(pDataCnf->status == ApiMac_status_noAck)
        {
            Sensor_msgStats.macAckFailures++;
    #ifdef DISPLAY_PER_STATS
            Util_setEvent(&Sensor_events, SENSOR_UPDATE_STATS_EVT);
    #endif
        }
        else if(pDataCnf->status != ApiMac_status_success)
        {
            Sensor_msgStats.otherDataRequestFailures++;
    #ifdef DISPLAY_PER_STATS
            Util_setEvent(&Sensor_events, SENSOR_UPDATE_STATS_EVT);
    #endif
            Ssf_displayError("dataCnf: ", pDataCnf->status);
        }
        else if(pDataCnf->status == ApiMac_status_success)
        {
            Ssf_updateFrameCounter(NULL, pDataCnf->frameCntr);
        }
    
        /* Make sure the message came from the app */
        if(pDataCnf->msduHandle & APP_MARKER_MSDU_HANDLE)
        {
            /* What message type was the original request? */
            if((pDataCnf->msduHandle & APP_MASK_MSDU_HANDLE)
               == APP_SENSOR_MSDU_HANDLE)
            {
                if(pDataCnf->status == ApiMac_status_success)
                {
                    Sensor_msgStats.msgsSent++;
    #ifdef DISPLAY_PER_STATS
                    Util_setEvent(&Sensor_events, SENSOR_UPDATE_STATS_EVT);
    #endif
                    /* Calculate end to end delay */
    #ifdef OSAL_PORT2TIRTOS
                    if(Clock_getTicks() < startSensorMsgTimeStamp)
                    {
                        endToEndDelay = Clock_getTicks() +
                                        (0xFFFFFFFF-startSensorMsgTimeStamp);
                    }
                    else
                    {
                        endToEndDelay = Clock_getTicks() - startSensorMsgTimeStamp;
                    }
    #else
                    if(ICall_getTicks() < startSensorMsgTimeStamp)
                    {
                        endToEndDelay = ICall_getTicks() +
                                        (0xFFFFFFFF-startSensorMsgTimeStamp);
                    }
                    else
                    {
                        endToEndDelay = ICall_getTicks() - startSensorMsgTimeStamp;
                    }
    #endif
                    endToEndDelay = endToEndDelay/TICKPERIOD_MS_US;
    
                    Sensor_msgStats.worstCaseE2EDelay =
                       (Sensor_msgStats.worstCaseE2EDelay > endToEndDelay) ?
                        Sensor_msgStats.worstCaseE2EDelay:endToEndDelay;
                    Sensor_msgStats.avgE2EDelay =
                        (((uint32_t)Sensor_msgStats.avgE2EDelay *
                          (Sensor_msgStats.msgsSent - 1)) + endToEndDelay)/
                         Sensor_msgStats.msgsSent;
    
                }
    
    
    #if CERTIFICATION_TEST_MODE
                {
                    /* Setup for the next message */
                    Ssf_setReadingClock(CERT_MODE_INTER_PKT_INTERVAL);
                }
    #endif
            }
            if((pDataCnf->msduHandle & APP_MASK_MSDU_HANDLE)
               == APP_TRACKRSP_MSDU_HANDLE)
            {
                if(pDataCnf->status == ApiMac_status_success)
                {
                    Sensor_msgStats.trackingResponseSent++;
                }
            }
            if((pDataCnf->msduHandle & APP_MASK_MSDU_HANDLE)
               == APP_CONFIGRSP_MSDU_HANDLE)
            {
                if(pDataCnf->status == ApiMac_status_success)
                {
                    Sensor_msgStats.configResponseSent++;
                }
            }
        }
    }
    
    /*!
     * @brief      MAC Data Indication callback.
     *
     * @param      pDataInd - pointer to the data indication information
     */
    static void dataIndCB(ApiMac_mcpsDataInd_t *pDataInd)
    {
        uint8_t cmdBytes[SMSGS_TOGGLE_LED_RESPONSE_MSG_LEN];
    
        if((pDataInd != NULL) && (pDataInd->msdu.p != NULL)
           && (pDataInd->msdu.len > 0))
        {
            Smsgs_cmdIds_t cmdId = (Smsgs_cmdIds_t)*(pDataInd->msdu.p);
    
    #ifdef FEATURE_MAC_SECURITY
            {
                if(Jdllc_securityCheck(&(pDataInd->sec)) == false)
                {
                    /* reject the message */
                    return;
                }
            }
    #endif /* FEATURE_MAC_SECURITY */
    
            switch(cmdId)
            {
                case Smsgs_cmdIds_configReq:
                    processConfigRequest(pDataInd);
                    Sensor_msgStats.configRequests++;
                    break;
    
                case Smsgs_cmdIds_trackingReq:
                    /* Make sure the message is the correct size */
                    if(pDataInd->msdu.len == SMSGS_TRACKING_REQUEST_MSG_LENGTH)
                    {
                        /* Update stats */
                        Sensor_msgStats.trackingRequests++;
    
                        /* Indicate tracking message received */
                        Ssf_trackingUpdate(&pDataInd->srcAddr);
    
                        /* send the response message directly */
                        cmdBytes[0] = (uint8_t) Smsgs_cmdIds_trackingRsp;
                        Sensor_sendMsg(Smsgs_cmdIds_trackingRsp,
                                &pDataInd->srcAddr, true,
                                1, cmdBytes);
                    }
                    break;
    
                case Smsgs_cmdIds_toggleLedReq:
                    /* Make sure the message is the correct size */
                    if(pDataInd->msdu.len == SMSGS_TOGGLE_LED_REQUEST_MSG_LEN)
                    {
    
                        /* send the response message directly */
                        cmdBytes[0] = (uint8_t) Smsgs_cmdIds_toggleLedRsp;
                        cmdBytes[1] = Ssf_toggleLED();
                        Sensor_sendMsg(Smsgs_cmdIds_toggleLedRsp,
                                &pDataInd->srcAddr, true,
                                SMSGS_TOGGLE_LED_RESPONSE_MSG_LEN,
                                cmdBytes);
                    }
                    break;
    
                case Smgs_cmdIds_broadcastCtrlMsg:
                    if(parentFound)
                    {
                        /* Node has successfully associated with the network */
                        processBroadcastCtrlMsg(pDataInd);
                    }
                    break;
    #ifdef POWER_MEAS
                case Smsgs_cmdIds_rampdata:
                    Sensor_pwrMeasStats.rampDataRcvd++;
                    break;
    #endif
    
    #ifdef FEATURE_NATIVE_OAD
                case Smsgs_cmdIds_oad:
                    //Index past the Smsgs_cmdId
                    OADProtocol_ParseIncoming((void*) &(pDataInd->srcAddr), pDataInd->msdu.p + 1);
                    break;
    #endif //FEATURE_NATIVE_OAD
    
                default:
                    /* Should not receive other messages */
                    break;
            }
        }
    }
    
    /*!
     * @brief      Get the next MSDU Handle
     *             <BR>
     *             The MSDU handle has 3 parts:<BR>
     *             - The MSBit(7), when set means the the application sent the
     *               message
     *             - Bit 6, when set means that the app message is a config request
     *             - Bits 0-5, used as a message counter that rolls over.
     *
     * @param      msgType - message command id needed
     *
     * @return     msdu Handle
     */
    static uint8_t getMsduHandle(Smsgs_cmdIds_t msgType)
    {
        uint8_t msduHandle = deviceTxMsduHandle;
    
        /* Increment for the next msdu handle, or roll over */
        if(deviceTxMsduHandle >= MSDU_HANDLE_MAX)
        {
            deviceTxMsduHandle = 0;
        }
        else
        {
            deviceTxMsduHandle++;
        }
    
        /* Add the App specific bit */
        msduHandle |= APP_MARKER_MSDU_HANDLE;
    
        /* Add the message type bit */
        if(msgType == Smsgs_cmdIds_sensorData || msgType == Smsgs_cmdIds_rampdata)
        {
            msduHandle |= APP_SENSOR_MSDU_HANDLE;
        }
        else if(msgType == Smsgs_cmdIds_trackingRsp)
        {
            msduHandle |= APP_TRACKRSP_MSDU_HANDLE;
        }
        else if(msgType == Smsgs_cmdIds_configRsp)
        {
            msduHandle |= APP_CONFIGRSP_MSDU_HANDLE;
        }
    
        return (msduHandle);
    }
    
    /*!
     @brief  Build and send fixed size ramp data
     */
    #if SENSOR_TEST_RAMP_DATA_SIZE
    static void processSensorRampMsgEvt(void)
    {
        uint8_t *pMsgBuf;
        uint16_t index;
    
        pMsgBuf = (uint8_t *)Ssf_malloc(SENSOR_TEST_RAMP_DATA_SIZE);
        if(pMsgBuf)
        {
            uint8_t *pBuf = pMsgBuf;
            *pBuf++ = (uint8_t)Smsgs_cmdIds_rampdata;
            for(index = 1; index < SENSOR_TEST_RAMP_DATA_SIZE; index++)
            {
                *pBuf++ = (uint8_t) (index & 0xFF);
            }
    
    #ifndef POWER_MEAS
            Board_Led_toggle(board_led_type_LED2);
    #endif
    
            Sensor_sendMsg(Smsgs_cmdIds_rampdata, &collectorAddr, true,
                    SENSOR_TEST_RAMP_DATA_SIZE, pMsgBuf);
    
            Ssf_free(pMsgBuf);
        }
    
    }
    #endif
    
    /*!
     @brief   Build and send sensor data message
     */
    static void processSensorMsgEvt(void)
    {
        Smsgs_sensorMsg_t sensor;
        uint32_t stat;
    
        memset(&sensor, 0, sizeof(Smsgs_sensorMsg_t));
    
        ApiMac_mlmeGetReqUint32(ApiMac_attribute_diagRxSecureFail, &stat);
        Sensor_msgStats.rxDecryptFailures = (uint16_t)stat;
    
        ApiMac_mlmeGetReqUint32(ApiMac_attribute_diagTxSecureFail, &stat);
        Sensor_msgStats.txEncryptFailures = (uint16_t)stat;
    
        ApiMac_mlmeGetReqArray(ApiMac_attribute_extendedAddress,
        		               sensor.extAddress);
    
        /* fill in the message */
        sensor.frameControl = configSettings.frameControl;
        if(sensor.frameControl & Smsgs_dataFields_tempSensor)
        {
            memcpy(&sensor.tempSensor, &tempSensor,
                   sizeof(Smsgs_tempSensorField_t));
        }
        if(sensor.frameControl & Smsgs_dataFields_lightSensor)
        {
            memcpy(&sensor.lightSensor, &lightSensor,
                   sizeof(Smsgs_lightSensorField_t));
        }
        if(sensor.frameControl & Smsgs_dataFields_humiditySensor)
        {
            memcpy(&sensor.humiditySensor, &humiditySensor,
                   sizeof(Smsgs_humiditySensorField_t));
        }
        if(sensor.frameControl & Smsgs_dataFields_msgStats)
        {
            memcpy(&sensor.msgStats, &Sensor_msgStats,
                   sizeof(Smsgs_msgStatsField_t));
        }
        if(sensor.frameControl & Smsgs_dataFields_configSettings)
        {
            sensor.configSettings.pollingInterval = configSettings.pollingInterval;
            sensor.configSettings.reportingInterval = configSettings
                            .reportingInterval;
        }
    
        /* inform the user interface */
        Ssf_sensorReadingUpdate(&sensor);
    
        /* send the data to the collector */
        sendSensorMessage(&collectorAddr, &sensor);
    }
    
    /*!
     * @brief   Build and send sensor data message
     *
     * @param   pDstAddr - Where to send the message
     * @param   pMsg - pointer to the sensor data
     *
     * @return  true if message was sent, false if not
     */
    static bool sendSensorMessage(ApiMac_sAddr_t *pDstAddr, Smsgs_sensorMsg_t *pMsg)
    {
        bool ret = false;
        uint8_t *pMsgBuf;
        uint16_t len = SMSGS_BASIC_SENSOR_LEN;
    
        /* Figure out the length */
        if(pMsg->frameControl & Smsgs_dataFields_tempSensor)
        {
            len += SMSGS_SENSOR_TEMP_LEN;
        }
        if(pMsg->frameControl & Smsgs_dataFields_lightSensor)
        {
            len += SMSGS_SENSOR_LIGHT_LEN;
        }
        if(pMsg->frameControl & Smsgs_dataFields_humiditySensor)
        {
            len += SMSGS_SENSOR_HUMIDITY_LEN;
        }
        if(pMsg->frameControl & Smsgs_dataFields_msgStats)
        {
            //len += SMSGS_SENSOR_MSG_STATS_LEN;
            len += sizeof(Smsgs_msgStatsField_t);
        }
        if(pMsg->frameControl & Smsgs_dataFields_configSettings)
        {
            len += SMSGS_SENSOR_CONFIG_SETTINGS_LEN;
        }
    
        pMsgBuf = (uint8_t *)Ssf_malloc(len);
        if(pMsgBuf)
        {
            uint8_t *pBuf = pMsgBuf;
    
            *pBuf++ = (uint8_t)Smsgs_cmdIds_sensorData;
    
            memcpy(pBuf, pMsg->extAddress, SMGS_SENSOR_EXTADDR_LEN);
            pBuf += SMGS_SENSOR_EXTADDR_LEN;
    
            pBuf  = Util_bufferUint16(pBuf,pMsg->frameControl);
    
            /* Buffer data in order of frameControl mask, starting with LSB */
            if(pMsg->frameControl & Smsgs_dataFields_tempSensor)
            {
                pBuf = Util_bufferUint16(pBuf, pMsg->tempSensor.ambienceTemp);
                pBuf = Util_bufferUint16(pBuf, pMsg->tempSensor.objectTemp);
            }
            if(pMsg->frameControl & Smsgs_dataFields_lightSensor)
            {
                pBuf = Util_bufferUint16(pBuf, pMsg->lightSensor.rawData);
            }
            if(pMsg->frameControl & Smsgs_dataFields_humiditySensor)
            {
                pBuf = Util_bufferUint16(pBuf, pMsg->humiditySensor.temp);
                pBuf = Util_bufferUint16(pBuf, pMsg->humiditySensor.humidity);
            }
            if(pMsg->frameControl & Smsgs_dataFields_msgStats)
            {
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.joinAttempts);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.joinFails);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.msgsAttempted);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.msgsSent);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.trackingRequests);
                pBuf = Util_bufferUint16(pBuf,
                                         pMsg->msgStats.trackingResponseAttempts);
                pBuf = Util_bufferUint16(pBuf,
                                         pMsg->msgStats.trackingResponseSent);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.configRequests);
                pBuf = Util_bufferUint16(pBuf,
                                         pMsg->msgStats.configResponseAttempts);
                pBuf = Util_bufferUint16(pBuf,
                                         pMsg->msgStats.configResponseSent);
                pBuf = Util_bufferUint16(pBuf,
                                         pMsg->msgStats.channelAccessFailures);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.macAckFailures);
                pBuf = Util_bufferUint16(pBuf,
                                         pMsg->msgStats.otherDataRequestFailures);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.syncLossIndications);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.rxDecryptFailures);
                pBuf = Util_bufferUint16(pBuf,  pMsg->msgStats.txEncryptFailures);
                pBuf = Util_bufferUint16(pBuf, Ssf_resetCount);
                pBuf = Util_bufferUint16(pBuf,  Ssf_resetReseason);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.joinTime);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.interimDelay);
                pBuf = Util_bufferUint16(pBuf, pMsg->msgStats.numBroadcastMsgRcvd);
                pBuf = Util_bufferUint16(pBuf,  pMsg->msgStats.numBroadcastMsglost);
                pBuf = Util_bufferUint16(pBuf,  pMsg->msgStats.avgE2EDelay);
                pBuf = Util_bufferUint16(pBuf,  pMsg->msgStats.worstCaseE2EDelay);
            }
            if(pMsg->frameControl & Smsgs_dataFields_configSettings)
            {
                pBuf = Util_bufferUint32(pBuf,
                                         pMsg->configSettings.reportingInterval);
                pBuf = Util_bufferUint32(pBuf,
                                         pMsg->configSettings.pollingInterval);
    
            }
    
            ret = Sensor_sendMsg(Smsgs_cmdIds_sensorData, pDstAddr, true, len, pMsgBuf);
    
            Ssf_free(pMsgBuf);
        }
    
        return (ret);
    }
    
    /*!
     * @brief      Process the Config Request message.
     *
     * @param      pDataInd - pointer to the data indication information
     */
    static void processConfigRequest(ApiMac_mcpsDataInd_t *pDataInd)
    {
        Smsgs_statusValues_t stat = Smsgs_statusValues_invalid;
        Smsgs_configRspMsg_t configRsp;
    
        memset(&configRsp, 0, sizeof(Smsgs_configRspMsg_t));
    
        /* Make sure the message is the correct size */
        if(pDataInd->msdu.len == SMSGS_CONFIG_REQUEST_MSG_LENGTH)
        {
            uint8_t *pBuf = pDataInd->msdu.p;
            uint16_t frameControl;
            uint32_t reportingInterval;
            uint32_t pollingInterval;
    
            /* Parse the message */
            configSettings.cmdId = (Smsgs_cmdIds_t)*pBuf++;
            frameControl = Util_parseUint16(pBuf);
            pBuf += 2;
            reportingInterval = Util_parseUint32(pBuf);
            pBuf += 4;
            pollingInterval = Util_parseUint32(pBuf);
    
            stat = Smsgs_statusValues_success;
            collectorAddr.addrMode = pDataInd->srcAddr.addrMode;
            if(collectorAddr.addrMode == ApiMac_addrType_short)
            {
                collectorAddr.addr.shortAddr = pDataInd->srcAddr.addr.shortAddr;
            }
            else
            {
                memcpy(collectorAddr.addr.extAddr, pDataInd->srcAddr.addr.extAddr,
                       (APIMAC_SADDR_EXT_LEN));
            }
    
            configSettings.frameControl = validateFrameControl(frameControl);
            if(configSettings.frameControl != frameControl)
            {
                stat = Smsgs_statusValues_partialSuccess;
            }
            configRsp.frameControl = configSettings.frameControl;
    
            if((reportingInterval < MIN_REPORTING_INTERVAL)
               || (reportingInterval > MAX_REPORTING_INTERVAL))
            {
                stat = Smsgs_statusValues_partialSuccess;
            }
            else
            {
    #ifndef POWER_MEAS
                configSettings.reportingInterval = reportingInterval;
    #endif
                {
                    uint32_t randomNum;
                    randomNum = ((ApiMac_randomByte() << 16) +
                                 (ApiMac_randomByte() << 8) + ApiMac_randomByte());
                    randomNum = (randomNum % reportingInterval) +
                            SENSOR_MIN_POLL_TIME;
                    Ssf_setReadingClock(randomNum);
                }
    
            }
            configRsp.reportingInterval = configSettings.reportingInterval;
    
            if((pollingInterval < MIN_POLLING_INTERVAL)
               || (pollingInterval > MAX_POLLING_INTERVAL))
            {
                stat = Smsgs_statusValues_partialSuccess;
            }
            else
            {
                configSettings.pollingInterval = pollingInterval;
                Jdllc_setPollRate(configSettings.pollingInterval);
            }
            configRsp.pollingInterval = configSettings.pollingInterval;
        }
    
        /* Send the response message */
        configRsp.cmdId = Smsgs_cmdIds_configRsp;
        configRsp.status = stat;
    
        /* Update the user */
        Ssf_configurationUpdate(&configRsp);
    
        /* Response the the source device */
        sendConfigRsp(&pDataInd->srcAddr, &configRsp);
    }
    
    /*!
     * @brief      Process the Broadcast Control Msg.
     *
     * @param      pDataInd - pointer to the data indication information
     */
    static void processBroadcastCtrlMsg(ApiMac_mcpsDataInd_t *pDataInd)
    {
        Smsgs_broadcastcmdmsg_t broadcastCmd;
    
        memset(&broadcastCmd, 0, sizeof(Smsgs_broadcastcmdmsg_t));
    
        /* Make sure the message is the correct size */
        if(pDataInd->msdu.len == SMSGS_BROADCAST_CMD_LENGTH)
        {
            uint8_t *pBuf = pDataInd->msdu.p;
            uint16_t broadcastMsgId;
    
            /* Parse the message */
            uint8_t cmdId = (Smsgs_cmdIds_t)*pBuf++;
            broadcastMsgId = Util_parseUint16(pBuf);
    
            /* Process Broadcast Command Message */
            Sensor_msgStats.numBroadcastMsgRcvd++;
    
            if(!initBroadcastMsg)
            {
                /* Not the first broadcast msg rcvdd after join or a rejoin*/
                if((broadcastMsgId - lastRcvdBroadcastMsgId) > 1)
                {
                    Sensor_msgStats.numBroadcastMsglost +=
                                    ((broadcastMsgId - lastRcvdBroadcastMsgId) -1);
                }
            }
    
            lastRcvdBroadcastMsgId = broadcastMsgId;
            /*To handle the very first broadcast msg rcvdd after join or a rejoin*/
            initBroadcastMsg = false;
    
            /* Switch On or Off LED based on broadcast Msg Id */
            if((broadcastMsgId % 2) == 0)
            {
                Ssf_OnLED();
            }
            else
            {
                Ssf_OffLED();
            }
        }
    }
    
    /*!
     * @brief   Build and send Config Response message
     *
     * @param   pDstAddr - Where to send the message
     * @param   pMsg - pointer to the Config Response
     *
     * @return  true if message was sent, false if not
     */
    static bool sendConfigRsp(ApiMac_sAddr_t *pDstAddr, Smsgs_configRspMsg_t *pMsg)
    {
        uint8_t msgBuf[SMSGS_CONFIG_RESPONSE_MSG_LENGTH];
        uint8_t *pBuf = msgBuf;
    
        *pBuf++ = (uint8_t) Smsgs_cmdIds_configRsp;
        pBuf = Util_bufferUint16(pBuf, pMsg->status);
        pBuf = Util_bufferUint16(pBuf, pMsg->frameControl);
        pBuf = Util_bufferUint32(pBuf, pMsg->reportingInterval);
        pBuf = Util_bufferUint32(pBuf, pMsg->pollingInterval);
    
        return (Sensor_sendMsg(Smsgs_cmdIds_configRsp, pDstAddr, true,
                        SMSGS_CONFIG_RESPONSE_MSG_LENGTH, msgBuf));
    }
    
    /*!
     * @brief   Filter the frameControl with readings supported by this device.
     *
     * @param   frameControl - suggested frameControl
     *
     * @return  new frame control settings supported
     */
    static uint16_t validateFrameControl(uint16_t frameControl)
    {
        uint16_t newFrameControl = 0;
    
    #if defined(TEMP_SENSOR)
        if(frameControl & Smsgs_dataFields_tempSensor)
        {
            newFrameControl |= Smsgs_dataFields_tempSensor;
        }
    #endif
    #if defined(LIGHT_SENSOR)
        if(frameControl & Smsgs_dataFields_lightSensor)
        {
            newFrameControl |= Smsgs_dataFields_lightSensor;
        }
    #endif
    #if defined(HUMIDITY_SENSOR)
        if(frameControl & Smsgs_dataFields_humiditySensor)
        {
            newFrameControl |= Smsgs_dataFields_humiditySensor;
        }
    #endif
        if(frameControl & Smsgs_dataFields_msgStats)
        {
            newFrameControl |= Smsgs_dataFields_msgStats;
        }
        if(frameControl & Smsgs_dataFields_configSettings)
        {
            newFrameControl |= Smsgs_dataFields_configSettings;
        }
    
        return (newFrameControl);
    }
    
    
    /*!
     * @brief   The device joined callback.
     *
     * @param   pDevInfo - This device's information
     * @param   pParentInfo - This is the parent's information
     */
    static void jdllcJoinedCb(ApiMac_deviceDescriptor_t *pDevInfo,
                              Llc_netInfo_t *pParentInfo)
    {
        uint32_t randomNum = 0;
    
        /* Copy the parent information */
        memcpy(&parentInfo, pParentInfo, sizeof(Llc_netInfo_t));
    
        /* Set the collector's address as the parent's address */
        if (pParentInfo->fh && CONFIG_RX_ON_IDLE)
        {
            collectorAddr.addrMode = ApiMac_addrType_extended;
            memcpy(collectorAddr.addr.extAddr, pParentInfo->devInfo.extAddress,
                   (APIMAC_SADDR_EXT_LEN));
        }
        else
        {
            collectorAddr.addrMode = ApiMac_addrType_short;
            collectorAddr.addr.shortAddr = pParentInfo->devInfo.shortAddress;
        }
    
        /* Start the reporting timer */
        if(CONFIG_FH_ENABLE)
        {
            randomNum = ((ApiMac_randomByte() << 16) +
                         (ApiMac_randomByte() << 8) + ApiMac_randomByte());
            randomNum = (randomNum % configSettings.reportingInterval) +
                        SENSOR_MIN_POLL_TIME;
            Ssf_setReadingClock(randomNum);
        }
        else
        {
           uint32_t randomNum;
           randomNum = ((ApiMac_randomByte() << 16) +
                        (ApiMac_randomByte() << 8) + ApiMac_randomByte());
           randomNum = (randomNum % configSettings.reportingInterval ) +
                       SENSOR_MIN_POLL_TIME;
           Ssf_setReadingClock(randomNum);
        }
    
        /* Inform the user of the joined information */
        Ssf_networkUpdate(rejoining, pDevInfo, pParentInfo);
    
        if((rejoining == false) && (pParentInfo->fh == false))
        {
    #ifdef FEATURE_MAC_SECURITY
            ApiMac_status_t stat;
            /* Add the parent to the security device list */
            stat = Jdllc_addSecDevice(pParentInfo->devInfo.panID,
                                      pParentInfo->devInfo.shortAddress,
                                      &pParentInfo->devInfo.extAddress, 0);
            if(stat != ApiMac_status_success)
            {
                Ssf_displayError("Auth Error: 0x", (uint8_t)stat);
            }
    #endif /* FEATURE_MAC_SECURITY */
        }
    
    #if (CONFIG_SUPERFRAME_ORDER != 15) && defined(MAC_NO_AUTO_REQ)
        /*
         * Set MAC Auto Request to false to enable multiple poll requests
         * per beacon interval
         */
        ApiMac_mlmeSetReqBool(ApiMac_attribute_autoRequest, false);
    #endif
    
    #ifdef OSAL_PORT2TIRTOS
        /* Calculate Join Time */
        if(Clock_getTicks() < joinTimeTicks)
        {
            joinTimeTicks = Clock_getTicks() + (0xFFFFFFFF-joinTimeTicks);
        }
        else
        {
            joinTimeTicks = Clock_getTicks() - joinTimeTicks;
        }
    #else
        /* Calculate Join Time */
        if(ICall_getTicks() < joinTimeTicks)
        {
            joinTimeTicks = ICall_getTicks() + (0xFFFFFFFF-joinTimeTicks);
        }
        else
        {
            joinTimeTicks = ICall_getTicks() - joinTimeTicks;
        }
    #endif
        Sensor_msgStats.joinTime = joinTimeTicks / TICKPERIOD_MS_US;
    #ifdef DISPLAY_PER_STATS
        /* clear the stats used for PER so that we start out at a
         * zeroed state
         */
        Sensor_msgStats.macAckFailures = 0;
        Sensor_msgStats.otherDataRequestFailures = 0;
        Sensor_msgStats.msgsSent = 0;
    #endif
    }
    
    /*!
     * @brief   Disassociation indication callback.
     *
     * @param   pExtAddress - extended address
     * @param   reason - reason for disassociation
     */
    static void jdllcDisassocIndCb(ApiMac_sAddrExt_t *pExtAddress,
                                   ApiMac_disassocateReason_t reason)
    {
        /* Stop the reporting timer */
        Ssf_setReadingClock(0);
        Ssf_clearNetworkInfo();
    
    #ifdef FEATURE_NATIVE_OAD
        /* OAD abort with no auto resume */
        OADClient_abort(false);
    #endif //FEATURE_NATIVE_OAD
    }
    
    /*!
     * @brief   Disassociation confirm callback to an application intiated
     *          disassociation request.
     *
     * @param   pExtAddress - extended address
     * @param   status - status of disassociation
     */
    static void jdllcDisassocCnfCb(ApiMac_sAddrExt_t *pExtAddress,
                                   ApiMac_status_t status)
    {
        /* Stop the reporting timer */
        Ssf_setReadingClock(0);
        Ssf_clearNetworkInfo();
    
    #ifdef FEATURE_NATIVE_OAD
        /* OAD abort with no auto resume */
        OADClient_abort(false);
    #endif //FEATURE_NATIVE_OAD
    }
    
    /*!
     * @brief   JDLLC state change callback.
     *
     * @param   state - new state
     */
    static void jdllcStateChangeCb(Jdllc_states_t state)
    {
    #ifdef FEATURE_NATIVE_OAD
        if( (state == Jdllc_states_joined) || (state == Jdllc_states_rejoined))
        {
    #if (CONFIG_SUPERFRAME_ORDER == 15)
            /* resume an OAD that may have aborted */
            OADClient_resume(30000);
    #else
            /* resume an OAD that may have aborted */
            OADClient_resume(60000);
    #endif
        }
        else if(state == Jdllc_states_orphan)
        {
            /* OAD abort with no auto resume */
            OADClient_abort(false);
        }
    #endif /* FEATURE_NATIVE_OAD */
    
        Ssf_stateChangeUpdate(state);
    }
    
    
    /*!
     * @brief   Manually read the sensors
     */
    static void readSensors(void)
    {
    #if defined(TEMP_SENSOR)
        /* Read the temp sensor values */
        tempSensor.ambienceTemp = Ssf_readTempSensor();
        tempSensor.objectTemp =  tempSensor.ambienceTemp;
    #endif
    }
    void PWM_Test(void)
    {
    
        /* Period and duty in microseconds */
        uint16_t   pwmPeriod = 3000;
        uint16_t   duty = 0;
        uint16_t   dutyInc = 100;
    
    
        PWM_Handle pwm1 = NULL;
        PWM_Handle pwm2 = NULL;
        PWM_Params params;
    
        /* Call driver init functions. */
        PWM_init();
    
        PWM_Params_init(&params);
        params.dutyUnits = PWM_DUTY_US;
        params.dutyValue = 0;
        params.periodUnits = PWM_PERIOD_US;
        params.periodValue = pwmPeriod;
        pwm1 = PWM_open(Board_PWM0, &params);
        if (pwm1 == NULL) {
        /* Board_PWM0 did not open */
            while (1);
        }
    
        PWM_start(pwm1);
    
        pwm2 = PWM_open(Board_PWM1, &params);
        if (pwm2 == NULL) {
        /* Board_PWM0 did not open */
            while (1);
        }
    
        PWM_start(pwm2);
    
        /* Loop forever incrementing the PWM duty */
           while (1) {
               PWM_setDuty(pwm1, duty);
    
               PWM_setDuty(pwm2, duty);
    
               duty = (duty + dutyInc);
    
               if (duty == pwmPeriod || (!duty)) {
                   dutyInc = - dutyInc;
               }
    
    
           }
    }
    

  • 非常感谢您的回答:

    您说的CC1310LAUNCHXL.c中修改,我在SDK安装目录下的和Sensor例程的工程里的CC1310LAUNCHXL.c都没找到,在PWM的历程中的CC1310LAUNCHXL.h中找到了。我是这样修改的我在Sensor的工程里添加了.c和.h文件,将PWM例程中CC1310LAUNCHXL.c和CC1310LAUNCHXL.h

    中PWM的相关部分移植了过来。包括您说的那个IO宏定义。


    nsonninnnooakdf

     testpwm.h

  • 这是我增加的.c和.h文件

    testpwm.c
    /*
     *  =============================== PWM ===============================
     *  Remove unused entries to reduce flash usage both in Board.c and Board.h
     */
    #include <ti/drivers/PWM.h>
    #include <ti/drivers/pwm/PWMTimerCC26XX.h>
    #include "testpwm.h"
    
    PWMTimerCC26XX_Object pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWMCOUNT];
    
    const PWMTimerCC26XX_HwAttrs pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWMCOUNT] = {
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN0, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER0A },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN1, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER0B },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN2, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER1A },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN3, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER1B },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN4, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER2A },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN5, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER2B },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN6, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER3A },
        { .pwmPin = CC1310_LAUNCHXL_PWMPIN7, .gpTimerUnit = CC1310_LAUNCHXL_GPTIMER3B },
    };
    
    const PWM_Config PWM_config[CC1310_LAUNCHXL_PWMCOUNT] = {
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM0], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM0] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM1], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM1] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM2], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM2] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM3], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM3] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM4], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM4] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM5], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM5] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM6], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM6] },
        { &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[CC1310_LAUNCHXL_PWM7], &pwmtimerCC26xxHWAttrs[CC1310_LAUNCHXL_PWM7] },
    };
    
    const uint_least8_t PWM_count = CC1310_LAUNCHXL_PWMCOUNT;
    
    /*
     *  =============================== GPTimer ===============================
     *  Remove unused entries to reduce flash usage both in Board.c and Board.h
     */
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    
    GPTimerCC26XX_Object gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMERCOUNT];
    
    const GPTimerCC26XX_HWAttrs gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMERPARTSCOUNT] = {
        { .baseAddr = GPT0_BASE, .intNum = INT_GPT0A, .intPriority = (~0), .powerMngrId = 0, .pinMux = GPT_PIN_0A, },
        { .baseAddr = GPT0_BASE, .intNum = INT_GPT0B, .intPriority = (~0), .powerMngrId = 0, .pinMux = GPT_PIN_0B, },
        { .baseAddr = GPT1_BASE, .intNum = INT_GPT1A, .intPriority = (~0), .powerMngrId = 1, .pinMux = GPT_PIN_1A, },
        { .baseAddr = GPT1_BASE, .intNum = INT_GPT1B, .intPriority = (~0), .powerMngrId = 1, .pinMux = GPT_PIN_1B, },
        { .baseAddr = GPT2_BASE, .intNum = INT_GPT2A, .intPriority = (~0), .powerMngrId = 2, .pinMux = GPT_PIN_2A, },
        { .baseAddr = GPT2_BASE, .intNum = INT_GPT2B, .intPriority = (~0), .powerMngrId = 2, .pinMux = GPT_PIN_2B, },
        { .baseAddr = GPT3_BASE, .intNum = INT_GPT3A, .intPriority = (~0), .powerMngrId = 3, .pinMux = GPT_PIN_3A, },
        { .baseAddr = GPT3_BASE, .intNum = INT_GPT3B, .intPriority = (~0), .powerMngrId = 3, .pinMux = GPT_PIN_3B, },
    };
    
    const GPTimerCC26XX_Config GPTimerCC26XX_config[CC1310_LAUNCHXL_GPTIMERPARTSCOUNT] = {
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER0], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER0A], GPT_A },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER0], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER0B], GPT_B },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER1], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER1A], GPT_A },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER1], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER1B], GPT_B },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER2], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER2A], GPT_A },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER2], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER2B], GPT_B },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER3], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER3A], GPT_A },
        { &gptimerCC26XXObjects[CC1310_LAUNCHXL_GPTIMER3], &gptimerCC26xxHWAttrs[CC1310_LAUNCHXL_GPTIMER3B], GPT_B },
    };
    
    3771.testpwm.h

  • 我没有5X5的板子,但是你改一下IO应该就可以了,可以去自己搞一下试试。
  • 好。谢谢。
  • 十分感谢您,已经调试成功了,再请教您一个问题,1310又5个IO驱动能力比较强,用这5个驱动能力强的IO当作PWM,会不会效果好一些?

  • 这个不好说,如果你是直接驱动一个led 没什么问题,但是如果你是驱动电机芯片给个PWM信号,这就无所谓的。
  • 谢谢,我正是要驱动电机芯片,那就用普通IO也可以对吧?
  • 是的,因为你给的是个信号,不是驱动一个负载所以无所谓。
  • 好的,再次感谢!!!能给五星好评吗0.0