Мне нужно знать, почему мои прерывания не работают здесь - PullRequest
0 голосов
/ 24 сентября 2019

Я использую stm8l - обнаружение, и я создал код для переключения светодиода на каждую 1 секунду, используя таймер (TIM1), но это не работает должным образом.Я что-то упустил здесь в моей конфигурации

Я мог войти в функцию прерывания в первый раз, но после этого она не входит в функцию прерывания.Кто-нибудь, пожалуйста, посмотрите и помогите мне

enter code here
#include <iostm8l.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"

unsigned int count = 0;

@svlreg @interrupt void TIM1(void)
{
count += 1;
TIM1_SR1 &= ~(0x01);
}

main()
{
CLK_DIVR = 0x00; // Set the frequency to 16Mhz
CLK_PCKENR2 = 0x02; // clock for timer1
PC_DDR = 0x80; // direction output for led
PC_CR1 = 0x80; // fast push pull mode
PE_DDR = 0x80; // direction output for led
PE_CR1 = 0x80; // fast push pull mode
TIM1_PSCRH = 0x3e; //to create a frequency for 1000 hz
TIM1_PSCRL = 0x80; // so prescalar is 16000
TIM1_CR1 = 0x01;
TIM1_IER = 0x01;
_asm("rim\n");
while(1)
{

    if (count == 1000)
    {
        PE_ODR ^= 0x80;
        count = 0;
    }
}
}

Прерывание входит только один раз, но после этого оно не входит.Таким образом, переменная "count" остается в значении 1

1 Ответ

1 голос
/ 25 сентября 2019
  • Вы используете магические числа для битовых масок вместо определенных констант, поэтому код чертовски труден для вас и меня обоих.Измените это так, чтобы код заканчивался как, например,

    TIM1_SR1 &= ~TIM1_SR1_UIF;

  • Так как это 8-битный MCU, абсолютно необходимо, чтобы вы u суффиксвсе целочисленные константы, или они будут иметь тип со знаком int, который вам не нужен.

    Например, этот код TIM1_SR1 &= ~(0x01); эквивалентен TIM1_SR1 &= -2.Очень легко писать случайные тонкие ошибки таким образом.Я рекомендую изучить Правила продвижения неявного типа .

    Настоятельно рекомендуется дизассемблировать каждый ISR, который вы пишете, чтобы увидеть, какой машинный код вы на самом деле получите, и пройти через отладчик, одновременно просматривая регистр.Этот конкретный регистр, кажется, игнорирует запись в него 1, так что вы можете просто сделать TIM1_SR = TIM1_SR1_UIF;.Неправильно очищенные флаги таймера внутри ISR - одна из самых распространенных ошибок во встроенных системах.

  • Цитирование руководства:

    UIF: Обновить флаг прерывания
    - При переполнении или понижении, если UDIS = 0 в регистре TIM1_CR1
    - Когда CNT повторно инициализируется программным обеспечением с использованием бита UG в регистре TIM1_EGR, если URS = 0 и UDIS = 0 в регистре TIM1_CR1.
    -Когда CNT повторно инициализируется событием триггера (см. Описание регистра TIM1_SMCR), если URS = 0 и UDIS = 0 в регистре TIM1_CR1

    Ваш код не выполняет никаких действийэто, так что вполне безопасно предположить, что счетчик таймера не сброшен.

  • Другая проблема заключается в том, что count должен быть объявлен как volatile, иначе компилятор может оптимизироватьэтот код полностью:

    if (count == 1000)
    {
        PE_ODR ^= 0x80;
        count = 0;
    }
    
...