STM8S103. Прерывание от ADC1

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Юрий48
Открыл глаза
Сообщения: 40
Зарегистрирован: Сб мар 20, 2021 23:31:54

STM8S103. Прерывание от ADC1

Сообщение Юрий48 »

Задача такая: Требуется запускать АЦП от переполнения TIM1 и результат преобразования считывать по прерыванию окончания преобразования. Настроить запуск АЦП от события переполнения таймера 1 мне, как я считаю, удалось. Этот вывод делаю из того, что если в бесконечном цикле делаю такую проверку:

Код: Выделить всё

if( ADC1_GetFlagStatus( ADC1_FLAG_EOC))
{
    resultat_ADC1 = ADC1_GetConversionValue(); //Читаем результат преобразования.
    GPIO_WriteReverse(GPIOD, GPIO_PIN_4);
    ADC1_ClearFlag( ADC1_FLAG_EOC);	  
}
, то вижу реальные результаты преобразования, синхронные с периодом переполнения. При этом инициализация глобального прерывания enableInterrupts(); закоментирована. Если её раскоментирую, то значения с АЦП больше не меняются, и в обработчик прерываний программа не попадает. Наверное, что-то ещё надо настраивать для обеспечения правильного прерывания. В моём понимании как будто всё правильно, отсюда и мыслей никаких нет. Хотел посмотреть приоритеты прерываний, но для ADC1 их не нашёл. Чтобы это значило?

Код: Выделить всё

main()
{	
    TIM1_PERIOD = GradazSdvig - 1;         // Период счета TIM1
    TIM1_PRECALER = (uint16_t)(CLK_HSI_RC / (4.0*f_Sig*(float)GradazSdvig)) - 1;   // Предделитель TIM1
    GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_FL_NO_IT);
    GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);

    clk_Config();
    //enableInterrupts();
    TIM1_Config();
    ADC1_Config();  

    while (1)
    {
        //result_ADC1 = ADC1_GetConversionValue();
        //ADC1_ClearFlag( ADC1_FLAG_EOC);
        if( ADC1_GetFlagStatus( ADC1_FLAG_EOC))
        {
            resultat_ADC1 = ADC1_GetConversionValue(); //Читаем результат преобразования.
            GPIO_WriteReverse(GPIOD, GPIO_PIN_4);
            ADC1_ClearFlag( ADC1_FLAG_EOC);  
        }
    }
}

static void TIM1_Config(void)
{
    TIM1_DeInit();
    TIM1_TimeBaseInit(TIM1_PRECALER, TIM1_COUNTERMODE_UP, TIM1_PERIOD, 0);

    /*TIM1_Pulse = CCR3_Val*/
    TIM1_OC3Init(
        TIM1_OCMODE_PWM1,
        TIM1_OUTPUTSTATE_ENABLE,
        TIM1_OUTPUTNSTATE_DISABLE,
        4,                    // ШИМ 4/8, отладка
        TIM1_OCPOLARITY_HIGH,
        TIM1_OCNPOLARITY_HIGH,
        TIM1_OCIDLESTATE_SET,
        TIM1_OCNIDLESTATE_RESET);

    /*TIM1_Pulse = CCR4_Val*/
    TIM1_OC4Init(
        TIM1_OCMODE_PWM1,
        TIM1_OUTPUTSTATE_ENABLE,
        Sdvig,
        TIM1_OCPOLARITY_LOW,
        TIM1_OCIDLESTATE_SET);
        
    //TIM1_UpdateDisableConfig (ENABLE);		// Enables or Disables the TIM1 Update event.
    TIM1_SelectOutputTrigger(TIM1_TRGOSOURCE_UPDATE); // Настройка выходного триггера таймера
    //TIM1_UpdateDisableConfig (ENABLE);		// Enables or Disables the TIM1 Update event.

    TIM1_CtrlPWMOutputs(ENABLE); // TIM1 Main Output Enable
    TIM1_Cmd(ENABLE); // TIM1 counter enable	
}

static void ADC1_Config(void)
{
    ADC1_DeInit();
    ADC1_Init( 
        ADC1_CONVERSIONMODE_SINGLE,  // Непрерывное преобразование
        ADC1_CHANNEL_3,                  // Канал 3, PD2    
        ADC1_PRESSEL_FCPU_D8,            //Prescaler selection fADC1 = fcpu/8, 2 мГц
        ADC1_EXTTRIG_TIM,        //  Conversion from Internal TIM1 TRGO event.
        ENABLE,              // Разрешение внешнего тактирования.
        //DISABLE,              // Разрешение внешнего тактирования.
        ADC1_ALIGN_RIGHT,        // Правое выравнивание
        ADC1_SCHMITTTRIG_CHANNEL3, //параметр выбирает вывод для включения или отключения SchmittTrigger, внутрисхемное отключения вывода от лишних узлов для предотвращения искажения конвертируемого сигнала.
        DISABLE); // Преобразование без триггера Шмидта. Относится к предыдущему параметрру
            
    //ADC1_Cmd(ENABLE);
    ADC1_ClearFlag( ADC1_FLAG_EOC);  
    ADC1_ITConfig( ADC1_IT_EOCIE, ENABLE); //Включаем прерывание от окончания преобразования.
    //enableInterrupts();                    // Разрешениие прерывания   
    //ADC1_StartConversion();
    //ADC1->CR1 = 1;
    //ADC1->CR1 = 1;
    //ADC1_ClearFlag( ADC1_FLAG_EOC); 
    ADC1_Cmd(ENABLE);		
}

INTERRUPT_HANDLER(ADC1_IRQHandler, 22)
{
    if( ADC1_GetFlagStatus( ADC1_FLAG_EOC))
    {
        resultat_ADC1 = ADC1_GetConversionValue(); //Читаем результат преобразования.
        ADC1_ClearFlag( ADC1_FLAG_EOC);
    }
}
Реклама
Аватара пользователя
Нефертити
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср дек 06, 2023 23:51:29
Откуда: 48

Re: STM8S103. Прерывание от ADC1

Сообщение Нефертити »

Попробую предположить, что бит UIF в TIM1_SR1 не очищаете в обработчике прерывания.
Относись к людям так, как хочешь, чтобы они относились к тебе.
Реклама
Юрий48
Открыл глаза
Сообщения: 40
Зарегистрирован: Сб мар 20, 2021 23:31:54

Re: STM8S103. Прерывание от ADC1

Сообщение Юрий48 »

Нефертити, очищается, собственно это видно из текста программы. Дело в том, что вообще в обработчик прерывания программа не заходит.
Аватара пользователя
Нефертити
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср дек 06, 2023 23:51:29
Откуда: 48

Re: STM8S103. Прерывание от ADC1

Сообщение Нефертити »

Тогда не знаю.
В RM про UIF написано "This bit is set by hardware on an update event. It is cleared by software."
Относись к людям так, как хочешь, чтобы они относились к тебе.
Реклама
Эиком - электронные компоненты и радиодетали
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: STM8S103. Прерывание от ADC1

Сообщение jcxz »

[uquote="Юрий48",url="/forum/viewtopic.php?p=4784213#p4784213"]

Код: Выделить всё

if( ADC1_GetFlagStatus( ADC1_FLAG_EOC))
{
    resultat_ADC1 = ADC1_GetConversionValue(); //Читаем результат преобразования.
    GPIO_WriteReverse(GPIOD, GPIO_PIN_4);
    ADC1_ClearFlag( ADC1_FLAG_EOC);	  
}
...
В моём понимании как будто всё правильно[/uquote]Даже не вникая в работу вызываемых вами функций (описания которых вы тоже как видно не прочитали) по этим 3-м строчкам видно, что это говнокод. Так как: 1) нет никакой синхронизации с ходом преобразований АЦП (нет проверки завершения преобразования); 2) некий "АЦП флаг" чистите от фонаря, в произвольное время, никак не связанное с процессом преобразований АЦП, а значит результаты преобразований будут иногда теряться (как фишка ляжет).

Начинать надо с прочтения документации тех функций, которые используете. Раз решили использовать их, а не читать RM.
Реклама
Юрий48
Открыл глаза
Сообщения: 40
Зарегистрирован: Сб мар 20, 2021 23:31:54

Re: STM8S103. Прерывание от ADC1

Сообщение Юрий48 »

jcxz, Если представленная Вами вырезка кода взята из while (1), то тогда, с тем о чём Вы говорит можно согласиться. Но реально его (кода) там нет, извините, что ввёл в заблуждение. Всё это делается в обработчике прерывания (см. конец кода). В этом случае Ваши заменчания остаются в силе? Если да, то как надо было сделать правильно?
Реклама
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: STM8S103. Прерывание от ADC1

Сообщение jcxz »

[uquote="Юрий48",url="/forum/viewtopic.php?p=4784612#p4784612"]Всё это делается в обработчике прерывания (см. конец кода). В этом случае Ваши заменчания остаются в силе? Если да, то как надо было сделать правильно?[/uquote]Нет, моё замечание было не про ISR.
Если говорить про ISR - как я понял у вас проблема: "в обработчик прерываний программа не попадает"?
На основании чего сделали такое заключение? Как отлаживаете - надеюсь под эмулятором на реальном МК? Разрешены ли прерывания в CPU? Правильно ли смаппирована таблица векторов прерываний? Разрешено ли прерывание в АЦП? Используются ли другие прерывания и работают ли они? Когда происходит "не попадание программы в ISR" в каком состоянии находятся флаги прерываний АЦП? И какой в это время текущий уровень приоритета прерываний CPU? какой приоритет установлен для прерывания АЦП?
Всё это следует проверить по регистрам STM8.

С МК я всегда работаю через регистры. И тем более - на STM8. Что означают все эти функции у вас и что они делают - понятия не имею. И вам советую работать через регистры, самостоятельно. Не надеясь на магические функции. STM8 - слишком примитивная платформа, чтобы работать с ним через какие-то "либы".

PS: и STM8 - это никаким местом не ARM.

Добавлено after 11 minutes 29 seconds:
[uquote="Юрий48",url="/forum/viewtopic.php?p=4784281#p4784281"]Нефертити, очищается, собственно это видно из текста программы. Дело в том, что вообще в обработчик прерывания программа не заходит.[/uquote]Вообще так и не понял - о каком обработчике прерываний тут идёт речь???... :?

Добавлено after 2 minutes 18 seconds:
[uquote="Нефертити",url="/forum/viewtopic.php?p=4784284#p4784284"]Тогда не знаю.
В RM про UIF написано "This bit is set by hardware on an update event. It is cleared by software."[/uquote]Не наблюдаю в коде ТС ни одного обработчика прерываний таймера. О каком обработчике и каком флаге UIF вы тогда ведёте речь?
Аватара пользователя
Нефертити
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср дек 06, 2023 23:51:29
Откуда: 48

Re: STM8S103. Прерывание от ADC1

Сообщение Нефертити »

Хотел намекнуть, что какой-то флаг не сбрасывается.
Гугл вообще говорит, что надо ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM, ENABLE);
Ответить

Вернуться в «ARM»