Страница 2 из 6 ПерваяПервая 123456 ПоследняяПоследняя
Показано с 11 по 20 из 51
  1. #11
    Пользователь
    Регистрация
    25.01.2011
    Сообщений
    24
    Вес репутации
    168

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Цитата Сообщение от Chip Посмотреть сообщение
    В обработчике прерывания я бы сначала положил в массив данные таймера счетчика и запустил новый отсчет, выход из обработчика и потом пока таймер считает выполняй другие задачи
    Вот пример кодовой посылки, которую надо считать и расшифровать:

    11111111111111 0 00000000 0 11111111 1

    (пробелы вставил для удобства чтения)
    сначала идет преамбула из 14-ти единиц
    потом разделитель - 0
    потом первый байт команды
    опять разделитель - 0
    второй байт команды
    стоповый бит - 1

    Вот и скажите, как мне все это получить?

    Ведь сначала надо поймать преамбулу. Это просто... Всего-то 14 раз поймать единицу. Если научиться ее ловить. Потом уже все остальное.

    Куда я буду запихивать столько данных из прерывания?
    Последний раз редактировалось Anri777; 26.01.2011 в 02:31.

  2. #12
    Администратор Аватар для Chip
    Регистрация
    08.06.2007
    Возраст
    54
    Сообщений
    13,379
    Вес репутации
    10

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Так тебе вообще не нужно писать все длятельности, достаточно делать записи битов только после смены 1 на 0 или наоборот
    Записывай биты функциями bitSet() это 1 и bitClear() это 0
    Последний раз редактировалось Chip; 26.01.2011 в 02:44.

  3. #13
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Вот код, в реале не проверял, но в отладчике вроде работает
    Код:
    #include <avr/io.h>
    
    #include "SmallUart.h"
    
    #include <avr/interrupt.h>
    #include <iopins.h>
    using namespace IO;
    
    volatile uint16_t WaveLength;
    volatile uint16_t CalcedWaveLength;
    
    #define TCNT2_Const (256-2)
    
    int main(void)
    {
        TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2   
        TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика  
        TCCR2B &= ~(1<<WGM22);// Режим работы таймера/счетчика  
        TCCR2B |= (1<<CS20)|(1<<CS21); //(1<<CS21)|(1<<CS20)|(1<<CS22); //установка предделителя 32
        ASSR &= ~(1<<AS2);  //Выбор источника синхронизации таймера если AS2=0 от системного генератора  
        TCNT2 = TCNT2_Const; //  16000000/256/100/64=8 tcnt2=256-8=248.      
        TIMSK2 |= (1<<TOIE2);//Разрешение прерывания по переполнению Т2. 
        sei(); 
    
    	WaveLength=0;
    	CalcedWaveLength=0;
    
    	for (;;)
    	{
    		for (;CalcedWaveLength==0;);
    		uint16_t cwl=CalcedWaveLength;
    		CalcedWaveLength=0;
    		UART_SendByte(cwl&255);
    		UART_SendByte(cwl>>8);
    		
    			
    	}
    }
    
    SIGNAL(TIMER2_OVF_vect) 
    {
    	TCNT2=TCNT2_Const;
    	uint16_t WL=WaveLength;
    	if (Pd2::IsSet())
    		WL++;
    	else
    	{
    		if (WL!=0)
    		{
    			CalcedWaveLength=WL;
    			WL=0;
    		}
    	}
    	WaveLength=WL;
    }
    Таймер выполняется примерно 50 тактов. Вызыается - каждые 64 такта процессора, т.е. считает каждые 4 микросекунды.

    В приложении - полный проект AVR Studio. Единственное, там стоит скорость 9600. ее надо увеличить до 115200 и в SmallUart.h включить
    @define UART_DOUBLESPEED
    Вложения Вложения
    • Тип файла: rar Wave.rar (17.7 Кб, Просмотров: 163)
    Последний раз редактировалось SBorovkov; 26.01.2011 в 02:46.

  4. #14
    Пользователь
    Регистрация
    25.01.2011
    Сообщений
    24
    Вес репутации
    168

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Цитата Сообщение от Chip Посмотреть сообщение
    Так тебе вообще не нужно писать все длятельности, достаточно делать записи битов только после смены 1 на 0 или наоборот
    attachInterrupt(1, blink, FALLING);

    Я так и делал. А что толку? Все равно ничего не выходит.

    Вот я иду в прерывание:

    time2 = micros(); time3=time2-time1;

    вычислил текущее время и вычел из него ранее запомненное

    Serial.print(" time="); Serial.println(time3);

    для понимания того, что делает у меня программа вывожу в порт замерянное значение

    time1=time2;

    запоминаю новое время и выхожу из обработчика...


    Вот скажи - что я делаю не так?

  5. #15
    Администратор Аватар для Chip
    Регистрация
    08.06.2007
    Возраст
    54
    Сообщений
    13,379
    Вес репутации
    10

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Я уже говорил, еще раз повторюсь , выкинь из обработчика
    Serial.print(" time="); Serial.println(time3);
    И лучше используй код от SBorovkov

  6. #16
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Строки
    Serial.print(" time=");
    Serial.println(time3);

    съедают астрономическое время. Во-первых это передача как минимум 7 (или 8) байт в uart. Что даже при скорости 115200 займет 115200/9/7 то есть 1/1800 секунды. А у тебя импульсы следуют 5 тыс раз в секунду. Это почти мгновенно должно приводить к переполнению буфера отправки.

    Кроме этого еще непосредственно Serial.println(time3) занимает кучу времени - нужно же преобразовать int32 в строку циклическим делением. А AVR аппаратного делителя не имеет.

    Кроме этого, micros() возвращает время с достаточно плохой точностью.

    Поэтому:
    1. Никаких делений и отправки данных в прерывании.
    2. Лучше воспользоваться собственным таймером.

  7. #17
    Пользователь
    Регистрация
    25.01.2011
    Сообщений
    24
    Вес репутации
    168

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Цитата Сообщение от Chip Посмотреть сообщение
    Я уже говорил, еще раз повторюсь , выкинь из обработчика
    Serial.print(" time="); Serial.println(time3);
    И лучше используй код от SBorovkov
    Я понял. Спасибо.

    Вся загвоздка в том, что я не могу понять ничего в коде SBorovkov`а... Это явно не для начинающих.

  8. #18
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    посмотрел, micros() возвращает время с точностью до 4 микросекунд. То есть рядом крутится еще один таймер, вызывающийся каждые 64 такта.

    Поэтому для начала лучше прописать
    #define TCNT2_Const (256-4)
    В результате наш таймер будет вызываться каждые 32*4 такта.

  9. #19
    Пользователь
    Регистрация
    25.01.2011
    Сообщений
    24
    Вес репутации
    168

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    Цитата Сообщение от SBorovkov Посмотреть сообщение
    посмотрел, micros() возвращает время с точностью до 4 микросекунд. То есть рядом крутится еще один таймер, вызывающийся каждые 64 такта.

    Поэтому для начала лучше прописать
    #define TCNT2_Const (256-4)
    В результате наш таймер будет вызываться каждые 32*4 такта.
    Все бы хорошо, но как "засунуть" этот код в "стандартную" среду от ардуины?

    P.S. Написал вопрос в личку, но ответа нет. Буду писать тут. Сорри.

  10. #20
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Помогите. Не могу понять тянет ли ардуино проект.

    TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2
    TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика
    TCCR2B &= ~(1<<WGM22);// Режим работы таймера/счетчика
    TCCR2B |= (1<<CS20)|(1<<CS21); //(1<<CS21)|(1<<CS20)|(1<<CS22); //установка предделителя 32
    ASSR &= ~(1<<AS2); //Выбор источника синхронизации таймера если AS2=0 от системного генератора
    TCNT2 = TCNT2_Const;
    TIMSK2 |= (1<<TOIE2);//Разрешение прерывания по переполнению Т2.
    sei();

    Это можно просто переписать - инициализирует таймер.

    volatile uint16_t WaveLength;
    volatile uint16_t CalcedWaveLength;
    объявляет две переменных, которые не должны быть оптимизированы процессором.
    Беззнаковые, 16-битные.

    for (;
    {
    for (;CalcedWaveLength==0;
    uint16_t cwl=CalcedWaveLength;
    CalcedWaveLength=0;
    UART_SendByte(cwl&255);
    UART_SendByte(cwl>>8);


    }

    Это основной цикл, который можно запихнуть в void Loop(void);

    Ждет пока в CalcedWaveLength будет что-то отличное от нуля, копирует его в переменную, отправляет в uart (в бинарном виде), и обнуляет.

    SIGNAL(TIMER2_OVF_vect)
    {
    TCNT2=TCNT2_Const; // задает параметр таймера. Переписать как есть.
    uint16_t WL=WaveLength; // копирует счетчик в локальную переменную
    if (Pd2::IsSet()); // если нога Digital2 в верхнем положении
    WL++; // то увеличиваем счетчик
    else // иначе
    {
    if (WL!=0) // если там что-то было в счетчике (не 0)
    {
    CalcedWaveLength=WL; // то то, что было складываем в CalcedWaveLength
    WL=0; // и очищаем
    }
    }
    WaveLength=WL; Задаем новое значение в основной счетчик (или 0)
    }



    Итого - логика такая - таймер считает время, пока нога в верхнем положении. Для этого использует переменную - счетчик WaveLength.
    Когда таймер обнаруживает, что нога в нижнем положении, она копирует WaveLength в CalcedWaveLength, а WaveLength очищает.

Страница 2 из 6 ПерваяПервая 123456 ПоследняяПоследняя

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

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

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

Ваши права

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