Уважаемые посетители! Форум CQHAM.RU существует исключительно за счет показа рекламы. Мы будем благодарны, если Вы не будете блокировать рекламу на нашем Форуме. Просим внести cqham.ru в список исключений для Вашего блокировщика рекламы.
Страница 3 из 4 ПерваяПервая 1234 ПоследняяПоследняя
Показано с 21 по 30 из 34

Тема: Си и валкодер

  1. #21
    Аватар для Genadi Zawidowski
    Регистрация
    22.07.2004
    Адрес
    Санкт-Петербург
    Сообщений
    11,100
    Записей в дневнике
    20
    Позывной
    UA1ARN
    Красивее вариант ra3rbe записать так (добавить ещё значение для положительного шага):
    Код:
    switch(EncState)
    {
    // положительные шаги
    case 0b11100001:
    case 0b11100111:
    case 0b11101110:
    // тут ещё один case пропущен
    	Plus_Step ++;
    	break;
    // отрицательные шаги
    case 0b11100010:
    case 0b11101011:
    case 0b11101101:
    case 0b11100100:
    	Minus_Step ++;
    	break;
    }
    Значения я не контролировал, автор поправит.
    Последний раз редактировалось Genadi Zawidowski; 13.05.2016 в 14:21.
    ... Я там глубину сам промерял!


  2. #22
    Цитата Сообщение от ra3rbe Посмотреть сообщение
    Зачем каждые 10 мс делать расчет, если валкодер не крутили?
    Так не буду я делать расчет, если не крутил. Если валкодер не вращали, в буфере валкодера 0. Если вращали, там какое-то число, на сколько я смог накрутить за 10 мс или за одну, это надо опытным путем определить.. Множим его на шаг перестройки, делаем расчет, вывод на индикатор, пишем в SI5351. После чего сбрасываем буфер в ноль. По новой с нуля, запускаем таймер. То есть расчет делаем с периодом через 10 или 1 мсек и то, если вращали. Если не вращали, вообще ничего. Только крутимся опрашивая переключатель диапазонов, кнопки управления и валкодер. Тут я вижу один недостаток - нет спящего режима. Хотя, это вроде тоже не проблема.
    То есть расчет делаем при установленном флаге переполнения и не нуле в буфере валкодера..

    Цитата Сообщение от Genadi Zawidowski Посмотреть сообщение
    Красивее вариант ra3rbe записать так
    Да, понял. А кстати, чего так не нравится "IF"? Лишние циклы?
    Последний раз редактировалось Владимир_К; 13.05.2016 в 14:54.

  3. #23
    Переделал так как советовали, все четко работает. Пока вопросов нет.
    Код сейчас такой, может еще кто пытается найти тропу. У меня валкодер на 6 и 7 пине порта, потому сдвиг вправо на 6, маска, потом на 2 влево, прицепил новое состояние пинов, потом анализ. Всем спасибо.

    void PollEncoder()
    {
    New =((EncoderPinPort>>6 ) & 0b11);
    EncState = (New << 2) | EncState;
    switch(EncState)
    {
    case 0b00000001:
    case 0b00000111:
    case 0b00001110:
    case 0b00001000:
    bufEnc--;
    break;

    case 0b00000010:
    case 0b00001011:
    case 0b00001101:
    case 0b00000100:
    bufEnc++;
    break;
    }
    EncState = New;

    }

  4. #24
    Так поменьше операций будет...

    void PollEncoder()
    {
    New = EncoderPinPort & 0b11000000;
    EncState = new | EncState;
    switch(EncState)
    {
    case 0b00010000:
    case 0b01110000:
    case 0b11100000:
    case 0b10000000:
    bufEnc--;
    break;

    case 0b00100000:
    case 0b10110000:
    case 0b11010000:
    case 0b01000000:
    bufEnc++;
    break;
    }
    EncState = New >> 2;
    }
    Последний раз редактировалось Oleg 9; 13.05.2016 в 17:52.

  5. Спасибо от Владимир_К

  6. #25
    Цитата Сообщение от Oleg 9 Посмотреть сообщение
    Так поменьше операций будет...
    Еще раз подтверждение того, что нет той программы, которую нельзя уменьшить хотя бы на один шаг. И сам не пойму, зачем двигал..

  7. #26
    Цитата Сообщение от Владимир_К Посмотреть сообщение
    Еще раз подтверждение того, что нет той программы, которую нельзя уменьшить хотя бы на один шаг.
    Так кажется потому что
    Цитата Сообщение от Владимир_К Посмотреть сообщение
    это моя первая программа на Си (не считая конечно "моргания" светодиодом),
    Со временем подобные оптимизации автоматом возможно будете делать .

  8. #27
    Аватар для vadim_d
    Регистрация
    29.10.2006
    Адрес
    Санкт-Петербург
    Сообщений
    14,916
    Цитата Сообщение от ra3rbe Посмотреть сообщение
    Нужно загнать 2 бита предыдущего состояния и 2 бита текущего в переменную И потом анализировать ее.
    Лучше всего CASE, и не делать каждый раз IF
    Неа, лучше объявить матрицу для прямой трансляции этого четырехбитного кода в приращение, как у меня

    static int8_t dcd_tbl[] PROGMEM = {
    0, -1, 1, 0,
    1, 0, 0, -1,
    -1, 0, 0, 1,
    0, 1, -1, 0
    };
    Вадим

  9. #28
    Если обрабатывать каждый шаг валкодера и при каждом изменении задавать новую частоту Si5351A, программа не успевает отрабатывать. Мало того, при некоторой "сноровке" подобрав скорость вращения валкодера, частота, что показывает частотомер, подключенный к выходу Si5351A, стоит на месте. Это происходит, если рассуждать теоретически, возможно таким образом - пока идет загрузка частоты, валкодер повернулся так, что состояние выходов валкодера стало таким же как и было раньше (а может не совсем так, но похоже).
    Поэтому, частоту решил писать в Si5351A примерно каждые 5 миллисекунд. По прерыванию от таймера. Хотя, наверное это не совсем так. При прерывании, программа обработки устанавливает признак переполнения - "t". В основном цикле проверяем значение "t". Если единица, запрещаем прерывания и пишем новую частоту в Si5351A, после чего восстанавливаем счетчик, сбрасываем "t", разрешаем прерывания. Пока этот кусок кода проверен на макете. Макет - плата Ардуино, на Atmega8, но работающая в среде WinAvr, валкодер, Si5351A. Вроде все нормально. Если у кого есть желание сделать замечания или предложить другой алгоритм, буду признателен.

    #define TCNT0_const 180
    #define TCCR0_const 5
    //#define |= (1 << LED_BIT) Stop
    unsigned char chagi=100,t;
    unsigned long frequency_r;
    uint32_t xtalFreq =27000000;
    //volatile char bufEnc=0;
    // ++++ функция инициализации МК ++++
    void initialization(void)
    {
    DDRD |=(0<<6)|(0<<7); // Set pin as input
    PORTD |=(1<<6)|(1<<7);

    TCNT0 = TCNT0_const; //Значение числа в счетчике для задержки
    TCCR0 = TCCR0_const; //Устанавливаем прескалер перед счетчиком =1024
    TIMSK = (1<<TOIE0)|(1<<OCIE1 A); //Разрешаем прерывания от счетчиков

    }
    ISR(TIMER0_OVF_vect)
    {
    t=1; //Обработка прерывания от переполнения счетчика
    }

    /******************** Вычисление частоты **************/

    void sub_freg()
    {
    if(bufEnc==1)
    frequency_r=frequenc y_r+chagi;
    else
    frequency_r=frequenc y_r- chagi;
    bufEnc=0;
    }
    /************ Основная программа *******************/
    int main(void)
    {
    initialization();
    i2cInit();
    frequency_r=12856753 ;
    sei();

    while (1) //Бесконечный цикл
    {
    PollEncoder(); //Проверяем состояние энкодера
    if (bufEnc!=0) //Если вращали, добавляем/вычитаем шаг
    sub_freg();

    if (t!=0) //если было переполнение счетчика, изм. частоту Si5351А
    {
    cli(); //запрещаем прерывания
    si5351aSetFrequency( frequency_r);
    t=0;
    TCNT0 = TCNT0_const; //Восстанавливаем значение счетчика
    sei(); //Разрешаем прерывания
    }
    }
    }
    Последний раз редактировалось Владимир_К; 18.05.2016 в 19:30.

  10. #29
    Владимир, если совсем правильно делать, то вот это должно обрабатываться в прерывании:

    Скрытый текст


    ISR(****) // прерывание по любому перепаду лог. уровня на входах энкодера.
    {
    New = EncoderPinPort & 0b11000000;
    EncState = new | EncState; // EncState - volatile unsigned char
    switch(EncState)
    {
    case 0b00010000:
    case 0b01110000:
    case 0b11100000:
    case 0b10000000:
    bufEnc--; // bufEnc - volatile signed char.
    break;

    case 0b00100000:
    case 0b10110000:
    case 0b11010000:
    case 0b01000000:
    bufEnc++;
    break;
    }
    EncState = New >> 2;
    Enc_flag=1; // Глобальная битовая переменная
    }


    А далее в основном цикле:

    Скрытый текст



    if (Enc_flag)
    {
    cli(); //запрещаем прерывания
    freqw_buff=bufEnc; //freqw_buff - глобальная signed char
    Enc_flag = 0;
    bufEnc =0;
    sei(); //Разрешаем прерывания

    TMP_F = freqw_buff * Step ; // TMP_F - unsigned long, или signed long, и так
    // и так будет правильно работать
    frequency_r += TMP_F;

    // далее можно вычислять частоту для Si5351A, записывать её в Si5351A, //выводить на индикатор - валкодер всегда будет правильно обрабатываться.

    }






    Добавлено через 15 минут(ы):

    PS: Возможно в функции обработке прерывания нужно ещё сбрасывать флаги прерываний от входов энкодера.... Не знаю как в атмеле это конкретно пишется.
    PPS: Подправил нижний спойлер, чтобы расчёт частоты вывод в сишку и на индикатор выполнялся только если она менялась от энкодера. Или по другому событию возводящему Enc_flag
    Последний раз редактировалось Oleg 9; 18.05.2016 в 20:44.


  11. #30
    Цитата Сообщение от Oleg 9 Посмотреть сообщение
    Владимир, если совсем правильно делать, то вот это должно обрабатываться в прерывании:
    Да, понял, спасибо.. Хотя, есть тут какая-то мысля.. Дело в том, что основной цикл (не в этом куске, конечно, а в полной программе) длится всего несколько микросекунд, поэтому есть ли смысл заводить валкодер на прерывание? Даже при большой скорости его вращения (разумной, понятно), программа не пропустит момент изменения состояния валкодера. Но это вполне может быть во время записи новой частоты в Si5351. А там, все равно все прерывания запрещены и я думаю их и нельзя там допускать, во избежание неверного расчета..
    Но, конечно, это пока не окончательно. Надо все слепить в кучу, для этого надо оформить все на нормальной плате. С макетом полного синтеза уже неудобно работать, да и в эту плату (Ардуино), оно все не помещается.
    Просто возник вопрос, когда начал пытать Si5351A и получил первые некоторые проблемы (скорость загрузки, пропадание сигнала на выходе во время загрузки примерно на 1,5 миллисек). Вот это выпадение сигнала убрал, исключив строку (внизу отмечено красным). Вообще, по управлению Si5351A есть еще много непонятного...
    //.................... .................... .................... .................... ..........
    setupPLL(SI_SYNTH_PL L_A, mult, num, denom);

    setupMultisynth(SI_S YNTH_MS_0, divider, SI_R_DIV_1);
    // Reset the PLL. This causes a glitch in the output. For small changes to
    // the parameters, you don't need to reset the PLL, and there is no glitch
    //i2cSendRegister(SI_P LL_RESET, 0xA0);

    i2cSendRegister(SI_C LK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);
    //.................... .................... .................... .................... .................... .................... .................... ....................
    Последний раз редактировалось Владимир_К; 18.05.2016 в 21:02.

Страница 3 из 4 ПерваяПервая 1234 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Самодельный валкодер
    от RA6LRW в разделе Технический кабинет
    Ответов: 214
    Последнее сообщение: 04.04.2020, 20:58
  2. Валкодер IC-7400
    от RW6AUR в разделе IC-746 (IC-7400)
    Ответов: 4
    Последнее сообщение: 03.01.2017, 01:11
  3. ic-820 валкодер
    от R1BBJ в разделе Icom
    Ответов: 12
    Последнее сообщение: 20.10.2011, 19:49
  4. Валкодер-энкодер
    от francua в разделе TS-430
    Ответов: 7
    Последнее сообщение: 23.08.2011, 21:57
  5. Валкодер IC 756pro
    от Vlad A.Mikchailov в разделе Трансиверы, приемники КВ/УКВ
    Ответов: 7
    Последнее сообщение: 20.01.2009, 12:28

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •