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.

[参考译文] CC1310:无线 M-Bus 背对背 Rx

Guru**** 1807890 points
Other Parts Discussed in Thread: CC1310, WMBUS
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1321678/cc1310-wireless-m-bus-back-to-back-rx

器件型号:CC1310
主题中讨论的其他器件: WMBUS

您好!

我们将使用 CC1310和应用手册"CC13xx 组合式 wM-Bus C 模式和 T-Mode"中提供的示例开发无线 M-Bus 应用、包括  

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/689154/cc1310-require-partial-mode-example-of-cc1310

我们可以接收数据包、但偶尔会丢失一些数据包、并且希望获得一些建议。

示例是使用一个线程在每次接收到包时激活无线电和回调、但我们已扩展代码来处理错误和 CRC 检查、这可能是原因。

是否可以在背对背接收设置中使用"部分读取"?

我们曾尝试 在不走运的情况下使用 bRepeatNok/bRepeatOk、但可以在回调本身中重新激活回调。

此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经进行了研发检查、应该没有任何理由不使用重复模式和部分读取条目。 但是、我们没有相关的代码示例、也没有对其进行测试。

    我假设在跟踪数据队列等方面、这会使代码稍微复杂化。

    我不明白为什么这也是必要的。 您不应在回调中进行大量处理、而应将其移动到应用中的其他位置。 然后在接收到数据包后重新启动 RX、然后处理接收到的数据包、同时重新启动射频内核并接收新的数据包。

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    感谢您的快速回复、我将尝试它。

    在回调中停止并重新初始化无线电的最佳方法是什么。 目前我只是设置 rxDone 和 partialReadEntry -> status = data_entry_pending,但有更好的方法吗?

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,Peter

    我不确定我是否理解您在回调中想要做什么。 你是否没有关注你所连接到的线程内的示例?

    您可以在回调中设置长度、如下所示:

    RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen);

    这将确保对讲机在接收到正确字节数时自动退出 RX、因此您不必手动停止对讲机。

    今天、我使用重复模式做了一些测试、发现在使用 SET_LEN 命令时无法使用该模式、因此需要将两种重复模式都设置为0。

    Br

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    是的、我遵循该示例并使用  

    RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen);

    它工作正常、但在某些情况下会发生错误、我希望在接收到整个包之前重新初始化。  

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您应该使用 RF_CancelCmd 来退出 RX。

    我正在处理一个更完整的代码示例、该示例中也包含一些错误处理、完成后可以将其发布在此处

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    非常感谢、非常感谢您的帮助、并期待看到您正在学习的示例。

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    早上好!

    我稍微更改了代码、但仍然有一些数据包丢失。 您对下面的代码有什么建议吗?

    /**
     * @file protocol/sndp/src/SndpWMBus.c
     * @brief WMBus message parser
     * @copyright (C) 2023 ReMoni ApS.
     *
     * These computer program listings and specifications, are the property of
     * ReMoni ApS and shall not be reproduced or copied or used in whole or in
     * part without written permission from ReMoni ApS.
     *
     */
    
    /*---------------------------------------------------------------------------
                                    Include files
       ---------------------------------------------------------------------------*/
    
    /* *INDENT-OFF* */
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
    #include <ti/drivers/rf/RF.h>
    #include <remoni/mode.h>
    #include <remoni/Device.h>
    #include <remoni/crc16wmbus.h>
    #include <pthread.h>
    #include <unistd.h>
    
    #include "Board.h"
    #include "nvm_cog.h"
    #include "Sndp.h"
    #include "SndpApAir_cc1310.h"
    #include "SndpCfg.h"
    #include "SndpRoutingTable.h"
    #include "sndpUart.h"
    #include "smartrf_settings/smartrf_settings_wmbus.h"
    #include "SndpWMBus.h"
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <xdc/runtime/System.h>
    /* *INDENT-ON* */
    
    /*---------------------------------------------------------------------------
                                  Macro definitions
       ---------------------------------------------------------------------------*/
    
    #define RF_TASK_PRIORITY   3
    
    /* Packet RX Configuration */
    #define DATA_ENTRY_HEADER_SIZE   12    /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH               255
    #define LENGTH_POSITION          2
    #define APPENDED_BYTES           1
    #define NUM_DATA_ENTRIES         1     /* NOTE: Only two data entries supported at the moment */
    
    #define FRAME_IX    (DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1)
    
    #define RF_QUEUE_DATA_ENTRY_HEADER_SIZE  12                                                             // Constant header size of a Generic Data Entry
    #define RF_QUEUE_QUEUE_ALIGN_PADDING(length)  (4 - ((length + RF_QUEUE_DATA_ENTRY_HEADER_SIZE) % 4))    // Padding offset
    #define RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(numEntries, dataSize, appendedBytes)                                                    \
    	(numEntries * (RF_QUEUE_DATA_ENTRY_HEADER_SIZE + dataSize + appendedBytes + RF_QUEUE_QUEUE_ALIGN_PADDING(dataSize + appendedBytes)))
    
    #define RX_EVT    Event_Id_00
    
    /*---------------------------------------------------------------------------
                         Enumerations/Type definitions/Structs
       ---------------------------------------------------------------------------*/
    
    /*---------------------------------------------------------------------------
                                Global variables/const
       ---------------------------------------------------------------------------*/
    
    extern Task_Params radioTaskParams;     // Borrow from radio task - not used in this mode
    extern Task_Struct radioTask;           // Borrow from radio task - not used in this mode
    extern uint8_t radioTaskStack[];        // Borrow from radio task - not used in this mode
    extern const size_t radioStackSize;     // Borrow from radio task - not used in this mode
    
    /*---------------------------------------------------------------------------
                                 Local variables/const
       ---------------------------------------------------------------------------*/
    
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
    								 MAX_LENGTH,
    								 APPENDED_BYTES)] __attribute__((aligned(4)));
    static rfc_dataEntryPartial_t* partialReadEntry = (rfc_dataEntryPartial_t*)&rxDataEntryBuffer;
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    
    static rfc_propRxOutput_t rxStatistics;
    static uint8_t lengthWritten = false;
    static uint8_t rxDone = false;
    
    static uint8_t packet[sizeof(rxDataEntryBuffer)];       /* The length byte is stored in a separate variable */
    static uint8_t has_packet = false;                      /* Act as boolean and length of packet when true */
    
    static RF_CmdHandle rf_comm_handle;
    
    rfc_CMD_READ_RFREG_t RF_cmdReadRfReg =
    {
    	.commandNo = 0x0601,
    	.address = 0x5178,
    	.value = 0,
    };
    
    Event_Handle rxEvent;
    Event_Params rxEventParams;
    Event_Struct rxStructEvent; /* Memory allocated at build time */
    
    /*---------------------------------------------------------------------------
                                   Local prototypes
       ---------------------------------------------------------------------------*/
    
    static void rfTaskFunction(UArg arg0, UArg arg1);
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    /****************************************************************************
                                   Local functions
    ****************************************************************************/
    
    /**
     * rfThread() - Thread initializing radio with callback and keep it going
     * @param  [in] arg0    Passed argument 0
     * @param  [in] arg1    Passed argument 1
     */
    static void rfTaskFunction(UArg arg0, UArg arg1)
    {
    	UInt events;
    	RF_Stat status;
    	RF_Params rfParams;
    
    	RF_Params_init(&rfParams);
    
    	partialReadEntry->length = MAX_LENGTH + LENGTH_POSITION + APPENDED_BYTES + 4;
    	partialReadEntry->config.irqIntv = LENGTH_POSITION;
    	partialReadEntry->config.type = DATA_ENTRY_TYPE_PARTIAL;
    	partialReadEntry->status = DATA_ENTRY_PENDING;
    
    	partialReadEntry->pNextEntry = (uint8_t*)partialReadEntry;
    
    	dataQueue.pCurrEntry = (uint8_t*)partialReadEntry;
    	dataQueue.pLastEntry = NULL;
    
    	/* Modify CMD_PROP_RX command for application needs */
    	RF_cmdPropRx_wmbus.pQueue = &dataQueue;                 /* Set the Data Entity queue for received data */
    	RF_cmdPropRx_wmbus.maxPktLen = 0;                       /* Unlimited length, needed for RF_runImmediateCmd to work */
    	RF_cmdPropRx_wmbus.rxConf.bAutoFlushCrcErr = 0x0;       /* Auto-flush packets with invalid CRC */
    	RF_cmdPropRx_wmbus.pktConf.bRepeatNok = 0x0;            /* Exit RX after a packet is recived */
    	RF_cmdPropRx_wmbus.pktConf.bRepeatOk = 0x0;             /* Exit RX after a packet is recived */
    	RF_cmdPropRx_wmbus.pOutput = (uint8_t*)&rxStatistics;
    
    	/* Request access to the radio */
    	rfHandle = RF_open(&rfObject, &RF_prop_wmbus, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup_wmbus, &rfParams);
    
    	/* Set the frequency */
    	rf_comm_handle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs_wmbus, RF_PriorityNormal, NULL, 0);
    
    	/* Set event */
    	Event_Params_init(&rxEventParams);
    	Event_construct(&rxStructEvent, &rxEventParams);        /* Memory allocated at build time */
    	rxEvent = Event_handle(&rxStructEvent);                 /* Memory allocated at build time */
    	// rxEvent = Event_create(&rxEventParams, NULL); /* Memory allocated in here */
    	// if (rxEvent == NULL) { System_abort("Event create failed"); }
    
    	while (!SndpWMBus_ShouldStop()) {
    		rxDone = false;
    		lengthWritten = false;
    		rf_comm_handle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx_wmbus, RF_PriorityNormal, &callback, IRQ_RX_N_DATA_WRITTEN);
    		uint32_t timeout_cnt = 7000; // Restart counter if something goes wrong
    		while (!rxDone && !SndpWMBus_ShouldStop()) {
    			// Using events instead of usleep(5000) to get faster response
    			events = Event_pend(rxEvent, Event_Id_NONE, RX_EVT, 5000 / 10); // tickPeriod 10 uS
    			timeout_cnt--;
    			// Filtering on events could be done like if (events & RX_EVT)
    			if (timeout_cnt == 0) { // Restart if nothing received
    				status = RF_flushCmd(rfHandle, rf_comm_handle, 0);
    				RF_close(rfHandle);
    				rfHandle = RF_open(&rfObject, &RF_prop_wmbus, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup_wmbus, &rfParams);
    				rf_comm_handle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs_wmbus, RF_PriorityNormal, NULL, 0);
    				(void)status;   // Just to remove warning - System_printf(status) can be used
    				break;
    			}
    			(void)events; // Remove warning
    		}
    	}
    	RF_flushCmd(rfHandle, RF_CMDHANDLE_FLUSH_ALL, 0);
    	RF_close(rfHandle);
    }
    
    /**
       callback() - Callback to set length and receive full package
     */
    /**
     * callback() - Callback to set length and receive full package
     * @param  [in] RF_Handle    	The radio handle
     * @param  [in] RF_CmdHandle    The command handle
     * @param  [in] RF_EventMask    The event mask initiating the callback
     */
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    	if (e & RF_EventNDataWritten) {
    		if (!lengthWritten) {
    			lengthWritten = true;
    
    			RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdReadRfReg);
    
    			if (RF_cmdReadRfReg.value == 1) { // C-Mode
    				uint8_t preamble = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    				switch (preamble) {
    				case 0xcd:
    				{
    					uint8_t l_field = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1];
    					uint8_t crc_length = (l_field > 9) ? (2 * (l_field - 10) / 16 + 2 + 1) : 0;
    					RF_cmdPropSetLen_wmbus.rxLen = l_field + crc_length + (LENGTH_POSITION - 1) + 2;
    					break;
    				}
    				case 0x3d:
    					// Length is 2 bytes longer than wmbusmeters because it is including CRC at the end
    					RF_cmdPropSetLen_wmbus.rxLen = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1] + (LENGTH_POSITION - 1) + 1 - 3;
    					break;
    				default:
    				{
    					// Unknown and ungandled package type - future implementation
    					RF_cmdPropSetLen_wmbus.rxLen = 0;
    					break;
    				}
    				}
    			} else {
    				// T-Mode currently unhandled
    				// uint8_t l_field = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    				// RF_cmdPropSetLen_wmbus.rxLen = l_field;
    				// System_printf("%d\n", l_field);
                    RF_cmdPropSetLen_wmbus.rxLen = 0;
    			}
    			if (RF_cmdPropSetLen_wmbus.rxLen == 0) {    // Abort
    			    RF_Stat status = RF_cancelCmd(h, ch, 1);    // Cancel command - callback will be called
    	            (void)status; // Remove warning
    			} else {    // Set length
                    memset(&rxDataEntryBuffer[30], 0, sizeof(rxDataEntryBuffer) - 30); // Mostly for debug when inspecting data
                    RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen_wmbus);
    			}
    		}
    	} else {
    		uint8_t preamble = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    		uint8_t length = rxDataEntryBuffer[FRAME_IX];
    		uint8_t is_valid = 0;
    
    		if (0xcd == preamble) {
    			//uint8_t is_valid = crc16wmbus_check_block(&rxDataEntryBuffer[FRAME_IX], 12);
    			length += (length > 9) ? (2 * (length - 10) / 16 + 2 + 2) : 3;
    			is_valid = crc16wmbus_check_split(&rxDataEntryBuffer[FRAME_IX], length);
    		} else if (0x3d == preamble) {
    			length += 1; //Length is without it self
    			is_valid = crc16wmbus_check_block(&rxDataEntryBuffer[FRAME_IX], length);
    		}
    		// TODO: Look at others
    
    		if (is_valid) {
    			int8_t rssi = rxStatistics.lastRssi;
    
    			/* Copy the payload + the status byte to the packet variable */
    			if (has_packet > 0) {
    				/* packet in use by sndp */
    			} else if (is_valid) {
    				has_packet = length + 1;
    				memset(packet, 0, sizeof(packet));
    				memcpy(packet, &rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE], length + 1);
    				SndpWMBus_NewMessage(packet, &has_packet, rssi);    // Non blocking handover
    				// System_printf("Data %d\n", rxStatistics.timeStamp);
    			}
    		}
    		// System_printf("%d %x %x\n", is_valid, preamble, e);
    		partialReadEntry->status = DATA_ENTRY_PENDING;
    		rxDone = true;
    		Event_post(rxEvent, RX_EVT);
    	}
    }
    
    /****************************************************************************
                                   Global functions
    ****************************************************************************/
    
    /**
       SndpWMBus_Init() - Initialize WMBus
     */
    void WMBusHW_Init(void)
    {
    	/* Create the rf task */
    	Task_Params_init(&radioTaskParams);
    	radioTaskParams.stackSize = radioStackSize;
    	radioTaskParams.priority = RF_TASK_PRIORITY;
    	radioTaskParams.stack = &radioTaskStack;
    	radioTaskParams.instance->name = "WMBus Task";
    	Task_construct(&radioTask, rfTaskFunction, &radioTaskParams, NULL);
    }
    

    它仍在进行中、但有点实用。 不过、设置长度实际上效果更好一些、如下所示:

    rf_cmdPropSetLen_wmbus.rxLen = data_entry_header_size + length_position;

    而不依赖 RF_CancelCmd ()。 我错了吗?

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    它看起来像使用 RF_cancelCmd (h、ch、0);突然退出产生了影响、所以使用上面的代码做了这个微小的改变。

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尚未完成演示、但正在进行中。

    只是为了确保我完全理解您的问题。

    您是否丢失了数据包、如未找到同步、还是数据包中出现 CRC 错误。

    如果您丢失了数据包、是否已确认这是时序问题? 即、在传输新的数据包时、您是否已经验证无线电尚未进入 RX?

    如果问题与 CRC 错误有关、您是否已确保遵循勘误表注释中的通报11?

    Br

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    感谢您的更新。  

    我不清楚为什么软件包会丢失、我真的不知道如何进一步调试它。 使用上面的代码、根本不存在任何 CRC 错误、回调不会报告任何异常情况。

    我从水表获得数据 、并过滤掉所有紧凑型封装、因此预计数据永远~2分钟、但有时(每几个小时)存在间隙。 在使用多个有源计量表和紧凑封装的情况下进行调试会有点困难。

    我 还没有实施建议11、因为它与 CPU 从空闲状态切换相关、我不知道是什么情况、但我将在下周执行、因为它不会有任何危害。

    在您的帮助下、上面的代码效果更好、可能每隔几个小时就会丢失一个包裹。 您能看到任何明显的错误或改进建议吗?

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我将尝试给您提供一些一般的调试提示、以便您可以尝试缩小问题范围。

    如果从您正在传输某些内容的意义上来说数据包丢失了、但没有收到任何数据包、则应检查以下事项:

    您确定器件处于 RX 状态吗? 检查 RX 命令的状态是否为2 (有效)

    将 RF_EventMdmSoft 添加到回调中来查看是否收到 SYNC、也是一个好主意。 通过这种方法、您可以确定数据包是否被过滤掉、或者您是否甚至找不到同步字。

    如果您的设备在 RX 中、但在传输数据包时找不到同步字、可能是因为存在干扰数据包的干扰器导致您错过同步字。 让监听器查看监听器是否接收到数据包始终是一个好主意。 如果监听器收到但并非您(并且您的器件位于 RX 中)、则可能是硬件出错、导致灵敏度不良。

    编写 SW 来接收所有正常数据包通常不算太难、但当您尝试处理所有错误情况时会更困难。

    我制作了一个可用于调试的代码示例。 您应该对设置等进行类似操作、然后确保代码处理所有错误情况。

    为了对此进行测试、我建议不仅要尝试从水表接收正常数据包、 但是、如果有发送器、则可以配置为传输太长、太短、具有 CRC 错误、导致溢出的数据包等的数据包。另外、请确保代码正在处理所有这些情况。

    我的测试代码如下:

    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/GPIO.h>
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /* Board Header files */
    #include "ti_drivers_config.h"
    
    /* Application Header files */
    #include "RFQueue.h"
    #include <ti_radio_config.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    // CMD_PROP_SET_LEN
    rfc_CMD_PROP_SET_LEN_t RF_cmdPropSetLen =
    {
       .commandNo = 0x3401,
       .rxLen = 0x0000,
    };
    
    /***** Defines *****/
    
    /* Packet RX Configuration */
    //  ----------------------------------------------------------------------------------------------------------
    //  | DATA_ENTRY_HEADER (12 bytes) | H0 | H1 | H2 | H3 | Length N | D0 | D1 | D2 | .. | .. | D(N-2) | D(N-1) |
    //  ----------------------------------------------------------------------------------------------------------
    
    // Optional appended bytes
    //  -------------------------------------------------------
    //  | CRC1 | CRC0 | RSSI | TS3 | TS2 | TS1 | TS0 | Status |
    //  -------------------------------------------------------
    #define DATA_ENTRY_HEADER_SIZE  12                      /* Constant header size of a Partial Data Entry */
    #define MAX_LENGTH              10                      /* Max length byte the application will accept */
    #define PACKET_HEADER_SIZE      4                       /* Bytes in packet before location of the length byte */
    #define LENGTH_POSITION         PACKET_HEADER_SIZE + 1  /* Position of length byte (after sync) */
    #define NUM_APPENDED_BYTES      0                       /* .rxConf.bIncludeCrc = 0x1;       // 2 bytes (if default CRC is used)
                                                               .rxConf.bAppendRssi = 0x1;       // 1 byte
                                                               .rxConf.bAppendTimestamp = 0x1;  // 4 bytes
                                                               .rxConf.bAppendStatus = 0x1;     // 1 byte */
    
    
    
    /***** Prototypes *****/
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    static RF_CmdHandle rxHandle;
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuf0, 4);
    static uint8_t rxDataEntryBuf0[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION - + NUM_APPENDED_BYTES];
    #pragma DATA_ALIGN (rxDataEntryBuf1, 4);
    static uint8_t rxDataEntryBuf1[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION - + NUM_APPENDED_BYTES];
    
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    static uint8_t rxDataEntryBuf0[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES];
    #pragma data_alignment = 4
    static uint8_t rxDataEntryBuf1[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES];
    
    #elif defined(__GNUC__)
    static uint8_t rxDataEntryBuf0[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES] __attribute__((aligned(4)));
    static uint8_t rxDataEntryBuf1[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES] __attribute__((aligned(4)));
    
    #else
    #error This compiler is not supported.
    #endif
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static uint16_t payloadLength;
    
    
    rfc_dataEntryPartial_t* partialReadEntry0 = (rfc_dataEntryPartial_t*)&rxDataEntryBuf0;
    rfc_dataEntryPartial_t* partialReadEntry1 = (rfc_dataEntryPartial_t*)&rxDataEntryBuf1;
    rfc_dataEntryPartial_t* currentReadEntry = (rfc_dataEntryPartial_t*)&rxDataEntryBuf0;
    
    rfc_propRxOutput_t rxStatistics;
    static uint8_t lengthWritten = false;
    static uint8_t cancelRx = false;
    RF_Stat status = 0xFF;
    
    /* RX Semaphore */
    static Semaphore_Struct rxSemaphore;
    static Semaphore_Handle rxSemaphoreHandle;
    
    uint8_t packetHeader[PACKET_HEADER_SIZE];
    uint8_t packetPayload[MAX_LENGTH + 1]; // Must have room to store the length byte as well
    uint8_t packetStatusBytes[NUM_APPENDED_BYTES];
    
    //debug
    uint8_t eventNDataWritten = 0;
    uint8_t eventRxOk = 0;
    uint8_t eventCmdAborted = 0;
    uint8_t eventRxBufFull = 0;
    uint8_t eventRxEntryDone = 0;
    uint8_t eventDataWritten = 0;
    uint8_t eventRxAborted = 0;
    uint8_t eventMdmSoft = 0;
    uint8_t eventLastCmdDone = 0;
    uint8_t dummy = 0;
    
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_setConfig(CONFIG_GPIO_RLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_write(CONFIG_GPIO_RLED, CONFIG_GPIO_LED_OFF);
    
        /* Initialize RX semaphore */
        Semaphore_construct(&rxSemaphore, 0, NULL);
        rxSemaphoreHandle = Semaphore_handle(&rxSemaphore);
    
        partialReadEntry0->length = MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES + 4;  // Make sure there is enough room for a complete packet in one data entry.
                                                                                            // Number of bytes following this length field
                                                                                            // + 4 is to make room for the pktStatus (2 bytes) and nextIndex (2 bytes)
        partialReadEntry0->config.irqIntv = LENGTH_POSITION;
        partialReadEntry0->config.type = DATA_ENTRY_TYPE_PARTIAL;
        partialReadEntry0->status = DATA_ENTRY_PENDING;
    
        partialReadEntry1->length = MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES + 4;  // Make sure there is enough room for a complete packet in one data entry.
                                                                                            // Number of bytes following this length field
                                                                                            // + 4 is to make room for the pktStatus (2 bytes) and nextIndex (2 bytes)
        partialReadEntry1->config.irqIntv = LENGTH_POSITION;
        partialReadEntry1->config.type = DATA_ENTRY_TYPE_PARTIAL;
        partialReadEntry1->status = DATA_ENTRY_PENDING;
    
        partialReadEntry0->pNextEntry = (uint8_t*)partialReadEntry1;
        partialReadEntry1->pNextEntry = (uint8_t*)partialReadEntry0;
    
        dataQueue.pCurrEntry = (uint8_t*)partialReadEntry0;
        dataQueue.pLastEntry = NULL;
    
    
        /* Modify CMD_PROP_RX command for application needs */
        RF_cmdPropRx.pQueue = &dataQueue;
        RF_cmdPropRx.pOutput = (uint8_t*)&rxStatistics;
        RF_cmdPropRx.rxConf.bIncludeHdr = 1; // Must be 1 to receive the first byte after sync in the data entry
        RF_cmdPropRx.maxPktLen = 0;          // Unlimited length
    
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
        RF_cmdPropRx.pktConf.bRepeatOk = 0;
        RF_cmdPropRx.pktConf.bRepeatNok = 0;
    
        // Optional status bytes appended AFTER the payload
        // If these are changed, NUM_APPENDED_BYTES must also be updated
        RF_cmdPropRx.rxConf.bIncludeCrc = 0x0;      // 2 byte (if default CRC is used)
        RF_cmdPropRx.rxConf.bAppendRssi = 0x0;      // 1 byte
        RF_cmdPropRx.rxConf.bAppendStatus = 0x0;    // 1 Byte
        RF_cmdPropRx.rxConf.bAppendTimestamp = 0x0; // 4 bytes
    
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        while(true)
        {
            lengthWritten = false;
            cancelRx = false;
            status = 0xFF;
    
            eventNDataWritten = 0;
            eventRxOk = 0;
            eventCmdAborted = 0;
            eventRxBufFull = 0;
            eventRxEntryDone = 0;
            eventDataWritten = 0;
            eventRxAborted = 0;
            eventMdmSoft = 0;
            eventLastCmdDone = 0;
    
            rxHandle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventNDataWritten |
                                                                                                 RF_EventRxOk         |
                                                                                                 RF_EventRxBufFull    |
                                                                                                 RF_EventCmdAborted   |
                                                                                                 RF_EventMdmSoft);
            Semaphore_pend(rxSemaphoreHandle, BIOS_WAIT_FOREVER);
    
            if (cancelRx)
            {
                status = RF_cancelCmd(rfHandle, rxHandle, 0);
                Semaphore_pend(rxSemaphoreHandle, BIOS_WAIT_FOREVER);
            }
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventNDataWritten)
        {
            GPIO_toggle(CONFIG_GPIO_RLED);
            eventNDataWritten++;
    
            if (!lengthWritten)
            {
                lengthWritten = true;
    
                payloadLength = *(uint8_t*)(&currentReadEntry->rxData + LENGTH_POSITION - 1);
    
                if (payloadLength > MAX_LENGTH)
                {
                    cancelRx = true;
                    Semaphore_post(rxSemaphoreHandle);
                }
                else
                {
                    RF_cmdPropSetLen.rxLen = payloadLength + LENGTH_POSITION - 1; // Must subtract 1 due to rxConf.bIncludeHdr = 1
                    RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen);
                }
            }
        }
    
        if (e & RF_EventMdmSoft)
        {
            eventMdmSoft++;
        }
    
        if (e & RF_EventRxOk)
        {
            eventRxOk++;
            memcpy(packetHeader,        (uint8_t*)(&currentReadEntry->rxData + 0                              ), PACKET_HEADER_SIZE);
            memcpy(packetPayload,       (uint8_t*)(&currentReadEntry->rxData + (LENGTH_POSITION - 1)          ), (payloadLength + 1));
            memcpy(packetStatusBytes,   (uint8_t*)(&currentReadEntry->rxData + LENGTH_POSITION + payloadLength), NUM_APPENDED_BYTES);
        }
    
        if (e & RF_EventLastCmdDone)
        {
           eventLastCmdDone++;
           currentReadEntry->status = DATA_ENTRY_PENDING;
           currentReadEntry = (rfc_dataEntryPartial_t*)currentReadEntry->pNextEntry;
           dataQueue.pCurrEntry = (uint8_t*)currentReadEntry;
    
           Semaphore_post(rxSemaphoreHandle);
        }
    
        if (e & RF_EventCmdAborted)
        {
            eventCmdAborted++;
            currentReadEntry->status = DATA_ENTRY_PENDING;
            currentReadEntry = (rfc_dataEntryPartial_t*)currentReadEntry->pNextEntry;
            dataQueue.pCurrEntry = (uint8_t*)currentReadEntry;
    
            Semaphore_post(rxSemaphoreHandle);
        }
    
        if (e & RF_EventRxBufFull)
        {
            currentReadEntry->status = DATA_ENTRY_PENDING;
            currentReadEntry = (rfc_dataEntryPartial_t*)currentReadEntry->pNextEntry;
            dataQueue.pCurrEntry = (uint8_t*)currentReadEntry;
    
            eventRxBufFull++;
        }
    }
    
    

    我已经测试了以下内容:

    数据包过短:

    A1 A2 A3 A4 1 1

    nRxStopped 递增并且 eventLastCmdDone 被设置

    数据包过长(应用程序将取消 RX 命令)

    A1 A2 A3 A4 14 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

    nRxStopped 递增,并设置 eventCmdAborted

    有 CRC 错误的数据包:

    A1 A2 A3 A4 5 1 2 3 4 5 6  

    nRxNok 递增并且  eventLastCmdDone 被设置

    OK 数据包:

    A1 A2 A3 A4 5 1 2 3 4 5 6

    nRxOk 递增并且  eventLastCmdDone 和 eventRxOk 被置位

    缓冲区溢出:

    在 rf_runImmediateCmd 的回调中设置断点以溢出

    nBrBuffFull 会递增、而 eventLastCmdDone 和 eventRxBufFull 会被设置

     

    由于您使用的是部分读取条目、因此 CPU 将在射频内核处于活动状态且正在接收数据包时执行代码。 因此、您需要遵循建议11。

    如果您正在使用正常的数据条目、并且在 RX 中完成无线电操作并收到数据包之前未获得回调、则这不是必需的、但在您的情况下是必要的。

    但是、如果问题是缺少同步而不是 CRC 错误、这不能解决您的问题、但您仍然应该实施它以避免 数据包中出现不必要的错误。

    Br

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    谢谢、我来试一下。

    我当前正在调试 T 模式、看起来像  

    RF_runImmediateCmd (rfHandle、(uint32_t*)&RF_cmdReadRfReg); //获取 Mode 值

    仅返回 RF_EventNDataWriten 的正确值、而不返回 RF_EventNDataWriten 的值。 是这样吗?

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我想您问的是  RF_EventNDataWriten 与 RF_EventDataWritten 的对比情况????

    RF_EventNDataWriten:写入部分读取 Rx 缓冲区的指定字节数

    RF_EventDataWriten: 写入部分读取 Rx 缓冲器的数据

    在我的示例中、长度是同步字之后的字节编号5、这意味着在接收到至少5个字节之前我无法读出长度。

    因此, partialReadEntry0->config.irqIntv 和 partialReadEntry1->config.irqIntv= 5;

    因此、我需要等待第一个 RF_EventNDataWriten 事件、然后才能读取长度信息。

    如果我第一次读取 RF_EventDataWriten 时尝试读取长度(字节5)、则表示尚未接收到长度。

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    感谢您的回答、C 模式现在很稳定。 我引用了我自己的代码、但我认为我已经找到了这个代码并从  

    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    	if (e & RF_EventNDataWritten) {
    		if (!lengthWritten) {
    			lengthWritten = true;
    
    			RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdReadRfReg);
    
    			if (RF_cmdReadRfReg.value == 1) { // C-Mode
    				uint8_t preamble = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    				switch (preamble) {
    				case 0xcd:
    				{
    					uint8_t l_field = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1];
    					uint8_t crc_length = (l_field > 9) ? (2 * (l_field - 10) / 16 + 2 + 1) : 0;
    					RF_cmdPropSetLen_wmbus.rxLen = l_field + crc_length + (LENGTH_POSITION - 1) + 2;
    					break;
    				}
    				case 0x3d:
    					// Length is 2 bytes longer than wmbusmeters because it is including CRC at the end
    					RF_cmdPropSetLen_wmbus.rxLen = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1] + (LENGTH_POSITION - 1) + 1 - 3;
    					break;
    				default:
    				{
    					// Unknown and ungandled package type - future implementation
    					RF_cmdPropSetLen_wmbus.rxLen = 0;
    					break;
    				}
    				}
    			} else {
    				// T-Mode currently unhandled
    				// uint8_t l_field = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    				// RF_cmdPropSetLen_wmbus.rxLen = l_field;
    				// System_printf("%d\n", l_field);
                    RF_cmdPropSetLen_wmbus.rxLen = 0;
    			}
    			if (RF_cmdPropSetLen_wmbus.rxLen == 0) {    // Abort
    			    RF_Stat status = RF_cancelCmd(h, ch, 1);    // Cancel command - callback will be called
    	            (void)status; // Remove warning
    			} else {    // Set length
                    memset(&rxDataEntryBuffer[30], 0, sizeof(rxDataEntryBuffer) - 30); // Mostly for debug when inspecting data
                    RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen_wmbus);
    			}
    		}
    	} else {
    		uint8_t preamble = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    		uint8_t length = rxDataEntryBuffer[FRAME_IX];
    		uint8_t is_valid = 0;
    
    		if (0xcd == preamble) {
    			//uint8_t is_valid = crc16wmbus_check_block(&rxDataEntryBuffer[FRAME_IX], 12);
    			length += (length > 9) ? (2 * (length - 10) / 16 + 2 + 2) : 3;
    			is_valid = crc16wmbus_check_split(&rxDataEntryBuffer[FRAME_IX], length);
    		} else if (0x3d == preamble) {
    			length += 1; //Length is without it self
    			is_valid = crc16wmbus_check_block(&rxDataEntryBuffer[FRAME_IX], length);
    		}
    		// TODO: Look at others
    
    		if (is_valid) {
    			int8_t rssi = rxStatistics.lastRssi;
    
    			/* Copy the payload + the status byte to the packet variable */
    			if (has_packet > 0) {
    				/* packet in use by sndp */
    			} else if (is_valid) {
    				has_packet = length + 1;
    				memset(packet, 0, sizeof(packet));
    				memcpy(packet, &rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE], length + 1);
    				SndpWMBus_NewMessage(packet, &has_packet, rssi);    // Non blocking handover
    				// System_printf("Data %d\n", rxStatistics.timeStamp);
    			}
    		}
    		// System_printf("%d %x %x\n", is_valid, preamble, e);
    		partialReadEntry->status = DATA_ENTRY_PENDING;
    		rxDone = true;
    		Event_post(rxEvent, RX_EVT);
    	}
    }
    

    至  

    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    	if (e & RF_EventNDataWritten) {
    		if (!lengthWritten) {
    			lengthWritten = true;
    
    			RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdReadRfReg);      // Get the Mode value
    			rxMode = RF_cmdReadRfReg.value;                                 // Store the mode - reg will change later
    
    			if (rxMode == 1) {                                              // C-Mode
    				uint8_t preamble = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    				switch (preamble) {
    				case 0xcd:
    				{
    					uint8_t l_field = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1];
    					uint8_t crc_length = (l_field > 9) ? (2 * (l_field - 10) / 16 + 2 + 1) : 0;
    					RF_cmdPropSetLen_wmbus.rxLen = l_field + crc_length + (LENGTH_POSITION - 1) + 2;
    					break;
    				}
    				case 0x3d:
    					// Length is 2 bytes longer than wmbusmeters because it is including CRC at the end
    					RF_cmdPropSetLen_wmbus.rxLen = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + LENGTH_POSITION - 1] + (LENGTH_POSITION - 1) + 1 - 3;
    					break;
    				default:
    				{
    					// Unknown and unhandled package type - future implementation
    					RF_cmdPropSetLen_wmbus.rxLen = 0;
    					break;
    				}
    				}
    			} else {
    				// T-Mode is like frame a
    				uint8_t l_field = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    				uint8_t crc_length = (l_field > 9) ? (2 * (l_field - 10) / 16 + 2) : 0;
    				RF_cmdPropSetLen_wmbus.rxLen = l_field + crc_length;
    			}
    			if (RF_cmdPropSetLen_wmbus.rxLen == 0) {                                                // Abort
    				RF_Stat status = RF_cancelCmd(h, ch, 0);                                        // Cancel command - callback will be called
    				(void)status;                                                                   // Remove warning
    			} else {                                                                                // Set length
    				memset(&rxDataEntryBuffer[30], 0, sizeof(rxDataEntryBuffer) - 30);              // Mostly for debug when inspecting data
    				RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen_wmbus);
    			}
    		}
    	} else {
    		uint8_t preamble = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];
    		uint8_t length = rxDataEntryBuffer[FRAME_IX];
    		uint8_t is_valid = 0;
    
    		if (rxMode == 0) {                                                      // T-Mode
    			length = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE];             // No preamble
    			length += (length > 9) ? (2 * (length - 10) / 16 + 2 + 2) : 3;
    			length += 1;                                                    //Length is without it self
    			if (length + DATA_ENTRY_HEADER_SIZE < MAX_LENGTH) {             // Don't process if to big
    				memmove(&rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + 1], &rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE], length);
    				rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE] = 0xcd;       // Fake C-Mode
    				is_valid = crc16wmbus_check_split(&rxDataEntryBuffer[FRAME_IX], length);
    			}
    		} else if (0xcd == preamble) {
    			//uint8_t is_valid = crc16wmbus_check_block(&rxDataEntryBuffer[FRAME_IX], 12);
    			length += (length > 9) ? (2 * (length - 10) / 16 + 2 + 2) : 3;
    			is_valid = crc16wmbus_check_split(&rxDataEntryBuffer[FRAME_IX], length);
    		} else if (0x3d == preamble) {
    			length += 1; //Length is without it self
    			is_valid = crc16wmbus_check_block(&rxDataEntryBuffer[FRAME_IX], length);
    		}
    		// TODO: Look at others
    
    		if (is_valid) {
    			int8_t rssi = rxStatistics.lastRssi;
    
    			/* Copy the payload + the status byte to the packet variable */
    			if (has_packet > 0) {
    				/* packet in use by sndp */
    			} else if (is_valid) {
    				has_packet = length + 1;
    				memset(packet, 0, sizeof(packet));
    				memcpy(packet, &rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE], length + 1);
    				SndpWMBus_NewMessage(packet, &has_packet, rssi);    // Non blocking handover
    				// System_printf("Data %d\n", rxStatistics.timeStamp);
    			}
    		}
    		// System_printf("%d %d %d %x %x\n", is_valid, rxMode, length, preamble, e);
    		partialReadEntry->status = DATA_ENTRY_PENDING;
    		rxDone = true;
    		Event_post(rxEvent, RX_EVT);
    	}
    }
    

    但是、这会导致 T 模式封装多于 WMBusMeters 可以看到的具有无效 CRC 的 T 模式封装、并且也会影响 C 模式。 实际上只有1米发送、那么问题出在哪里呢?

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,Peter

    我不确定我是否理解您所问的问题。 "什么意思?

    "这会导致多于 WMBusMeters 可以看到的具有无效 CRC 的 T 模式封装、并影响 C。 模式"

    我无法调试您的实现、我不确定我是否理解您遇到的问题。

    请记住、即使您仅有1米的传输距离、附近也可能有其他仪表可以接收。 此外、由于 wmbus 仅使用2字节的同步字、因此您还将接收伪数据包。 如果接收到伪数据包时占用代码、则此时发送的任何其他数据包都将丢失。

    在验证软件是否按预期工作之前、最好在屏蔽环境中进行一些测试、此时可以完全控制发送到无线电的内容(无干扰源)。

    此外、在调试时将代码简化为仅记录找到的 SYNC 数量、c 模式的数量和 t 模式数据包的数量、并将该数量与您发送的数据包数量进行比较、可能有助于了解传输中有多少其他数据、 这可能会干扰您的数据包。

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    我将尝试进一步解释、不希望您调试我的代码、只需快速查看是否有关闭的东西。

    我认为代码在仅配置为 C 模式(帧格式 A 和 B)时基本没问题、但在启用 T 模式后开始失效。

    我 希望寻找假的 T-Mode 数据包可能会导致 C 模式数据包丢失、但没有办法尽早识别这些情况、例如在新的同步中重新启动?

    我希望能够可靠地处理 C 模式和 T 模式封装。

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,Peter

    仍然不确定我是否理解您遇到的问题。

    当您尝试进行电机控制时、

    1. 接收不到您要发送的 T 模式数据包、
    2. 或者、您是否会收到这些数据包、但还会收到很多虚假 T 模式数据包、这也会导致您丢失 C 模式数据包?
    3. 还有其他问题吗?

    我无法仅通过查看代码来说明问题所在、我只能建议您继续调试问题以缩小问题范围。

    当我们知道问题的原因时、我们也可以查看解决方案。

    我们可以做的是设置具有 SmartRF Studio 的 CC1310 LP、并将其用作监听器。

    您无法从 Studio 运行 C/T 模式补丁、但您可以设置正确的 PHY 参数、例如6字节的固定数据包长度。

    这将给你一个指示,在空气中发生了什么。

    从下图中可以看出、我已将 CC1310在我的办公桌上运行了大约3分钟。

    它接收到27个数据包、其中3个是我从另一个 LP 传输的数据包、其余为噪声或附近的其他仪表。

    从 RSSI 水平可以看出、我实际发送的3个数据包比收集的其余数据包强得多。 一些其他数据包看起来像"真实"C 模式数据包、因为它们具有信令字节(0x54)、其余数据包可能是 T 模式或噪声。

    请注意、wmbus 补丁具有可编程的载波侦听阈值。 此设置默认为-107dBm、因此不接受信号强度低于的同步字。

    出于调试目的、可以将阈值增加到接收到实际发送的数据包的水平、而其他所有内容都将不被接受。

    此处说明了如何更改阈值:

    CC13xx 组合的 wM-Bus C 模式和 T 模式应用手册(修订版 E)

    我对您的代码有一些可能会导致问题的注释:

    在设置了 RF_cmdPropSetLen_wmbus.rxLen 的回调中、您将其设置为 l_field +某个值。

    这意味着得到的长度可以大于255。

    您是否已确保数据条目足够大、从而不会出现溢出的情况?

    从代码来看、似乎您正在设置

    partialReadEntry -> length = MAX_LENGTH + length_position + added_bytes + 4;

    在这里、您不考虑 rxLen 大于 MAX_LEN

    您的代码另一个可能的问题是您没有订阅 RF_EventCmdAborted

     

    if (e & RF_EventNDataWritten)
    {
        .
        .
    }
    else
    {
        partialReadEntry->status = DATA_ENTRY_PENDING;
        rxDone = true;
        Event_post(rxEvent, RX_EVT);
    }
    

    如果您执行 RF_cancelCmd、则不会获得 eventLastCmdDone、而只能获得 RF_EventCmdAborted、这意味着在取消的情况下您的代码不会设置 partialReadEntry -> status = DATA_ENTRY_PUNDING;

    可能还有其他原因、因此、我强烈建议您调试代码、每次仅调试一种数据包类型、以确保所有"错误案例"/"边界案例"都得到正确处理。

    长度字节= 0

    长度字节= 255

    CRC 错误

    C 模式的帧格式错误(不是帧 A 或帧 B)

    Br

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    再次感谢您的帮助、非常感谢。

    我看到的是您的选项2

    或者您是否会收到这些数据包、但还会收到很多虚假 T 模式数据包、这也会导致您丢失 C 模式数据包

    我已经实施了您的建议

    • 已启用事件  RF_EventCmdAborted
    • 将 partialReadEntry ->长度限制为 MAX_LENGTH

    但是设置 载波侦听阈值实际上并不会对任何东西产生影响。 我正在 Linux 上开发、因此使用 SmartRF Studio 有点困难、但我还要尝试获取 Windows 机器。

    这是有道理的,寻找幽灵包将使我松散真正的包.

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    不应将 partialReadEntry ->长度限制为 MAX_LENGTH

    您可能需要增加它、因为您可以接收比此时间更长的数据包。

    在我的示例中、长度字节表示后跟多少个字节(不包括 CRC)

    /  ----------------------------------------------------------------------------------------
    //  | DATA_ENTRY_HEADER (12 bytes) | H0 | H1 | H2 | H3 | Length 5 | D1 | D2 | D3 | D4 | D5 |
    //  ----------------------------------------------------------------------------------------
    
    #define DATA_ENTRY_HEADER_SIZE  12
    #define MAX_LENGTH              5
    #define PACKET_HEADER_SIZE      4 
    #define LENGTH_POSITION         5
    #define NUM_APPENDED_BYTES      0                     
    
    static uint8_t rxDataEntryBuf0[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES]
    
    partialReadEntry0->length = MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES + 4;
    
    RF_cmdPropSetLen.rxLen = payloadLength + LENGTH_POSITION - 1; // Must subtract 1 due to rxConf.bIncludeHdr = 1 (H0 in the figure above)
    

    有效载荷长度从不大于 MAX_LENGTH (5)、因此最大 rxLen i 将设置为9。

    MAX_LENGTH 为255。 我不知道 wmbus 数据包的格式、因此不知道其中包含的内容、但如果您有如下内容:

    /  -------------------------------------------------------------------------------------------------------
    //  | DATA_ENTRY_HEADER (12 bytes) | H0 | Length 255 | D1 | D2 | D3 | D4 | D5 |------| D255 | CRC1 | CRC2 |
    //  -------------------------------------------------------------------------------------------------------
    
    #define DATA_ENTRY_HEADER_SIZE  12
    #define MAX_LENGTH              255
    #define PACKET_HEADER_SIZE      1 
    #define LENGTH_POSITION         2
    #define NUM_APPENDED_BYTES      0                     
    
    static uint8_t rxDataEntryBuf0[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + NUM_APPENDED_BYTES]
    
    partialReadEntry0->length = MAX_LENGTH    + 2 + LENGTH_POSITION + NUM_APPENDED_BYTES + 4;
    
    RF_cmdPropSetLen.rxLen    = payloadLength + 2 + LENGTH_POSITION - 1; // Must subtract 1 due to rxConf.bIncludeHdr = 1 (H0 in the figure

    必须将2添加到 partialReadEntry0->length 和 rf_cmdPropSetLen.rxLen 中。

    如果将 CS 阈值增大到高值根本没有帮助(例如、-50dBm、具体取决于您的发送器的强度)、我猜大概是问题与处理噪声/伪数据包无关。

    Br

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    我认为、至少目前将大小限制为 MAX_LENGTH 是可以的。 我还没有看到任何这样长的软件包、我们正在通过另一个具有更严格限制的协议转发这些软件包。

    我可能没有以正确的方式或在正确的位置提高 CS 阈值。 I 使用  

    HW_REG_OVERRIDE (0x6090、0x0ACE);//载波侦听阈值覆盖

    并尝试在不同的地方甚至像0x0AFF 一样使用它、但没有任何明显的差别。

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    覆盖已是应与该补丁一起使用的设置的一部分、因此您只需修改它(而不是将其添加到其他位置:

    #include DEVICE_FAMILY_PATH(driverlib/rf_mailbox.h)
    #include DEVICE_FAMILY_PATH(driverlib/rf_common_cmd.h)
    #include DEVICE_FAMILY_PATH(driverlib/rf_prop_cmd.h)
    #include <ti/drivers/rf/RF.h>
    #include DEVICE_FAMILY_PATH(rf_patches/rf_patch_cpe_wmbus_ctmode.h)
    #include DEVICE_FAMILY_PATH(rf_patches/rf_patch_mce_wmbus_ctmode.h)
    #include DEVICE_FAMILY_PATH(rf_patches/rf_patch_rfe_wmbus_ctmode.h)
    #include "smartrf_settings.h"
    
    uint32_t txShapeTMode[] = {0x00000000, 0x00000000, 0x00000000, 0x4B110200, 0xF2F0E1A6, 0xF2F2F2F2};   
    uint32_t txShapeCMode[] = {0x00000000, 0x00000000, 0x00000000, 0x440F0200, 0xD9D8CA96, 0xD9D9D9D9};
    
    // TI-RTOS RF Mode Object
    RF_Mode RF_prop =
    {
        .rfMode = RF_MODE_PROPRIETARY_SUB_1,
        .cpePatchFxn = &rf_patch_cpe_wmbus_ctmode,
        .mcePatchFxn = &rf_patch_mce_wmbus_ctmode,
        .rfePatchFxn = &rf_patch_rfe_wmbus_ctmode,
    };
    
    // Overrides for CMD_PROP_RADIO_DIV_SETUP
    static uint32_t pOverrides[] =
    {
    	//Run the MCE and RFE patches
        MCE_RFE_OVERRIDE(1,0,0,1,0,0),
        // override_synth_prop_863_930_div5.xml
        // Synth: Set recommended RTRIM to 7
        HW_REG_OVERRIDE(0x4038,0x0037),
        // Synth: Set Fref to 4 MHz
        (uint32_t)0x000684A3,
        // Synth: Configure fine calibration setting
        HW_REG_OVERRIDE(0x4020,0x7F00),
        // Synth: Configure fine calibration setting
        HW_REG_OVERRIDE(0x4064,0x0040),
        // Synth: Configure fine calibration setting
        (uint32_t)0xB1070503,
        // Synth: Configure fine calibration setting
        (uint32_t)0x05330523,
        // Synth: Set loop bandwidth after lock to 20 kHz
        (uint32_t)0x0A480583,
        // Synth: Set loop bandwidth after lock to 20 kHz
        (uint32_t)0x7AB80603,
        // Synth: Configure VCO LDO (in ADI1, set VCOLDOCFG=0x9F to use voltage input reference)
        ADI_REG_OVERRIDE(1,4,0x9F),
        // Synth: Configure synth LDO (in ADI1, set SLDOCTL0.COMP_CAP=1)
        ADI_HALFREG_OVERRIDE(1,7,0x4,0x4),
        // Synth: Use 24 MHz XOSC as synth clock, enable extra PLL filtering
        (uint32_t)0x02010403,
        // Synth: Configure extra PLL filtering
        (uint32_t)0x00108463,
        // Synth: Increase synth programming timeout (0x04B0 RAT ticks = 300 us)
        (uint32_t)0x04B00243,
        // override_phy_rx_aaf_bw_0xd.xml
        // Rx: Set anti-aliasing filter bandwidth to 0xD (in ADI0, set IFAMPCTL3[7:4]=0xD)
        ADI_HALFREG_OVERRIDE(0,61,0xF,0xD),
        // override_phy_gfsk_rx.xml
        // Rx: Set LNA bias current trim offset to 3
        (uint32_t)0x00038883,
        // Rx: Freeze RSSI on sync found event
        HW_REG_OVERRIDE(0x6084,0x35F1),
        // override_phy_gfsk_pa_ramp_agc_reflevel_0x2e.xml
        // Tx: Configure PA ramping setting and set AGC reference level to 0x2E
        HW_REG_OVERRIDE(0x6088,0x082E),
        // Tx: Configure PA ramping setting and set AGC settle wait = (0x7+1)*2 = 16 samples
        HW_REG_OVERRIDE(0x608C,0x0407),
        // override_phy_rx_rssi_offset_5db.xml
        // Rx: Set RSSI offset to adjust reported RSSI by +5 dB
        (uint32_t)0x00FB88A3,
        // TX power override
        // Tx: Set PA trim to max (in ADI0, set PACTL0=0xF8)
        ADI_REG_OVERRIDE(0,12,0xF8),
    	// AGC winsize 2 samples
        HW_REG_OVERRIDE(0x6064,0x1101),
        // CS threshold to –107 dBm
        HW_REG_OVERRIDE(0x6090,0xA095),//////////////////////////////////////////Change the override here
        // Let the patch control the correlator setting
        (uint32_t)0x00048103,
        // Clear state in internal radio register due to frequency change
        HW_REG_OVERRIDE(0x51F8,0x0000),
        // Set divider bias to disabled
        HW32_ARRAY_OVERRIDE(0x405C,1),
        (uint32_t)0x18000200,
        // TX shape in T-mode
        0xC0040031,
        (uint32_t)&txShapeTMode[0],
        // TX shape in C-mode
        //0xC0040031,
        //(uint32_t)&txShapeCMode[0],
        (uint32_t)0xFFFFFFFF,
    };

    如果您这样做、您收到的所有数据包的 RSSI 均为-50 dBm 以上、因此您可能有一些您不知道的强干扰器/仪表、或者您的问题不是虚假数据包。

    使用 SmartRF Studio 将同步事件添加到回调和/或测试中将帮助您了解这一点。

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    谢谢、这是我的错。

    现在它的工作和价值-85给出了合理的结果,没有许多"鬼"在我的工作地点,这是非常嘈杂。 我将在明天的实际情景中进行测试、并在团队中进行讨论。

    TI 建议在嘈杂环境中使用大约-90的值还是应 保持在-107?

    此致 Peter

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这取决于具体情况、很难给出任何好的建议。

    设置较高的阈值(假设为-90dBm)将减少由于噪声(或附近的其他仪表)而导致的错误数据包的数量、因此您更有可能接收到想要的数据包、因为接收器不会被占用来处理不适合您的数据包。

    另一方面、这也会设置您的灵敏度级别、因为您将无法接收信号强度低于-90dBm 的任何数据包(即使这些数据包是为您准备的)。

    我假设在数据包的开头有一些信息可以用来确定数据包是否适合您(某种 ID 等?)

    如果有、我想您可以检查该信息、并在数据包不适合您时取消 RX、而不必等待接收整个数据包、然后再进行检查。

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Siri:

    好的、谢谢、这是讲得通的。 我想我将进一步测试和完善这一点、现在您已向我指出了正确的方向。

    谢谢、祝您愉快。 此致 Peter