Jump to content
Илья Болдырев

Не работает прерывание по таймеру в F411

Recommended Posts

Сделал два прерывания на кнопку и на таймер. Нажатие кнопки прекрасно обрабатывается. А вот с таймером проблемы. Решил потетстить свою настройку RCC, т.к. она не хочет работать корректно, ну или мне так кажется, но наткнулся еще на одну проблему. Код:

void exti_init()
{
    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
    SYSCFG->EXTICR[3] |=
        SYSCFG_EXTICR1_EXTI0_PA;
    EXTI->RTSR |=
        EXTI_RTSR_TR0;
    EXTI->PR =
        EXTI_PR_PR0;
    EXTI->IMR |= EXTI_IMR_MR0;
    NVIC_EnableIRQ( EXTI0_IRQn );
    NVIC_SetPriority( EXTI0_IRQn, 14 );
//    NVIC_EnableIRQ ( RCC_IRQn );
//    NVIC_SetPriority( RCC_IRQn, 10 );

    __enable_irq();
}

void RCC_Init(void )
{
    SET_BIT( RCC->CR, RCC_CR_HSEON );

    while ( READ_BIT( RCC->CR, RCC_CR_HSERDY == RESET ) );

    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_0WS;

    SET_BIT( RCC->PLLCFGR, RCC_PLLCFGR_PLLM_2 );
    SET_BIT( RCC->PLLCFGR, RCC_PLLCFGR_PLLM_3 );

    SET_BIT( RCC->PLLCFGR, RCC_PLLCFGR_PLLN_5 );
    SET_BIT( RCC->PLLCFGR, RCC_PLLCFGR_PLLN_6 );

    SET_BIT( RCC->PLLCFGR, ~RCC_PLLCFGR_PLLP_Pos );

    SET_BIT( RCC->CFGR, RCC_CFGR_PPRE2_DIV1 );
    SET_BIT( RCC->CFGR, RCC_CFGR_PPRE1_DIV2 );
    SET_BIT( RCC->CFGR, RCC_CFGR_HPRE_DIV1 );
    SET_BIT( RCC->CR, RCC_CR_PLLON );

    while ( READ_BIT( RCC->CR, RCC_CR_PLLRDY == RESET ) );

    SET_BIT( RCC->CFGR, RCC_CFGR_SW_PLL );

    while ( READ_BIT( RCC->CR, RCC_CFGR_SWS_1 == RESET ) );
}

GPIO_init(void )
{
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;

    GPIOC->MODER |= GPIO_MODER_MODER13_0;
    GPIOA->MODER &= ~GPIO_MODER_MODER0_0;
    GPIOA->MODER &= ~GPIO_MODER_MODER0_1;
    SET_BIT( GPIOA->PUPDR, GPIO_PUPDR_PUPD0_0 );
}

TIM2_init(void){
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    TIM2->PSC = 8000-1;
    TIM2->ARR = 1000-1;

    TIM2->DIER |= TIM_DIER_UDE;
    TIM2->CR1 |= TIM_CR1_CEN;

    NVIC_EnableIRQ(TIM2_IRQn);
    NVIC_SetPriority(TIM2_IRQn, 13);
}

int main( void )
{
//    RCC_Init();
    GPIO_init();
    TIM2_init();
    exti_init();
    while ( 1 )  {

    }
}

void RCC_IRQHandler()
{

}

void EXTI0_IRQHandler( void )
{
    if ( EXTI->PR & EXTI_PR_PR0 ) {
        EXTI->PR = EXTI_PR_PR0;

    GPIOC->ODR ^= GPIO_ODR_ODR_13;
   }
}

void TIM2_IRQHandler(void)
{
    TIM2->SR = TIM_SR_UIF;

    GPIOC->ODR ^= GPIO_ODR_ODR_13;
}

 

Share this post


Link to post
Share on other sites
Posted (edited)

Из-за буферизации регистров ARR PSC нужно сделать Update вручную TIM2->EGR = TIM_EGR_UG; 

Ну и TIM2->DIER |= TIM_DIER_UDE; это запрос на ДМА нужно TIM2->DIER  = TIM_DIER_UIE;

Edited by MasterElectric

Share this post


Link to post
Share on other sites

Популярные пружинные клеммники Degson со склада Компэл

Пружинные разъемные клеммники Degson с технологией Push-In обеспечивают надежное и безопасное электрическое соединение. При их использовании исключается возможность короткого замыкания в точке контакта, что гарантирует надежное соединение. Электрическая безопасность клеммных блоков подтверждается соответствием мировым стандартам UL, IEC и VDE.
Подробнее

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

    • А такой не пробовал ?
    • 1) Полтора литра, или от 1 до 5 л? 2) Зачем минимальные размеры платы, если БП по определению будет намного больше? Смысл в минимизации? 3) Место Вашей локализации?
    • Привет, мой друг, почему ты не сказал, что думаешь о схеме, но пришел напасть на меня из-за языка? Я говорю на четырех языках: английском, арабском, курдском и турецком. Спасибо.
    • Хочу попросить совета. У меня С1-65А, он рабочий, но внезапно вылезла такая неисправность. При включении он стал показывать ВЧ меандр. Что могло выйти со строя, что бы постоянно на экране мог появиться высокочастотный сигнал. Схема у меня есть. Хотелось бы получить подсказку "бывалых" опытных товарищей где искать данную "подлянку". Опыта по ремонту осциллографов у меня нет. Ими до настоящего времени только пользовался. Другие аппараты ремонтирую без проблем.  Надеюсь,  что кто то откликнется на мою просьбу, буду признателен за любую помощь. 
    • Житель британского города Ньюпорт Джеймс Хауэллс (James Howells), прославившийся тем, что случайно выбросил жёсткий диск с 7500 биткоинами, объявил о новом этапе поисков. Он хочет отыскать HDD на свалке при помощи искусственного интеллекта и сканеров. Об этом он рассказал The Sun. Хауэллс случайно выкинул жёсткий диск с криптовалютой в 2013 году. На HDD хранилось 7,5 тысяч биткоинов. На тот момент стоимость каждого токена составляла около $1250, что в сумме давало более $9 млн. На сегодняшний день их общая стоимость превысила $240 миллионов. Несмотря на многолетние безуспешные поиски, он не оставляет надежд отыскать его на свалке.  Теперь британец объявил о новом этапе поисков диска. Хауэллс сузил область поисков до 200 квадратных метров свалки, глубина которой составляет около 15 метров. Он хочет проверить необходимый объём мусора при помощи искусственного интеллекта. Суммарно ему предстоит обыскать от 300 до 400 тысяч тонн мусора. Несмотря на планирование, власти не разрешают ему провести раскопки мусора. По их мнению, запланированная процедура может обойтись в миллионы фунтов. Кроме этого, это может произвести «необратимое воздействие на окружающую среду». В ответ Хауэллс предложил заплатить правительству 55 миллионов фунтов стерлингов (около $76 миллионов) за проведение работ. Удастся ли ему урегулировать этот вопрос с правительством, пока неясно. https://3dnews.ru/1044126/britanets-vibrosivshiy-hdd-s-7500-bitkoinami-ishchet-pomoshchi-u-ii-i-hochet-prosvetit-pomoyku-rentgenom
    • думаю это он  и бэйджик с трупа снял и на шею повесил
    • эх жаль(( Спасибо!! Как-то даже и не экспериментировал с форматом..
  • Similar Content

    • By 9Klima
      Здравствуйте обитатели форума, вернулся к кодингу и на форум после лет 12 паузы.
      взялся за STM8 перед тем как штурмовть стм32 там уже получил по лбу когда-то и откотился.
      суть вопроса сконфигурировал второй таймер. второй канал на кристале STM8S103F3  как ШИМ1 всё класно работает гордость за не напрасно потраченное время на дробления  RM0016.
      наступил момент написания библиотеки для удобности обращения с шимом и тут началась эпопея:
      Сначала как посчитать что загрузить чтобы получить желаемую частоту, потом проверка всё на осциллограммах и тут на меня приходит озарение что наверное что то не так, временные интервалы до частоты 122Hz рросчитываются и совпадают.
      А после просто треш : тактовая частота HSI 16 000 000 без делителей прямо на вход таймера.
      PSCR =0;  ARR=65535;   Fout=244Hz
      PSCR =1;  ARR=65535;   Fout=121Hz
      PSCR =2;  ARR=65535;   Fout=60Hz
      PSCR =3;  ARR=65535;   Fout=30Hz
      PSCR =4;  ARR=65535;   Fout=15Hz
      PSCR =5;  ARR=65535;   Fout=7,59Hz
      PSCR =6;  ARR=65535;   Fout=3,8Hz
      PSCR =7;  ARR=65535;   Fout=1,91Hz
      PSCR =8;  ARR=65535;   Fout=0,98Hz
      Вроде всё гармонично но по факту както у меня не сошлось с расчётами. Там где должно быть 80 там 60. Я понимаю что встроенный генератор не блещет стабтильностью но всё равно что-то с расчётами не так либо я вообще не знаю что делаю не так.
      Fout= Fтактирования/([PSCR]+1)/([ARR]+1) тз сих выходит:
      PSCR =8;  ARR=65535;   Fout=???Hz
      16 000 0000/9/65536/=27Hz
      Что не так? где лыжи не едут?
      чувствую нужно срочно заказать частотомер для измерения до чёрто знаков дабы  невроз не лечить.
       
       
       
    • By Alex_fish
      Здравствуйте.
      Захотел я посмотреть как на Arduino Uno (mega328P С кварцем на 16МГц) можно сделать простой генератор меандра, библиотечными digitalWrite() и delay() она начала привирать частоту гдето от 1-2кГц, решил написать на обычном Си.
      Взял таймер TIM1 с тактировкой от 16МГц с прерыванием по совпадению, и в прерывании обнулял счетчик и просто переключал ножку.
      interrupt [TIM1_COMPA] void timer1_compa_isr(void) { static unsigned char flag=0;//флаг лог. уровня пина TCNT1H=0x00;//обнуляем счетчик таймера TCNT1L=0x00; // Place your code here if (flag==0){ PORTB = 0x01;//лог 1 flag=1; } else { PORTB = 0x00;//лог 0 flag=0; } } Ожидал что работа с таймером и прерываниями отъест тактов 30-50, на отработку прерывания, заход и выход из него, один if и т.п. И будет у меня максимум килогерц 300 а дальше пойдет врать частоту.  Но был удивлен тем что такая система начала привирать частоту уже на 10кГц, где давала 9.7кГц, а на 20кГц уже показывала 19кГц. (проверял точность осцилом).
      Вот и вопрос неужели таймер с прерыванием настолько медленные ? или я что-то делаю не так ?
      Полный код на Си если нужно прикреплен.
       
      boroda.c
    • By xopkep
      Путем писания пятой точкой, сообразил такую версию кода:
      Оно все работает, при условии, что подключен USBasp и он (USBasp) воткнут в усб компьютера. При отсутствии программатора происходит следующее: Запуск - Езернет инит - отправка данных на народмон - вывод на дисплей - всё, тут всё виснет. Т.е. отображаются данные на момент вывода и не происходит более ни отправки ни обновления на дисплее.
      Что делать, чтобы не зависало без программатора?
      Добавлю. Если убрать код анемометра целиком (прерывания и обсчет и вывод) - зависает реже (а может и не зависнуть). В чем ошибка?
    • By graf_alex
      Всем привет!
      Разбираюсь с подключением AVR к USB с использованием библиотеки V-USB на стороне контроллера и средствами hid.dll на стороне винды.
      Идея сделать дебажный вывод (строк) на комп через USB.
      Покопавшись пару дней смог доставать сообщения из контроллера через GET_REPORT. Следущий этап - USB прерывания. Да, я знаю что USB это хост ориентированый протокол и то, что через Interrupt In можно прокачать только 8 байт. Поэтому когда мне необходимо отправить сообщение в сторону компа я посылаю "пустое" прерывание, которое сигнализирует хосту что неплохо было бы данные забрать.
      Код со стороны контроллера (интересные его части)

      typedef struct { uchar reportID; uchar msgLen; char message[30]; } debugMsg_t; const uchar DEBUG_INT_MSG_ID = 1; const uchar DEBUG_MESSAGE_ID = 2; const PROGMEM char usbHidReportDescriptor[] = { 0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop) 0x09, 0x01, // USAGE (Vendor Usage 1) 0xa1, 0x01, // COLLECTION (Application) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) // The message data 0x85, DEBUG_MESSAGE_ID, // REPORT_ID (2) 0x95, sizeof(debugMsg_t)-1, // REPORT_COUNT (31) - extra byte for ReportID 0x09, 0x00, // USAGE (Undefined) 0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf) // Interrupt (with no data inside) indicates that data is available at debugMsg_t report 0x85, DEBUG_INT_MSG_ID, // REPORT_ID (1) 0x95, 0x01, // REPORT_COUNT (7) - Fake 0x09, 0x00, // USAGE (Undefined) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0 // END_COLLECTION }; static uchar idleRate; /* repeat rate for keyboards, never used for mice */ /*volatile*/ debugMsg_t messageToSend; volatile bool messageSent = true; static uchar interruptMsg[2]; usbMsgLen_t usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (usbRequest_t *)data; if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) // HID class request { if(rq->bRequest == USBRQ_HID_GET_REPORT) // wValue: ReportType (highbyte), ReportID (lowbyte) { if(rq->wValue.bytes[0] == DEBUG_MESSAGE_ID) //switch the report ID { usbMsgPtr = (usbMsgPtr_t)&messageToSend; messageSent = true; return sizeof(messageToSend); } } else if(rq->bRequest == USBRQ_HID_GET_IDLE) { usbMsgPtr = (usbMsgPtr_t)&idleRate; return 1; } else if(rq->bRequest == USBRQ_HID_SET_IDLE) { idleRate = rq->wValue.bytes[1]; } else { } } else { // ignore vendor type requests, we don't use any } return 0; } void DebugMsg(const char * msg) { // Data is too large to be transferred via interrupt. So we prepare the data at messageToSend // and send fake interrupt so that host can retrieve the data via standard GetReport. strncpy(messageToSend.message, msg, sizeof(messageToSend.message)); messageToSend.msgLen = strlen(messageToSend.message); messageToSend.reportID = DEBUG_MESSAGE_ID; messageSent = false; while(!usbInterruptIsReady()) usbPoll(); interruptMsg[0] = DEBUG_INT_MSG_ID; usbSetInterrupt(interruptMsg, 2); while(!messageSent) { wdt_reset(); usbPoll(); if(!(PIND & (1<<PIND5)) && usbInterruptIsReady()) { usbSetInterrupt(interruptMsg, 2); } } }
      Код приема:

      int usbGetReport(usbDevice_t *device, int reportType, int reportNumber, char *buffer, int *len) { HANDLE handle = (HANDLE)device; BOOLEAN rval = 0; DWORD bytesRead; switch(reportType){ case USB_HID_REPORT_TYPE_INPUT: buffer[0] = reportNumber; rval = ReadFile(handle, buffer, *len, &bytesRead, NULL); if(rval) *len = bytesRead; break; case USB_HID_REPORT_TYPE_OUTPUT: break; case USB_HID_REPORT_TYPE_FEATURE: buffer[0] = reportNumber; rval = HidD_GetFeature(handle, buffer, *len); break; } return rval == 0 ? USB_ERROR_IO : 0; } void MainWindow::on_receiveButton_clicked() { if(!handle) return; // Wait for the interrupt ui->logArea->append("\nWaiting for the interrupt"); char intMsg[2]; int len = 2; int err = usbGetReport(handle, USB_HID_REPORT_TYPE_INPUT, DEBUG_INT_MSG_ID, intMsg, &len); if(err) { ui->logArea->append(QString("Error code %1, last error %2").arg(err).arg(GetLastError())); return; } ui->logArea->append(QString("Received interrupt %1 bytes").arg(len)); debugMsg_t msgBuf; len = sizeof(msgBuf); msgBuf.reportID = DEBUG_MESSAGE_ID; ui->logArea->append("\nGetting the data"); err = usbGetReport(handle, USB_HID_REPORT_TYPE_FEATURE, DEBUG_MESSAGE_ID, (char*)&msgBuf, &len); ui->logArea->append(QString("Received %1 bytes").arg(len)); ui->logArea->append(QString("Error code %1, last error %2").arg(err).arg(GetLastError())); ui->logArea->append(QString::fromLatin1(msgBuf.message, msgBuf.msgLen)); }
      Проблема №1
      Первый вызов usbGetReprot (который внутри вызывает ReadFile) виснет, не смотря на то, что прерывание со стороны контроллера ушло. После того как я один раз с помощью кнопки на плате контроллера посылаю дополнительное прерывание (строка if(!(PIND & (1<<PIND5)) && usbInterruptIsReady())) все начинает работать как надо.
      Зачем нужно дополнительное прерывание?
      Проблема №2
      Не могу сделать пустое прерывание. Т.е такое, которое состоит только из ReportID. ReadFile в этом случае никогда не развисает. Приходится таска дополнительный байт (соответственно посылать и принимать 2 байта)
      Где копать?
      ЗЫ Извините за код в столбик - это так он скопировался на сайт. Видимо табы глотаются
    • By mosfetx
      Всем привет. Проблема в следующем. При пошаговой отладке не переходит на вектор прерывания по переполнению таймера 0 (в avrStudio 4 все работает как положено).
      Проверьте если не затруднит проект на вашей студии 6.2. Файл проекта прилагается. или может кто то сталкивался и решил такую проблему.
      Отпишитесь если работает, или не работает. Если не затруднит. Заранее спасибо
      test.rar
×
×
  • Create New...