Embedded STM32L011D3红外发光二极管

Embedded STM32L011D3红外发光二极管,embedded,stm32,pwm,Embedded,Stm32,Pwm,我用STM32L011D3和LED制作了一块小电路板。我想使用38kHz的LED,占空比为50%。现在我将LED连接到mcu上的错误引脚,因此我不能直接将计时器用作PWM发生器。所以我试图在主回路中手动生成PWM信号。我认为这会起作用,因为我实际上没有在mcu上做任何其他事情 我配置了时钟,如下图所示: 定时器TIM2 I的配置如下图所示: 这意味着我应该有4MHz/4/26=38.461kHz 主循环当前看起来如下所示: 通过这种设置,我可以在37us开/关之间找到一些东西。时间安排不太

我用STM32L011D3和LED制作了一块小电路板。我想使用38kHz的LED,占空比为50%。现在我将LED连接到mcu上的错误引脚,因此我不能直接将计时器用作PWM发生器。所以我试图在主回路中手动生成PWM信号。我认为这会起作用,因为我实际上没有在mcu上做任何其他事情

我配置了时钟,如下图所示:

定时器TIM2 I的配置如下图所示:

这意味着我应该有4MHz/4/26=38.461kHz

主循环当前看起来如下所示:

通过这种设置,我可以在37us开/关之间找到一些东西。时间安排不太稳定


可能是因为我的led启用/禁用指令太长,无法在所有25us内执行,以获得稳定的pwm输出吗?

您在浪费时间读取输出-您设置了它,因此您已经知道它是什么:

for(;;)
{
    int out = (timer2Value >= 13) ? GPIO_PIN_SET : GPIO_PIN_RESET ;
    HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7, out ) ;
}
如果时间没有改变,那么问题更可能是你的时钟没有以你认为的频率运行

一个更确定的解决方案(不包括纠正硬件设计)是设置定时器以38000-1的间隔生成中断,并在中断处理程序中切换输出:

void TIM2_IRQHandler()
{
    static int out = 0 ;
    out = out ? 0 : 1 ;
    HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7, out ) ;
}
甚至只是:

void TIM2_IRQHandler()
{
    HAL_GPIO_TogglePin( GPIOA, GPIO_PIN_7 ) ;
}
如果您确实想要尽可能快的输出切换,那么您可以确定pin的位带地址并直接切换:

鉴于:

__IO uint32_t* getBitBandAddress( volatile const void* address, int bit )
{
    __IO uint32_t* bit_address = 0;
    uint32_t addr = reinterpret_cast<uint32_t>(address);

    // This bit maniplation makes the function valid for RAM
    // and Peripheral bitband regions
    uint32_t word_band_base = addr & 0xf0000000;
    uint32_t bit_band_base = word_band_base | 0x02000000;
    uint32_t offset = addr - word_band_base;

    // Calculate bit band address
    bit_address = reinterpret_cast<__IO uint32_t*>(bit_band_base + (offset * 32u) + (static_cast<uint32_t>(bit) * 4u));

    return bit_address ;
}
类似地,在中断中:

void TIM2_IRQHandler()
{
    static __IO uint32_t* gpioA7 = getBitBandAddress( &GPIOA->ODR, 7 ) ;

    *gpioA7 = !*gpioA7 ;
}

尽管您可能会选择在中断情况下从外部初始化
gpioA7

您在浪费时间读取输出-您设置了它,因此您已经知道它是什么:

for(;;)
{
    int out = (timer2Value >= 13) ? GPIO_PIN_SET : GPIO_PIN_RESET ;
    HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7, out ) ;
}
如果时间没有改变,那么问题更可能是你的时钟没有以你认为的频率运行

一个更确定的解决方案(不包括纠正硬件设计)是设置定时器以38000-1的间隔生成中断,并在中断处理程序中切换输出:

void TIM2_IRQHandler()
{
    static int out = 0 ;
    out = out ? 0 : 1 ;
    HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7, out ) ;
}
甚至只是:

void TIM2_IRQHandler()
{
    HAL_GPIO_TogglePin( GPIOA, GPIO_PIN_7 ) ;
}
如果您确实想要尽可能快的输出切换,那么您可以确定pin的位带地址并直接切换:

鉴于:

__IO uint32_t* getBitBandAddress( volatile const void* address, int bit )
{
    __IO uint32_t* bit_address = 0;
    uint32_t addr = reinterpret_cast<uint32_t>(address);

    // This bit maniplation makes the function valid for RAM
    // and Peripheral bitband regions
    uint32_t word_band_base = addr & 0xf0000000;
    uint32_t bit_band_base = word_band_base | 0x02000000;
    uint32_t offset = addr - word_band_base;

    // Calculate bit band address
    bit_address = reinterpret_cast<__IO uint32_t*>(bit_band_base + (offset * 32u) + (static_cast<uint32_t>(bit) * 4u));

    return bit_address ;
}
类似地,在中断中:

void TIM2_IRQHandler()
{
    static __IO uint32_t* gpioA7 = getBitBandAddress( &GPIOA->ODR, 7 ) ;

    *gpioA7 = !*gpioA7 ;
}

尽管您可能会选择在中断情况下从外部初始化
gpioA7

只需修补硬件或订购新的PCB?其他一切都是一个糟糕的解决方案。通过发布一张文本图片,任何人都无法将您的代码复制粘贴到答案中。不要那样做;它不鼓励回答,这对您没有帮助。您可以简单地测量调用
HAL\u GPIO\u WritePin
函数的持续时间,例如通过register
DWT\u CYCCNT
。我预计它需要几百个CPU周期,所以我们需要几个。这可能会在某种程度上扰乱你的算法,我认为你没有选择正确的实现方式。在中断模式下管理计时器,每次收到中断时,您都会切换LED。此外,如果您有计时问题,不要使用HAL,因为它速度非常慢,因为它管理所有可能的用例(4MHz和1.25MIPS/MHz),您有时间处理125条指令-如果要获得准确计时有点紧,这似乎足够了,尽管谁知道HAL中会发生什么样的开销,或者任何可能正在运行的中断?如果你想要精确的确定时间,你最好控制所有的代码,而不是使用所有的CubeMX bloatware?其他一切都是一个糟糕的解决方案。通过发布一张文本图片,任何人都无法将您的代码复制粘贴到答案中。不要那样做;它不鼓励回答,这对您没有帮助。您可以简单地测量调用
HAL\u GPIO\u WritePin
函数的持续时间,例如通过register
DWT\u CYCCNT
。我预计它需要几百个CPU周期,所以我们需要几个。这可能会在某种程度上扰乱你的算法,我认为你没有选择正确的实现方式。在中断模式下管理计时器,每次收到中断时,您都会切换LED。此外,如果您有计时问题,不要使用HAL,因为它速度非常慢,因为它管理所有可能的用例(4MHz和1.25MIPS/MHz),您有时间处理125条指令-如果要获得准确计时有点紧,这似乎足够了,尽管谁知道HAL中会发生什么样的开销,或者任何可能正在运行的中断?如果你想要精确的确定时间,你最好控制所有的代码,而不是使用所有的CubeMX bloatware。谢谢你的回答。明天当我有机会使用示波器时,我会检查一下。谢谢你的回答。明天当我有示波器的时候我会检查一下。