亲,“电路城”已合并升级到更全、更大、更强的「新与非网」。点击查看「新与非网」

本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

基于EK-TM4C123GXL的扩频相控阵声呐

发布时间:2022-10-31
分享到:

基于EK-TM4C123GXL的扩频相控阵声呐

发布时间:2022-10-31
分享到:

在其他声学项目成功的激励下,一个声纳项目跃入我的脑海。

相控阵声纳的工作原理与相控阵雷达相同,而不是旋转传感器看方向。这是通过组合来自一组固定传感器的信号,每个传感器都有不同的相位。通常使用大量(100多个)传感器。在天体物理学中,它们是随机分布的。本项目只使用了两个超声波接收器。只使用一台发射机。

现有的HC-SR04发出8个40kHz脉冲。在这个项目中,我将它替换为二进制相移键(BPSK) m序列,每个键由5个脉冲组成。这具有更好的信号特性。

现有HC-SR04信号
下面的图表来自未修改的HC-SR04

你可以看到,在max232芯片完成发送8个脉冲到换能器后,换能器如何继续共振。

新的声纳脉冲
下面是使用值(-1,1,-1,-1,1,1,1)的m序列的二进制相移键信号。如果你看得足够近,你可以看到相位的变化。

它比原来的8个脉冲长得多,这影响了它的最小范围。

这是它进入传感器时的样子

这是它收到时的样子(红框内)

之所以你能在接收到的信号中看到三个灯泡是因为相位的变化。你之前看到的三个灯泡是通过PCB传输的。在未被黑的HC-SR04中,比较器是关闭的,所以它看不到这一点。

发射台上产生信号
脉冲序列和到max232芯片的电源是使用发射台上的pwm产生的。其中一个PWM产生40khz载波,而另一个产生8Khz相位调制,根据m序列的当前状态是-ve或+ve,它反转40khz载波PWM信号。您可以查看代码,了解具体是如何完成的。

HC-SR04
在其中一台hc - sr04上,我简单地拆卸了CPU,并插入跳线以访问T1IN和T2IN,并为MAX232芯片供电。我还访问了接收信号后所有运放放大器,但之前它进入比较器(白线)。有点乱。在另一个HC-SR04上,我只是访问这个样本接收信号。

发射台
发射台工作在3.3V,而HC-SR04工作在5v,所以我使用标准的MOSFET基于电平转换器PCB转换信号。我发现10K欧姆的引体向上引入了太多的回转,所以我补充了2.2K欧姆的引体向上。不过我不确定它是否真的需要,但在示波器上看起来更好。

lm324芯片上第三个运放的输出连接到发射台上的模拟数字转换器。信号必须重新偏压,以适应发射台使用电阻分压器网络。56K欧姆是任意使用的,它们只需要是高的值。使用10uF陶瓷是因为这是无极化陶瓷帽的最大值。

处理输入
来自HC-SR04模块的信号进入发射台上的两个模拟到数字转换器。它经过一个叫做I/Q调制器的阶段。假设我们使用的是二进制而不是正交相位调制意味着我们每一秒都要乘以- 1。同样,您可以查看代码,以确切了解这是如何完成的。

你可以分辨出m序列逐渐变大的驼峰。你也可以看到一个和另一个是180度的相位差。

以下是原始10个脉冲的解调图,供参考:

解调之后是与m序列的相关。它不是一个尖峰,但仍然是一个高峰。这种相关性给出了目标的范围。

相控阵
相控阵的工作原理是将两个输入的和与相位差相关联。相位差通过强化信号有效地工作。产生最高值的相关性表示指向目标的方向。下图显示了两组65个相关性。一个瓶子在位置A,另一个在位置b,你可以看到为什么通常这样的相控阵设置有很多传感器。

瓶子的位置:

增加范围
随着“更好的信号”而来的是更高性能的信号。这是4.6米高的墙壁反射后的相关图

main.c:

/*
Copyright(c) 2015 Graham Chow

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "inc/hw_types.h"
#include "inc/hw_adc.h"
#include "driverlib/fpu.h"
#include "driverlib/pin_map.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "driverlib/rom.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/udma.h"
#include "driverlib/uart.h"
#include "inc/hw_pwm.h"
#include "usblib/usblib.h"
#include "usblib/usbhid.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdcomp.h"
#include "usblib/device/usbdhid.h"
#include "usblib/device/usbdhidmouse.h"
#include "usblib/device/usbdhidkeyb.h"
#include "driverlib/pwm.h"
#include "utils/uartstdio.h"
#include "utils/ustdlib.h"
#include "global_defs.h"

///////////////////////////////////////////////////////////////////////////////
// ADC stage
//
static int32_t g_adcPing[NUM_CHANNELS];
static int32_t g_adcPong[NUM_CHANNELS];
static volatile uint32_t g_ui32DMAErrCount = 0;
static int16_t g_filterBuffer0[BUFFER_SIZE] = { 0 };
static int16_t g_filterBuffer1[BUFFER_SIZE] = { 0 };
static int16_t *g_filterInPtr0 = g_filterBuffer0;
static int16_t *g_filterInPtr1 = g_filterBuffer1;
static int16_t g_peak[OFFSET_COUNT * 2 + 1][BUFFER_SIZE - MSEQ_SIZE*BURST_COUNT*2];
static int32_t g_offset_peak[OFFSET_COUNT * 2 + 1];


static volatile bool g_filled[2] = { false, false };

// end of adc stage
static volatile PROCESSING_STATE g_processing_state = PROCESSING_STATE_WAITING;

// pwm
static uint32_t g_ui32PWMClock;
static uint32_t g_ui32Load0;
static uint32_t g_ui32Load1;
static int16_t g_mseq[MSEQ_SIZE] = { -1, 1, -1, -1, 1, 1, 1};
//static int16_t g_mseq[MSEQ_SIZE] = { 1, 1, 0, 0, 0, 0, 0 };
static int8_t g_pulse_count = CHARGE_ON_START;


void ConfigureUART(void);
void InitADC00(void);
void ConfigurePwm(void);
void PWM_0_1_IntHandler(void);
void InvertPwmOutput(bool invert);
void ZeroOutput();

// uDMA control table aligned to 1024-byte boundary
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];


/*
 * main.c
 */
int main(void) {
    
    ROM_FPULazyStackingEnable();

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    // configure dma
    ROM_SysCtlPeripheralClockGating(true);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
    ROM_IntEnable(INT_UDMAERR);
    ROM_uDMAEnable();
    ROM_uDMAControlBaseSet(pui8ControlTable);

    // configure A/D converter, use AIN4 PD3

    InitADC00();
    ConfigurePwm();
    ConfigureUART();

    UARTprintf("Going...\n");

    IntMasterEnable();


    while(true)
    {
        if(g_processing_state == PROCESSING_STATE_PROCESSSING)
        {
            int i, j, k;
            for(k=-OFFSET_COUNT;k<=OFFSET_COUNT;k++)
            {

                int o0, o1;
                if(k < 0)
                {
                    o0 = -k/2;
                    o1 = 0;
                }
                else if(k > 0)
                {
                    o0 = 0;
                    o1 = k/2;
                }
                int16_t *ptrb0 = g_filterBuffer0 + o0;
                int16_t *ptrb1 = g_filterBuffer1 + o1;
                int16_t *ppeak = g_peak[k+OFFSET_COUNT];

                int max_index = -1;
                int max_sum = -1;
                for(i=0;i<BUFFER_SIZE-MSEQ_SIZE*BURST_COUNT*2-OFFSET_COUNT/2;i++)
                {
                    int32_t sum0 = 0;
                    int32_t sum1 = 0;
                    int16_t *ptr0 = ptrb0;
                    int16_t *ptr1 = ptrb1;
                    int16_t *seq = g_mseq;

                    for(j=MSEQ_SIZE;j>0;j--)
                    {
                        int16_t ms = *seq++;

                        sum0 += ms * (*ptr0++);
                        sum0 += ms * (*ptr0++);

                        sum0 += ms * (*ptr0++);
                        sum0 += ms * (*ptr0++);

                        sum0 += ms * (*ptr0++);
                        sum0 += ms * (*ptr0++);

                        sum0 += ms * (*ptr0++);
                        sum0 += ms * (*ptr0++);

                        sum0 += ms * (*ptr0++);
                        sum0 += ms * (*ptr0++);


                        sum1 += ms * (*ptr1++);
                        sum1 += ms * (*ptr1++);

                        sum1 += ms * (*ptr1++);
                        sum1 += ms * (*ptr1++);

                        sum1 += ms * (*ptr1++);
                        sum1 += ms * (*ptr1++);

                        sum1 += ms * (*ptr1++);
                        sum1 += ms * (*ptr1++);

                        sum1 += ms * (*ptr1++);
                        sum1 += ms * (*ptr1++);

                    }
                    ptrb0++;
                    ptrb1++;

                    int sum = ((k & 0x1) == 0) ? (sum0 + sum1) : (sum0 - sum1);
                    *ppeak++ = sum >> 2;

                    if(sum > max_sum)
                    {
                        max_sum = sum;
                        max_index = i;
                    }
                }
                g_offset_peak[k + OFFSET_COUNT] = max_index;
            }
            g_processing_state = PROCESSING_STATE_WAITING;
        }
    }

}

//*****************************************************************************
//
// Configure the UART and its pins.  This must be called before UARTprintf().
//
//*****************************************************************************
void ConfigureUART(void)
{
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART mode.
    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}


void InitADC00(void)
{
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    ROM_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3); // AIN4
    ROM_GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2); // AIN5

    ROM_ADCHardwareOversampleConfigure(ADC0_BASE, HW_AVERAGE);
    ROM_ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH4);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH5);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH4);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH5);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH4);
    ROM_ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH5|ADC_CTL_IE|ADC_CTL_END);
    ADCSequenceDMAEnable(ADC0_BASE, 0);

    // adc 0
    ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
                                    UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);

    ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                            UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 |
                              UDMA_ARB_8);

    ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                            UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 |
                              UDMA_ARB_8);

    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *) (ADC0_BASE + ADC_O_SSFIFO0),
                               (void *)&g_adcPing[0], NUM_CHANNELS);

    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *) (ADC0_BASE + ADC_O_SSFIFO0),
                               (void *)&g_adcPong[0], NUM_CHANNELS);
    // both
    ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC0);

    ROM_ADCIntClear(ADC0_BASE, 0);
    ROM_ADCIntEnable(ADC0_BASE, 0);
    ROM_IntEnable(INT_ADC0SS0);
    //ADCSequenceEnable(ADC0_BASE, 0);
}


void uDMAErrorHandler(void)
{
    uint32_t ui32Status;
    ui32Status = ROM_uDMAErrorStatusGet();
    if(ui32Status)
    {
        ROM_uDMAErrorStatusClear();
        g_ui32DMAErrCount++;
    }
}

// ADC interrupt handler. Called on completion of uDMA transfer
// reduce sample rate to 1000000/(4*3) = 83333.3
void ADC00IntHandler(void)
{
    uint32_t ui32ModeP;
    uint32_t ui32ModeA;
    int32_t *ptr;


    ROM_ADCIntClear(ADC0_BASE, 0);

    ui32ModeP = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);
    if(ui32ModeP == UDMA_MODE_STOP)
    {
        ptr = g_adcPing;
        int16_t sum0 = *ptr++;
        int16_t sum1 = *ptr++;
        sum0 += *ptr++;
        sum1 += *ptr++;
        sum0 += *ptr++;
        sum1 += *ptr++;
        sum0 -= 0x800 * 3;
        sum1 -= 0x800 * 3;
        *g_filterInPtr0++ = sum0;
        *g_filterInPtr1++ = sum1;
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *) (ADC0_BASE + ADC_O_SSFIFO0),
                                   (void *)&g_adcPing[0], NUM_CHANNELS);
        ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    }
    else
    {
        ui32ModeA = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
        if(ui32ModeA == UDMA_MODE_STOP)
        {
            ptr = g_adcPong;

            int16_t sum0 = *ptr++;
            int16_t sum1 = *ptr++;
            sum0 += *ptr++;
            sum1 += *ptr++;
            sum0 += *ptr++;
            sum1 += *ptr++;
            sum0 -= 0x800 * 3;
            sum1 -= 0x800 * 3;
            *g_filterInPtr0++ = -sum0;
            *g_filterInPtr1++ = -sum1;

            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *) (ADC0_BASE + ADC_O_SSFIFO0),
                                       (void *)&g_adcPong[0], NUM_CHANNELS);
            ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC0);
        }
    }
    if(g_filterInPtr0 >= &g_filterBuffer0[BUFFER_SIZE])
    {
        g_filterInPtr0 = &g_filterBuffer0[0];
        g_filterInPtr1 = &g_filterBuffer1[0];
        g_processing_state = PROCESSING_STATE_PROCESSSING;
        ADCSequenceDisable(ADC0_BASE, 0);
    }
}

void ConfigurePwm(void)
{
    // configure pwm
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_4);
    GPIOPinConfigure(GPIO_PB6_M0PWM0);
    GPIOPinConfigure(GPIO_PB7_M0PWM1);
    GPIOPinConfigure(GPIO_PB4_M0PWM2);

    g_ui32PWMClock = SysCtlClockGet() / 1;

    g_ui32Load0 = (g_ui32PWMClock / PWM_CARRIER_FREQUENCY) - 1;
    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC |  PWM_GEN_MODE_DBG_STOP);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, g_ui32Load0);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, g_ui32Load0 / 2);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, g_ui32Load0 / 2);

    PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, false);
    PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false);
    PWMOutputUpdateMode(PWM0_BASE, PWM_OUT_0_BIT, PWM_OUTPUT_MODE_SYNC_LOCAL);
    PWMOutputUpdateMode(PWM0_BASE, PWM_OUT_1_BIT, PWM_OUTPUT_MODE_SYNC_LOCAL);
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);

    //g_ui32Load1 = (g_ui32PWMClock / PWM_PHASE_CHANGE_FREQUENCY) - 1;
    g_ui32Load1 = (g_ui32Load0) * BURST_COUNT;
    //g_ui32Load1 = 400;
    PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC |  PWM_GEN_MODE_DBG_STOP);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, g_ui32Load1);
    // 384
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, (g_ui32Load1 / 2) - 429);
    // for 5, use ?
    // for 7, use ?
    // for 9, use 429
    PWMOutputState(PWM0_BASE, PWM_OUT_2_BIT, false);
    PWMOutputUpdateMode(PWM0_BASE, PWM_OUT_2_BIT, PWM_OUTPUT_MODE_SYNC_LOCAL);
    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_1, PWM_INT_CNT_AD);
    PWMGenEnable(PWM0_BASE, PWM_GEN_1);

    ZeroOutput();

    IntEnable(INT_PWM0_1);


    PWMSyncTimeBase(PWM0_BASE, PWM_GEN_0 | PWM_GEN_1);

    // configure timer
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);

    uint32_t ui32Period = (SysCtlClockGet() / 2) / 2;
    TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period -1);

    IntEnable(INT_TIMER0A);
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerEnable(TIMER0_BASE, TIMER_A);
}

void PWM_0_1_IntHandler(void)
{
    PWMGenIntClear(PWM0_BASE, PWM_GEN_1, PWM_INT_CNT_AD);
    if(g_pulse_count >= MSEQ_SIZE)
    {
        if(g_pulse_count == TURN_ON_A2D)
        {
            g_pulse_count = CHARGE_ON_START;
            PWMIntDisable(PWM0_BASE, PWM_INT_GEN_1);
            g_processing_state = PROCESSING_STATE_COLLECTING;
            g_filterInPtr0 = &g_filterBuffer0[0];
            g_filterInPtr1 = &g_filterBuffer1[0];
            ADCSequenceEnable(ADC0_BASE, 0);
        }
        else
        {
            if(g_pulse_count == MSEQ_SIZE)
            {
                PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT, false);
                // disable the power
                GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 4);
                ZeroOutput();
            }
            g_pulse_count++;
        }
    }
    else
    {
        if(g_pulse_count >= 0)
        {
            if(g_pulse_count == 0)
            {
                PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT, true);
            }
            int sig = g_mseq[g_pulse_count];
            if(sig == 0)
            {
                ZeroOutput();
            }
            else
            {
                PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT, true);
                InvertPwmOutput(sig == -1);
            }
            //invert = false;

        }
        else if(g_pulse_count == CHARGE_ON_START)
        {
            ZeroOutput();
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); // PF2
        }
        g_pulse_count++;
    }
}

void InvertPwmOutput(bool invert)
{
    HWREG(PWM0_BASE + PWM_O_INVERT) = ((invert) ? PWM_OUT_0_BIT : PWM_OUT_1_BIT);
}

void ZeroOutput()
{
    HWREG(PWM0_BASE + PWM_O_INVERT) = 0; //PWM_OUT_0_BIT | PWM_OUT_1_BIT;
    PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT, false);
}

void Timer0IntHandler(void)
{
    // Clear the timer interrupt
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    if((g_pulse_count == CHARGE_ON_START) && (g_processing_state == PROCESSING_STATE_WAITING))
    {
        g_processing_state = PROCESSING_STATE_SEND_PULSE;
        PWMSyncTimeBase(PWM0_BASE, PWM_GEN_0 | PWM_GEN_1);
        PWMIntEnable(PWM0_BASE, PWM_INT_GEN_1);
    }
}

如果您对此项目有任何想法、意见或问题,请在下方留言。

以上内容翻译自网络,原作者:Graham Chow,如涉及侵权,可联系删除。

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论