Перейти к содержанию

    

Auratos

Участник
  • Публикаций

    29
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о Auratos

  • Звание
    Участник
  1. Спасибо за помощь. Завтра на работе проверю этот вариант. А по поводу тактирования от внутреннего генератора не подскажите? Как его выбрать источником и выбрать частоту, на котором он работает?
  2. Честно говоря, я и не знал, что это играет роль. Надо именно порядок поменять? TMR0H = 0xEC; TMR0L = 0xСС; Или значение предзагрузки поменять местами? TMR0H = 0xCC; TMR0L = 0xEС;
  3. Добрый день. У меня контроллер PIC18F25K22. Пытался завести таймер TMR0 с частотой прерываний 1мс. Но на деле получаю 1,31мс. И не пойму, почему так. Настройки таймера рассчитал вручную, а затем с помощью программы PIC Timer Calculator. Данные сошлись, но по факту частота не та. У меня внешний тактовый генератор 4,9152МГц с включенной PLL. От этого и отталкивался. Считал, что на CLKOUT имею 4915200Гц. Значит в 16-битном режиме для 1мс мне понадобится 4916 приращений таймера. Сделал предзагрузку 0xECCC. И получил не то, что хотел. Вот такие у меня настройки источника тактирования: #pragma config WDTEN = SWON // сторожевой таймер #pragma config WDTPS = 512 // скорость работы сторожевого таймера #pragma config FOSC = HSMP // частота тактового генератора #pragma config PLLCFG = ON #pragma config PRICLKEN = ON #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config PWRTEN = ON //#pragma config BORV = 285 #pragma config BOREN = OFF #pragma config PBADEN = OFF #pragma config XINST = OFF И вот настройки таймера: // обработка прерывания таймера TMR0 void tmr0_int(void) { INTCONbits.TMR0IF = 0; // сброс переполнения таймера T0CONbits.TMR0ON = 0; TMR0L = 0xСС; TMR0H = 0xEC; T0CONbits.TMR0ON = 1; LED_SW; } // инициализация таймера TMR0 void tmr0_init(void) { T0CONbits.T08BIT = 0; // 16-ти разрядный таймер T0CONbits.T0CS = 0; // тактирование от осцилятора 4*Fosc/4 T0CONbits.T0SE = 0; // приращение по переднему фронту импульса T0CONbits.PSA = 1; // предделитель не используется T0CONbits.T0PS = 0; // коэф. предделителя не используется TMR0L = 0xСС; // регистр таймера в ноль TMR0H = 0xEC; INTCON2bits.TMR0IP = 1; // приоритет прерывания TMR0 - высокий INTCONbits.TMR0IE = 1; // разрешить прерывание по переполнению TMR0 T0CONbits.TMR0ON = 1; } Частоту смотрю на осциллографе по светодиоду, состояние которого меняю каждое прерывание. Схема подключения внешнего тактового генератора на фотографии. Подскажите, пожалуйста, в чем может быть загвоздка? В Fosc выбрал не тот режим? Завел еще таймер TMR1. В регистре T1CONbits в бите TMR1CS ставил и 00 и 01. После соответствующего пересчета получал все то же значение частоты. TMRxCS<1:0>: Timer1/3/5 Clock Source Select bits 11 =Reserved. Do not use. 10 =Timer1/3/5 clock source is pin or oscillator: If TxSOSCEN = 0: External clock from TxCKI pin (on the rising edge) If TxSOSCEN = 1: Crystal oscillator on SOSCI/SOSCO pins 01 =Timer1/3/5 clock source is system clock (FOSC) 00 =Timer1/3/5 clock source is instruction clock (FOSC/4) Еще подскажите, пожалуйста, как начать тактироваться от внутреннего тактового генератора. Где это настраивается? В регистре OSCCON?
  4. Добрый день. Попала ко мне в руки платка с контроллером PIC18F25K22 и проект для нее. Стоит внешний генератор на 4,9152МГц и включен PLL: #pragma config FOSC = HSMP // частота тактового генератора #pragma config PLLCFG = ON #pragma config PRICLKEN = ON #pragma config FCMEN = OFF ... Стоит задача оценить, с какой максимальной частотой можно с помощью этого контроллера передавать через RS-485 на компьютер данные (число float, 4 байта), если не брать в расчет задержки на выполнение сторонних алгоритмов (чистый проект), а сконцентрироваться только на обмене по сети. В данный момент проект сконфигурирован на скорость 9600 бод: void usart_init(void) { UINT_32 tmp; TRISCbits.TRISC6 = 0; // установить 0 вывод порта А как выход ANSELCbits.ANSC6 = 1; tmp = 4915200; // вычисление частоты USART по формуле SPBRG = Fosc/16 - 1 tmp /= 4; tmp /= 9600; tmp--; //не Fosc, а 4xFosc SPBRG1 = (BYTE)tmp; // устанавливаем частоту USART1 TXSTA1bits.SYNC = 0;// установка асинхронного режима TXSTA1bits.BRGH = 1; RCSTA1bits.SPEN = 1;// включить модуль USART1 PIR1bits.RCIF = 0; // очистить буфер приемника PIE1bits.RCIE = 1; // прерывание от приемника USART разрешено PIE1bits.TXIE = 0; // прерывание от передатчика USART запрещено IPR1bits.RCIP = 0; // приоритет прерывания от приемника USART - низкий IPR1bits.TXIP = 0; // приоритет прерывания от передатчика USART - низкий TXSTA1bits.TX9 = 0; // 8 разрядная передача RCSTA1bits.RX9 = 0; // 8 бит принятых данных RCSTA1bits.CREN = 1; // разрешить прием TXSTA1bits.TXEN = 1; // разрешить передачу } Нашел в даташите табличку со скоростями, настройками USART. Если вкратце, то на скорость влияют только 3 регистра: SYNC, BRGH и BRG16. В данном проект они сконфигурированы так: SYNC = 0, BRGH = 1, BRG16 = 0. Формально можно выставить максимальную скорость 115200 бод. Исходя из формулы V_bit = V_uart * d / (d + 1 + s + p) где: V_uart — скорость UART (например: 9600, 115200), бод; d — количество бит данных; s — количество стоповых бит; p — количество бит четности, p = 1 если бит четности присутствует, или p = 0 если бит четности отсутствует; единица в знаменателе отражает наличие стартового бита. Т.е. 1 бит на скорости 115200 бод будет передаваться в идеале со скоростью: 115200 * 8 / (8 + 1 +1 + 0) = 92160 бит/с = 11520 байт/с = 2880 float/c = 2,88 кГц. Подскажите, пожалуйста, способен ли данный контроллер работать на 115200? На сколько упадет частота с учетом задержек при передаче между байтами/внутри байта? Каким-нибудь ПО можно оценить скорость передачи?
  5. STM32F107RCT6 Настройки таймера

    Добрый день. У меня контроллер STM32F107RCT6. Настраиваю таймеры TIM1 и TIM2 для генерации частоты на выводах. TIM_TimeBaseInitTypeDef timer; TIM_OCInitTypeDef TIM_OCConfig; void TIM1_Init(uint16_t presc, uint16_t period, uint16_t repCnt) { TIM_TimeBaseInitTypeDef timer; TIM_OCInitTypeDef TIM_OCConfig; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); // тактирование таймера // выход TIM1_CH1 (F1) GPIO_mInit(GPIO_Speed_50MHz, GPIO_Mode_AF_PP, GPIOA, GPIO_Pin_8); TIM_TimeBaseStructInit(&timer); // заполнение поля структуры дефолтными значениями timer.TIM_Prescaler = presc; // предделитель timer.TIM_Period = period; // период timer.TIM_RepetitionCounter = repCnt; // счетчик повторений TIM_TimeBaseInit(TIM1, &timer); // инициализация TIM1 TIM_ARRPreloadConfig(TIM1, ENABLE); TIM1->BDTR |= TIM_BDTR_MOE; // включение выхода таймера TIM1 TIM_OCStructInit(&TIM_OCConfig); TIM_OCConfig.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCConfig.TIM_OutputState = TIM_OutputState_Enable; TIM_OC1Init(TIM1, &TIM_OCConfig); // включение канал1 таймера TIM1 TIM_Cmd(TIM1, ENABLE); // включение таймера TIM1_CH1(F1) } TIM1_Init(7, 17999, 1); TIM2_Init(7, 17999); Шина APB1 работает на частоте 36МГц, а APB2 - на 72МГц. Причем частоту фиксирую непосредственно перед инициализацией таймеров. Из даташита на таймеры на STM32 я вижу формулу, по ней произвожу расчет выходной частоты Взять, например, таймер TIM1: 72000000 / ((7 + 1) * (17999 + 1) * (0 + 1)) = 500Гц. Но фактически на осциллографе вижу частоту 249,9Гц, то есть делиться ровно в 2 раза. Пробовал на разных частотах - результат тот же. Подскажите, пожалуйста, в чем может быть косяк? И еще одна непонятная ситуация - изменения значения RepetitionCounter не влияет на выходную частоту. Пробовал и 1, и 2, и 170 - результат один. Как работает этот RepetitionCounter?
  6. STM32F107RCT6 Time base generator

    Спасибо большое. Помогло :biggrin:
  7. STM32F107RCT6 Time base generator

    Добрый день. У меня контроллер STM32F107RCT6. Хочу сделать тактовый генератор на таймере TIM1 (на 1-й канал выдавать частоту). Вроде все инициализировал (таймер, ножку PA8 для Ch1), а на ножке все равно глухо. Частота кварца 72MГц. Т.е. при текущей настройке на выходе должна быть частота 100Гц. Подскажите, пожалуйста, в чем может быть загвоздка? С контроллером серии STM32L100 у меня получалось, там просто некоторые структуры библиотечные выглядят немного иначе. А вот с этим контроллером никак int main( void) { TIM_TimeBaseInitTypeDef timer; TIM_OCInitTypeDef TIM_OCConfig; SystemCoreClockUpdate (); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN, ENABLE); GPIO_mInit(GPIO_Speed_10MHz, GPIO_Mode_AF_PP, GPIOA, GPIO_Pin_8); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructInit(&timer); timer.TIM_Prescaler = 11000; timer.TIM_Period = 65; TIM_TimeBaseInit(TIM1, &timer); TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_OCStructInit(&TIM_OCConfig); TIM_OCConfig.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCConfig.TIM_OutputState = TIM_OutputState_Enable; TIM_OC1Init(TIM1, &TIM_OCConfig); TIM_Cmd(TIM1, ENABLE); // Включение таймера TIM1_CH1(F1) while(1) { wdt_reset(); // сброс WDT } }
  8. Мне уже на другом форуме рассказали, что "в одном флаконе" такого нет, нужно будет делать самому. Защиту по току еще можно найти в драйверах, а вот контроля положения - нет :rolleyes: Поэтому сейчас мне интересно узнать хотя бы названия российских производителей/поставщиков с более-менее крупной линейкой контроллеров/драйверов под разные нужды
  9. Подскажите, пожалуйста, хотя бы названия нескольких производителей, желательно, российских, кто занимается производством или поставками драйверов Скажите, пожалуйста, а чем примечателен именно этот контроллер?
  10. Добрый день. Товарищи, подскажите, пожалуйста, недорогие модели (до 300-400 рублей) контроллеров шаговых двигателей или даже готовые драйвера шаговых двигателей (цена до 1000 рублей), кто уже интересовался, сталкивался или знает, где можно поискать. Параметры: вых. напряжение 5В, вых. ток до 2.5А. Желательно наличие функций считывание текущего положения двигателя, т.е. некий аналог датчика положения, чтобы после подачи питания можно было определить количество уже сделанных шагов. И защита от перегрузок в крайних положениях, когда поступает команда "Сделай шаг", а двигатель уже в крайнем положении. Желательно контроллеры более-менее популярных, проверенных и доступных производителей с большой линейкой аналогичной продукции
  11. Принцип работы RTC в STM32F107

    Цитата(Baser @ Feb 28 2018, 16:04) 2038 год будет уже всего-то через 20 лет. А время бежит быстро. Вот сделаете вы какой-нибудь удачный прибор, и будут люди применять его 20 лет и хвалить. А тут раз - и из-за ошибки времени облом. Зачем сознательно закладывать ошибку, если ее можно легко избежать Все верно. Создаем вычислительное устройство, настал момент его сертифицировать, где мы гарантируем 15 лет бесперебойной работы, поэтому уже через 4 года мы не сможем гарантировать указанный срок службы, т.к. 2022 + 15 = 2037 год
  12. Принцип работы RTC в STM32F107

    Цитата(Baser @ Feb 28 2018, 12:25) Это библиотечная фунция, входящая в Си. В ней применяется UNIX-время (Unix Epoch). Отсчет начинается от 1 января 1970 года. 2036-м годом ограничено, потому что в 2038 UNIX-время достигнет 2х31 и может неверно интерпретироваться как отрицательное. Почитайте по ссылке. Вы можете сдвигать время как угодно, но при этом нужно будет применять свои функции или сдвигать стандартные. Я применяю время с 1 января 2000 года. Переписал функции и использую такой свой Timestamp. И вы также используете библиотечные функции localtime и mktime? А не могли бы вы, пожалуйста, привести пример своих функций для работы со временем?
  13. Принцип работы RTC в STM32F107

    Цитата(viakon @ Feb 28 2018, 10:28) Откуда, зададите оттуда и будет. Главное правильно преобразовать при синхронизации часов. Можно, пожалуйста, поподробнее? Просто я пользуюсь библиотечной функцией при установке времени и даты Кодvoid Set_Time(struct tm *t) {   uint32_t CounterValue = (uint32_t)mktime(t);   save_Time(CounterValue; } void save_Time(uint32_t tmr) {   RTC_WaitForLastTask();   RTC_SetCounter(tmr);   RTC_WaitForLastTask(); } Так вот, функция mktime не воспринимает дату позже февраля 2036 года (найдено опытным путем вплоть до минуты и секунды), т.к. при инкрементации новой секунды происходит переполнение 32-битного CounterValue. Или я неправильно Вас понял? Как выставить дату больше указанной?
  14. Принцип работы RTC в STM32F107

    Добрый день. Имеется на руках контроллер серии STM32F107xx. Пользуюсь активно таймером реального времени. И вот, собственно, возник вопрос: а какой у этого таймера диапазон измерения времени? Т.к. там 32-битный секундный счетчик, то максимум он сможет отсчитать ~136 лет. Отсчет начинается, как я понял, с 1900 года, т.е. до 2036 года. А что будет после его переполнения, т.е. после 2036 года? Можно ли самому подвинуть точку отсчета? Или там совсем все устроено по-другому? Объясните, пожалуйста
  15. STM32F107. Модуль USB не передает данные

    Добрый день. Не нашел отдельной ветки для STM-контроллеров, поэтому пишу сюда. Имеется контроллер STM32F107RCT6. Задействовал у него модуль USB и взял с сайта ST последнюю версию библиотеки и драйвера USB (STM32_USB_OTG_Driver v2.2.0). На плате также имеется GSM-модуль фирмы SIMCOM. Спаяли две платы с данными контроллерами. Одна работает, вторая "болеет". Проблема в том, что если не вставлена SIM-карта, то USB модуль работает отлично. Но со вставленной SIM-картой и после прохождения этапа регистрации в сети перестает работать обмен данными через USB: принимать данные - принимает, но обратно не передает. Попробовали сначала перепаять контроллер и просмотреть линии, ведущие к USB - не помогло. Стал теперь копаться в драйвере. В рабочей версии платы при попытке передать данные в USB порт в функции USBD_OTG_ISR_Handler дважды генерируется некое прерывание, которое драйвер относит к группе inepint Кодuint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev) {   USB_OTG_GINTSTS_TypeDef  gintr_status;   uint32_t retval = 0;      if (USB_OTG_IsDeviceMode(pdev)) /* ensure that we are in device mode */   {     gintr_status.d32 = USB_OTG_ReadCoreItr(pdev);          ...          if (gintr_status.b.inepint)     {       retval |= DCD_HandleInEP_ISR(pdev);     }         ...     }   return retval; } При обнаружении данного прерывания вызывается функция DCD_HandleInEP_ISR Кодstatic uint32_t DCD_HandleInEP_ISR(USB_OTG_CORE_HANDLE *pdev) {   USB_OTG_DIEPINTn_TypeDef  diepint;      uint32_t ep_intr;   uint32_t epnum = 0;   uint32_t fifoemptymsk;   diepint.d32 = 0;   ep_intr = USB_OTG_ReadDevAllInEPItr(pdev);      while ( ep_intr )   {     if ((ep_intr & 0x1) == 0x01) /* In ITR */     {       diepint.d32 = DCD_ReadDevInEP(pdev , epnum); /* Get In ITR status */       if ( diepint.b.xfercompl )       {         fifoemptymsk = 0x1 << epnum;         USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0);         CLEAR_IN_EP_INTR(epnum, xfercompl);         /* TX COMPLETE */         USBD_DCD_INT_fops->DataInStage(pdev , epnum);                  if (pdev->cfg.dma_enable == 1)         {           if((epnum == 0) && (pdev->dev.device_state == USB_OTG_EP0_STATUS_IN))           {             /* prepare to rx more setup packets */             USB_OTG_EP0_OutStart(pdev);           }         }                 }       if ( diepint.b.timeout )       {         CLEAR_IN_EP_INTR(epnum, timeout);       }       if (diepint.b.intktxfemp)       {         CLEAR_IN_EP_INTR(epnum, intktxfemp);       }       if (diepint.b.inepnakeff)       {         CLEAR_IN_EP_INTR(epnum, inepnakeff);       }       if ( diepint.b.epdisabled )       {         CLEAR_IN_EP_INTR(epnum, epdisabled);       }             if (diepint.b.emptyintr)       {         DCD_WriteEmptyTxFifo(pdev , epnum);       }     }     epnum++;     ep_intr >>= 1;   }      return 1; } За эти два прерывания, про которые я упомянул, поочередно взводятся два флага: diepint.b.emptyintr и diepint.b.xfercompl. Возведение diepint.b.xfercompl как раз и сигнализирует о том, что данные пошли на отправку. Но в нерабочей плате взводится только diepint.b.emptyintr, и статус USB так и остается как "занят", но при этом данные не передались. Стал копаться глубже и зашел в тупик. Подскажите, пожалуйста, что можно посмотреть еще? Линии, регистры? Любая подсказка