工具/软件:
您好:
我使用 GPT 计时器捕获脉冲宽度。 涉及两个计时器、我设置两个 GPTTImers 以捕获脉冲的两个边沿、然后计算第一个边沿和第二个边沿的差值。 我有一条 TX 线路、这条线路将在两个计时器都设置完毕后启用。 Tx 线路将连接到两个相同的电容器、每个电容器的两端连接到不同的 Rx GPIO。 RX 信号是相同的、因此生成的中断应同时发生、但似乎实际上只产生了一个中断、 而不是两者都产生。
谢谢、
Kenneth T.
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.
工具/软件:
您好:
我使用 GPT 计时器捕获脉冲宽度。 涉及两个计时器、我设置两个 GPTTImers 以捕获脉冲的两个边沿、然后计算第一个边沿和第二个边沿的差值。 我有一条 TX 线路、这条线路将在两个计时器都设置完毕后启用。 Tx 线路将连接到两个相同的电容器、每个电容器的两端连接到不同的 Rx GPIO。 RX 信号是相同的、因此生成的中断应同时发生、但似乎实际上只产生了一个中断、 而不是两者都产生。
谢谢、
Kenneth T.
您好 Kenneth、
您是否能够提供一个基本代码文件来演示您的 GPTimer 设置、并能帮助我们重现您所描述的问题? 是否调用了同一个 GPTimer 中断、或者两者之间是否不同? 如果其中一个被禁用、那么另一个中断是否始终被处理? 如果使用3.3V 电源电平、是否会发生相同的行为?
您是否正在使用 TI 驱动程序、 driverlib或 直接访问硬件寄存器? 您可以通过调试计时器的寄存器中断状态来收集哪些信息? 此外、您正在评估哪个版本的 F2 SDK?
此致、
Ryan
vector<GPTimerCC26XX_Handle> gptimer_handles(2); for (size_t t = 0; t < 2; t++) { // Configure GPTimer for edge time capture GPTimerCC26XX_Params gptimer_params; GPTimerCC26XX_Params_init(&gptimer_params); gptimer_params.width = GPT_CONFIG_16BIT; gptimer_params.mode = GPT_MODE_EDGE_TIME; gptimer_params.matchTiming = GPTimerCC26XX_SET_MATCH_NEXT_CLOCK; gptimer_params.direction = GPTimerCC26XX_DIRECTION_UP; gptimer_params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF; // Open GPTimer and set argument to "this" object for callback to use GPTimerCC26XX_Handle gptimer_handle = GPTimerCC26XX_open(t, &gptimer_params); gptimer_handles[t] = gptimer_handle; GPTimerCC26XX_setArg(gptimer_handle, this); // Configure Gpio for edge interrupt if (t == 0) { gpio.configure(Gpio::PinId::DIO_16, Gpio::Direction::INPUT, Gpio::Pull::NONE, Gpio::State::NONE, Gpio::Strength::NONE, GPTimerCC26XX_getPinMux(gptimer_handle)); } else if (t == 1) { gpio.configure(Gpio::PinId::DIO_1, Gpio::Direction::INPUT, Gpio::Pull::NONE, Gpio::State::NONE, Gpio::Strength::NONE, GPTimerCC26XX_getPinMux(gptimer_handle)); } // Set load value in order to support full/max 24-bit capability, configure edge mode and register callback GPTimerCC26XX_setLoadValue(gptimer_handle, MAX_GPTIMER_COUNT); GPTimerCC26XX_setCaptureEdge(gptimer_handle, both_edges ? GPTimerCC26XX_BOTH_EDGES : (rising_edge ? GPTimerCC26XX_POS_EDGE : GPTimerCC26XX_NEG_EDGE)); GPTimerCC26XX_registerInterrupt(gptimer_handle, gptimerCallback, GPT_INT_CAPTURE); GPTimerCC26XX_start(gptimer_handle); } tx_gpio.writeHigh(); for (size_t t = 0; t < 2; t++) { first_edge_sem.wait(); } for (size_t t = 0; t < 2; t++) { _second_edge_sem.wait(); } tx_gpio.writeLow(); for (size_t t = 0; t < 2; t++) { // Stop and close GPTimer GPTimerCC26XX_unregisterInterrupt(gptimer_handles[t]); GPTimerCC26XX_stop(gptimer_handles[t]); GPTimerCC26XX_close(gptimer_handles[t]); }
void Timer::gptimerCallback(GPTimerCC26XX_Handle gptimer_handle, GPTimerCC26XX_IntMask interruptMask) { // Capture edge value Timer* timer = reinterpret_cast<Timer*>(GPTimerCC26XX_getArg(gptimer_handle)); if (timer->_edge_count == 0) { timer->_first_edge_gpt = GPTimerCC26XX_getValue(gptimer_handle); timer->_first_edge_sem.post(); } else if (timer->_edge_count == 1) { timer->_second_edge_gpt = GPTimerCC26XX_getValue(gptimer_handle); timer->_second_edge_sem.post(); } timer->_edge_count++; }
嘿、Kenneth、
您能否针对寄存器级或核心功能差异对我的代码设置进行评论?
/* * Copyright (c) 2016-2020, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * ======== timerled.c ======== */ #include <stddef.h> #include <unistd.h> /* Driver Header files */ #include <ti/drivers/GPIO.h> #include <ti/drivers/timer/GPTimerCC26XX.h> /* Board Header file */ #include "ti_drivers_config.h" #define MAX_GPTIMER_COUNT 16777215 GPTimerCC26XX_Handle GPTimer0; GPTimerCC26XX_Handle GPTimer1; uint8_t timerCount0 = 0; uint8_t timerCount1 = 0; void gptimerCallback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) { // interrupt callback code goes here. Minimize processing in interrupt. if (handle == GPTimer0) { timerCount0++; } else if (handle == GPTimer1) { timerCount1++; } } /* * ======== mainThread ======== */ void *mainThread(void *arg0) { /* Call driver init functions */ GPIO_init(); /* Configure the LED pin */ GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); /* Turn off user LED */ GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF); GPTimerCC26XX_Params gptimer_params; GPTimerCC26XX_Params_init(&gptimer_params); gptimer_params.width = GPT_CONFIG_16BIT; gptimer_params.mode = GPT_MODE_EDGE_TIME; gptimer_params.matchTiming = GPTimerCC26XX_SET_MATCH_NEXT_CLOCK; gptimer_params.direction = GPTimerCC26XX_DIRECTION_UP; gptimer_params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF; // Open GPTimer and set argument to "this" object for callback to use GPTimer0 = GPTimerCC26XX_open(CONFIG_GPTIMER_0, &gptimer_params); GPTimer1 = GPTimerCC26XX_open(CONFIG_GPTIMER_1, &gptimer_params); GPTimerCC26XX_setArg(GPTimer0, (void *)0x00); GPTimerCC26XX_setArg(GPTimer1, (void *)0x01); GPTimerCC26XX_setLoadValue(GPTimer0, MAX_GPTIMER_COUNT); GPTimerCC26XX_setCaptureEdge(GPTimer0, GPTimerCC26XX_BOTH_EDGES); GPTimerCC26XX_registerInterrupt(GPTimer0, gptimerCallback, GPT_INT_CAPTURE); GPTimerCC26XX_start(GPTimer0); GPTimerCC26XX_setLoadValue(GPTimer1, MAX_GPTIMER_COUNT); GPTimerCC26XX_setCaptureEdge(GPTimer1, GPTimerCC26XX_BOTH_EDGES); GPTimerCC26XX_registerInterrupt(GPTimer1, gptimerCallback, GPT_INT_CAPTURE); GPTimerCC26XX_start(GPTimer1); GPIO_setConfigAndMux(CONFIG_GPIO_0, GPIO_CFG_IN_PU, GPTimerCC26XX_getPinMux(GPTimer0)); GPIO_setConfigAndMux(CONFIG_GPIO_1, GPIO_CFG_IN_PU, GPTimerCC26XX_getPinMux(GPTimer1)); while(1) { sleep(10); } return (NULL); }
两个计时器都由同一中断提供服务、因为我可以看到 两个 timerCount 值的递增、但我只是使用一个开关(即没有电容器)下拉两个 GPIO 并短接至 GND、然后工作电压为3.3V、因此我不确定这些变量中是否有任何一个导致了可观察到的差异。
此致、
Ryan
我修改了代码、现在脉冲宽度为20 微秒、但结果仍然成功。
您可以观察到一个竞态条件、因为在此期间必须发生四个中断(每个输入都向上和向下)并由同一个 HWI 函数(CPTimerCC26XX.c 中的 GPTimerCC26XXHwiFxn)进行处理。 可能第一个计时器的第一个边沿超过10微秒、因此第一个计时器的第二个边沿接下来会处理、而不是第二个计时器的第一个边沿。 我不清楚的是第二个计时器的第一个或第二个边沿是否触发了 HWiFxn、但它会导致至少一个 gptimerCallback 中断服务例程被覆盖/跳过。
我不认为 GPTimer TI 驱动程序适用于此类操作。 您能否尝试减少 gptimerCallback 中的处理、作为测试并评论这是否会改善行为? 您可能需要修改 CPTimerCC26XX.c 或将其用作参考、以便独立于 TI 驱动程序创建您的 HWI、从而进一步减少处理中断所花费的时间。
此致、
Ryan