STM32L011D3 ИК светодиодный - PullRequest
       50

STM32L011D3 ИК светодиодный

0 голосов
/ 08 октября 2019

Я построил небольшую плату с STM32L011D3 и светодиодом. Я хочу использовать светодиод на 38 кГц с рабочим циклом 50%. Теперь я подключил светодиод к неправильному выводу на MCU, поэтому я не могу использовать таймер в качестве генератора ШИМ напрямую. Поэтому я пытался генерировать сигнал ШИМ вручную в основном цикле. Я думал, что это будет работать, так как на самом деле я больше ничего не делаю на MCU.

Я настроил свои часы, как показано на рисунке ниже: clock configuration

ТаймерTIM2 Я настроил так, как показано на рисунке ниже: timer configuration

Так что это означает, что у меня должно быть 4MHz / 4/26 = 38,461 кГц

Основной цикл в настоящее время выглядит следующим образомэто: main loop

С этой настройкой я получаю что-то около 37us вкл / 37us off. Времена не очень стабильны.

Может ли быть так, что мои инструкции по включению / отключению светодиода слишком длинны для выполнения всех 25us, чтобы получить стабильный вывод ШИМ?

1 Ответ

2 голосов
/ 08 октября 2019

Вы тратите время на чтение выходных данных - вы установили его, так что вы уже знаете, что это такое:

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 ) ;
}

Если вы действительно хотите максимально быстрое переключение выхода, то вы можете определить адрес битовой полосыПин и и переключите это непосредственно:

Дано:

__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 ;
}

Тогда:

__IO uint32_t* gpioA7 = getBitBandAddress( &GPIOA->ODR, 7 ) ;
for(;;)
{
    gpioA7 = (timer2Value >= 13) ;
}

Аналогично в прерывании:

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

    gpioA7 = !gpioA7 ;
}

ХотяВы можете инициализировать gpioA7 извне в случае прерывания.

...