Jump to content

    

Auratos

Участник
  • Content Count

    32
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Auratos

  • Rank
    Участник

Recent Profile Visitors

858 profile views
  1. Спасибо большое вам за помощь. Все работает :)
  2. Попробовал ваш вариант. Контроллер отвечает шустро, только ответ неверный на запрос. Вместо правильного ответа [01][03][0C][00][00][00][00][00][00][00][00][00][05][00][00][83][71] приходит [03][01][00][00][00][00][00][00][00][00][00][05][00][00][83][FD] Не подскажите, в чем может быть загвоздка?
  3. Добрый день. Есть контроллер серии PIC18. Возникла сейчас необходимость производить передачу по USART в прерывании. Раньше для этого я использовал функцию, и работало все без прерываний: void usart_Tx(void* buf,BYTE size) { BYTE i,j; UINT16 k; char* ptr = (char*)buf; TRAN; // установить признак передачи для переключения переходника TTL-RS485 PIE1bits.RCIE = 0; // запретить прерывание от приемника USART for(i = 0; i < size; i++) { TXREG1 = ptr[i]; // запись байта в буфер передатчика USART while(!PIR1bits.TXIF); // ожидание опустошения буфера for(j = 0; j < 255; j++) // временная выдержка для достижения скорости передачи k++; } REC; // установить признак приема для переключения переходника TTL-RS485 PIE1bits.RCIE = 1; // разрешить прерывание от приемника USART } Нужно именно использовать прерывания, чтобы контроллер не отвлекался надолго на передачу. Но что-то не могу найти хотя бы одного примера, как это организовывается.Все, что придумал, это char* ptr = (char*)usart_rx_buf; // количество данных для передачи void tx_str(BYTE cnt) { PIE1bits.TXIE = 1; TRAN; // установить признак передачи для переключения переходника TTL-RS485 PIE1bits.RCIE = 0; // запретить прерывание от приемника USART totalElementstoSend = cnt; sendPointer = 0; REC; // установить признак приема для переключения переходника TTL-RS485 PIE1bits.RCIE = 1; // разрешить прерывание от приемника USART } void usart_Tx_Int(void) { BYTE i,j; UINT16 k; TXREG = ptr[sendPointer]; while(!PIR1bits.TXIF); // ожидание опустошения буфера for(j = 0; j < 255; j++) // временная выдержка для достижения скорости передачи k++; sendPointer++; if (sendPointer >= totalElementstoSend) PIE1bits.TXIE = 0; PIR1bits.TXIF = 0; } Вроде все передается, но все равно как будто не то. Подскажите, пожалуйста, как это сделать лучше? Или может у кого небольшой фрагментик готового кода завалялся :))
  4. Спасибо за помощь. Завтра на работе проверю этот вариант. А по поводу тактирования от внутреннего генератора не подскажите? Как его выбрать источником и выбрать частоту, на котором он работает?
  5. Честно говоря, я и не знал, что это играет роль. Надо именно порядок поменять? TMR0H = 0xEC; TMR0L = 0xСС; Или значение предзагрузки поменять местами? TMR0H = 0xCC; TMR0L = 0xEС;
  6. Добрый день. У меня контроллер 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?
  7. Добрый день. Попала ко мне в руки платка с контроллером 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? На сколько упадет частота с учетом задержек при передаче между байтами/внутри байта? Каким-нибудь ПО можно оценить скорость передачи?
  8. Добрый день. У меня контроллер 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?
  9. STM32F107RCT6 Time base generator

    Спасибо большое. Помогло :biggrin:
  10. 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 } }
  11. Мне уже на другом форуме рассказали, что "в одном флаконе" такого нет, нужно будет делать самому. Защиту по току еще можно найти в драйверах, а вот контроля положения - нет :rolleyes: Поэтому сейчас мне интересно узнать хотя бы названия российских производителей/поставщиков с более-менее крупной линейкой контроллеров/драйверов под разные нужды
  12. Подскажите, пожалуйста, хотя бы названия нескольких производителей, желательно, российских, кто занимается производством или поставками драйверов Скажите, пожалуйста, а чем примечателен именно этот контроллер?
  13. Добрый день. Товарищи, подскажите, пожалуйста, недорогие модели (до 300-400 рублей) контроллеров шаговых двигателей или даже готовые драйвера шаговых двигателей (цена до 1000 рублей), кто уже интересовался, сталкивался или знает, где можно поискать. Параметры: вых. напряжение 5В, вых. ток до 2.5А. Желательно наличие функций считывание текущего положения двигателя, т.е. некий аналог датчика положения, чтобы после подачи питания можно было определить количество уже сделанных шагов. И защита от перегрузок в крайних положениях, когда поступает команда "Сделай шаг", а двигатель уже в крайнем положении. Желательно контроллеры более-менее популярных, проверенных и доступных производителей с большой линейкой аналогичной продукции
  14. Принцип работы RTC в STM32F107

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

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