ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
4 мая
1514355 Топик полностью
framer (25.04.2025 21:40, просмотров: 180) ответил __LightElf на Мну полагает, что вот эти строки неправильны
чатгпт поставил +1 

🔍 Возможные проблемы:

Неправильная очистка флага прерывания (IR):

c

Copy

Edit

LPC_TIM2->IR |= BIT(4);

Регистр IR является регистрoм типа write-1-to-clear, поэтому правильный способ очистки флага должен выглядеть так:

c

Copy

Edit

LPC_TIM2->IR = BIT(4);

То же самое касается BIT(5). Использование |= может случайно установить другие биты, если в регистре IR уже есть значения.

Избыточное использование volatile для tm2_cr0 и tm2_cr1:

c

Copy

Edit

static volatile uint32_t tm2_cr0;

Ключевое слово volatile используется, когда значение переменной может изменяться извне (например, оборудованием или другим прерыванием). В данном случае это лишнее — переменные используются только внутри ISR и не изменяются снаружи. Лучше так:

c

Copy

Edit

static uint32_t tm2_cr0;

Проблемы синхронизации при чтении CR0, CR1:

Регистр CRx может изменяться динамически, особенно если источник сигнала внешний. Если прерывание задерживается, разность между CRx и tm2_crx может быть большой, что приведёт к ошибочному увеличению счётчика.

Ошибка в логике FIN_MIN_PERIOD:

Неизвестно, чему равен FIN_MIN_PERIOD. Если значение слишком большое или тип данных выбран неверно, сравнение может быть некорректным и импульсы не будут считаться.

Нет защиты от переполнения CR0/CR1:

Регистр CR0 и CR1 имеют ограниченную длину (например, 32 бита), и могут переполниться. Сравнение:

c

Copy

Edit

if (LPC_TIM2->CR0 - tm2_cr0 >= FIN_MIN_PERIOD)

работает корректно, если переменные типа uint32_t, но важно удостовериться, что логика переполнения учитывается.

Слишком длинный код внутри обработчика прерывания (ISR):

В ISR не рекомендуется выполнять много логики — здесь происходят сравнения, присваивания, инкременты... Если ISR работает слишком долго, можно потерять последующие прерывания.

✅ Рекомендуемая версия обработчика:

c

Copy

Edit

void TIMER2_IRQHandler(void)

{

static uint32_t tm2_cr0;

static uint32_t tm2_cr1;

// Обработка канала 0 (CR0)

if (LPC_TIM2->IR & BIT(4)) {

LPC_TIM2->IR = BIT(4); // Очистка флага

uint32_t now = LPC_TIM2->CR0;

if ((now - tm2_cr0) >= FIN_MIN_PERIOD) {

tm2_cr0 = now;

vars.fcntr[0]++;

}

}

// Обработка канала 1 (CR1)

if (LPC_TIM2->IR & BIT(5)) {

LPC_TIM2->IR = BIT(5); // Очистка флага

uint32_t now = LPC_TIM2->CR1;

if ((now - tm2_cr1) >= FIN_MIN_PERIOD) {

tm2_cr1 = now;

vars.fcntr[1]++;

}

}

}