|
|
  |
STM32L051K8T6 + SysTick + ADC |
|
|
|
Sep 23 2014, 05:32
|
Группа: Новичок
Сообщений: 5
Регистрация: 23-09-14
Пользователь №: 82 902

|
Добрый день, товарищи! У меня такая проблема: настраиваю системный таймер с периодом 10мкс и АЦП с периодом преобразования 50 мкс, по отдельности все работает нормально. Когда вместе, при одинаковых приоритетах прерываний на осциллографе вижу только работу таймера, если у АЦП выше приоритет, то есть пропуски прерываний от таймера, т.е. между входами t = 20мкс. Тактирую от HSI. Проверяю это с помощью светодиода и сигнала на лапах. CODE void Init() {
//------ System clock HSI = 16 MHz ---------------------------------------- // FLASH->ACR = 0x00000001; RCC->CFGR = RCC_CFGR_SW_HSI;// | RCC_CFGR_PPRE2_DIV16; RCC->CR = RCC_CR_HSION | RCC_CR_HSIDIVEN; // Âíóòðåííèé ãåíåðàòîð ñ äåëèòåëåì íà 4
while(!(RCC->CR & RCC_CR_HSIRDY)) ; // Îæèäàíèå ñòàáèëèçàöèè ÷àñòîòû âíóòðåííåãî ãåíåðàòîðà while(!(RCC->CR & RCC_CR_HSIDIVF)) ; RCC->IOPENR = RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN; // Òàêòèðîâàíèå ïîðòîâ À è  RCC->APB2ENR = RCC_APB2ENR_ADC1EN; // Òàêòèðîâàíèå ÀÖÏ
GPIOA->MODER = 0xE85EFDDF; GPIOA->PUPDR = 0x25000000;
GPIOB->MODER = 0xFFFFDFFF;
ADC1->CR |= ADC_CR_ADCAL; while(ADC1->CR & ADC_CR_ADCAL) ; // Îæèäàíèå îêîí÷àíèÿ êàëèáðîâêè ADC1->IER |= ADC_IER_EOCIE; // Ðàçðåøåíèå ïðåðûâàíèÿ ïî çàâåðøåíèè ïðåîáðàçîâàíèÿ ADC1->CFGR1 |= ADC_CFGR1_WAIT | ADC_CFGR1_CONT; ADC1->CFGR2 |= ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSR_1; ADC1->CHSELR |= ADC_CHSELR_CHSEL3; // 3 êàíàë - ïðèåìíèê ADC1->SMPR = ADC_SMPR_SMPR; ADC->CCR |= ADC_CCR_LFMEN; // Low Frequency Mode ADC1->CR = ADC_CR_ADSTART | ADC_CR_ADEN;
//----------------------SysTick Timer-------------------------------- SysTick->LOAD = 5; // NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ SysTick->VAL = 0; SysTick->CTRL |= 0x07;
// NVIC_SetPriority(ADC1_COMP_IRQn, (1<<__NVIC_PRIO_BITS) - 1); NVIC_EnableIRQ(ADC1_COMP_IRQn); } //------------------------------------------- void SysTick_Handler(void) // 10 ìêñ { f_blink ^= 0x01; if(f_blink) GREEN_LED_ON; else GREEN_LED_OFF; } //------------------------------------------- void ADC1_COMP_IRQHandler() { uint16_t resADC = ADC1->DR;
f_blink1 ^= 0x01; if(f_blink1) RED_LED_ON; else RED_LED_OFF; }
Подскажите, пожалуйста в чем проблема.
Сообщение отредактировал IgorKossak - Sep 24 2014, 08:45
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Sep 23 2014, 06:32
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата SysTick->LOAD = 5; 16M / 8 / 5 -> 2.5 мкс Другими словами прерывание происходит каждые 40 тактов проца. Ну что за такое время можно успеть? Проверил по документации Цитата SysTick->CTRL |= 0x07; Вообще 5 тактов, т.к. предделитель для SysTick отключается.
|
|
|
|
|
Sep 23 2014, 06:50
|
Группа: Новичок
Сообщений: 5
Регистрация: 23-09-14
Пользователь №: 82 902

|
Цитата(adnega @ Sep 23 2014, 10:17)  16M / 8 / 5 -> 2.5 мкс
Другими словами прерывание происходит каждые 40 тактов проца. Ну что за такое время можно успеть? Не совсем понял? Как я понимаю частота тактирования таймера HCLK/8 с предделителем /4 - T=500 кГц или 2мкс на счет. При загрузке значени 5 в LOAD - срабатывание будет через 10мкс - я это вижу на осциллографе, когда АЦП отключено Цитата(adnega @ Sep 23 2014, 10:32)  Проверил по документации
Вообще 5 тактов, т.к. предделитель для SysTick отключается. Для серии L0 всегда HCLK/8 я проверил и CubeMX в Clock Configuration так показывает! Делитель нельзя отключить!!!
|
|
|
|
|
Sep 23 2014, 10:16
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Борис 1984 @ Sep 23 2014, 10:50)  Для серии L0 всегда HCLK/8 я проверил и CubeMX в Clock Configuration так показывает! Делитель нельзя отключить!!! В документе "PM0223 STM32L0 Series Cortex®-M0+ programming manual" STK_CSR: Цитата Bit 2 CLKSOURCE Selects the SysTick timer clock source: 0 = External reference clock. 1 = Processor clock. Попробуйте увеличить LOAD до 200-1 и посмотреть за периодом. Должен быть 100 мкс. 16M(HSI) / 4(HSIDIV4) / 200(LOAD) / 2(BLINK on-off) = 100 мкс.
|
|
|
|
|
Sep 23 2014, 10:30
|
Группа: Новичок
Сообщений: 5
Регистрация: 23-09-14
Пользователь №: 82 902

|
Спасибо! Похоже все дело в том что МК не успевает обрабатывать прерывания на таких частотах, появляются пропуски, сейчас попробую поднять частоту через PLL. Цитата(scifi @ Sep 23 2014, 14:23)  Какой ужас. Зачем 10 мкс? Обычно бывает 10 мс. А если 10 мкс, то велик риск "что-нибудь не успеть", как справедливо замечено выше. Нужна программная реализация высокоскоростного протокола обмена.
|
|
|
|
|
Sep 23 2014, 11:52
|
Группа: Новичок
Сообщений: 5
Регистрация: 23-09-14
Пользователь №: 82 902

|
Цитата(adnega @ Sep 23 2014, 14:38)  А что за протокол? А почему бы не приспособить для этого периферийные блоки? А какой кайф от L-серии в такой "программной реализации"? Протокол собственной разработки, передача последовательностей 8-10 бит, длительность бита 250мкс. Серия L выбрана, как низко потребляющая. Можете подробнее рассказать, какие периферийные блоки можно использовать?
|
|
|
|
|
Sep 23 2014, 12:05
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Борис 1984 @ Sep 23 2014, 15:52)  Протокол собственной разработки, передача последовательностей 8-10 бит, длительность бита 250мкс. Серия L выбрана, как низко потребляющая. Можете подробнее рассказать, какие периферийные блоки можно использовать? А какой именно протокол? Можно в UART или SPI превратить? Если нет, то "плохой")) В крайнем случае можно завести на таймер и генерить одно прерывание на бит аппаратно (делал для ИК-приемника, 1-wire, wiegand т.п.). Чтобы проц мало потреблял, софт должен отвечать нескольким требованиям. Самое главное, он все время должен спать. А софтовая обработка с дискретизацией 10 мкс спать процу не даст.
|
|
|
|
|
Sep 24 2014, 07:03
|
Группа: Новичок
Сообщений: 5
Регистрация: 23-09-14
Пользователь №: 82 902

|
Цитата(adnega @ Sep 23 2014, 16:05)  А какой именно протокол? Можно в UART или SPI превратить? Если нет, то "плохой")) В крайнем случае можно завести на таймер и генерить одно прерывание на бит аппаратно (делал для ИК-приемника, 1-wire, wiegand т.п.). Чтобы проц мало потреблял, софт должен отвечать нескольким требованиям. Самое главное, он все время должен спать. А софтовая обработка с дискретизацией 10 мкс спать процу не даст. Протокол - аналог SystemSensors. Попробовал поднять частоту с помощью PLL до 32МГц - помогло, но пока не знаю что с потреблением в итоге получится. Все спасибо за помощь, среди постов есть интересные мысли.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|