www.open-tager.ru

открытый лазертаг форум
Текущее время: 19 апр 2024, 19:31

Часовой пояс: UTC + 3 часа [ Летнее время ]


Реклама

Правила форума


В разделе запрещены - обсуждение оборудования не поддерживающего открытых протоколов, реклама и ссылки на готовые продукты лазертага, обсуждение политики производителей и самих производителей. Виден всем.



Начать новую тему Ответить на тему  [ Сообщений: 169 ]  На страницу Пред.  1, 2, 3, 4, 5, 6 ... 17  След.
Автор Сообщение
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 00:08 
Не в сети
Старожил

Зарегистрирован: 18 мар 2015, 13:19
Сообщений: 574
Откуда: Нижний Новгород
Итак, по итогам первого дня работы:

1. Вот репозиторий: https://github.com/DAlexis/lasertag-smart-sensor .
2. Там есть проект STM32Cube, настроеный практически полностью. Тулчейн - gcc, cmake. Проект компилируется и прошивается. Перегенерация проекта в Кубе ничего не портит.
3. В проект добавлен newlib.c - так что нет проблем с принтфами и динамической памятью. Пока-что для отладки printf работает через UART1. Последовательный порт у контроллера всего один, а Cortex-M0 не умеют выводить текст через SWD :(
4. Написан ИК-приемник. Пакеты успешно принимаются, работа протестирована, вроде всё надежно.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 00:27 
Не в сети
Старожил

Зарегистрирован: 18 мар 2015, 13:19
Сообщений: 574
Откуда: Нижний Новгород
LTagKirov писал(а):
Alexies писал(а):
И, разумеется, "тупые" датчики с одной зоной поражения всё равно будут поддерживаться в Caustic.
Почему с одной, Каустик вроде позволяет подключить несколько групп проводных датчиков на несколько разных входов ?

Да, все верно. Но вряд ли целесообразно поддерживать оба варианта "многозонности". Зоны поражения в текущем виде требуют место на плате под ключи и разъёмы. Это одна из причин разработки смарт-сенсоров. Мне представляется логичным оставить одну тупую зону + много умных.

LTagKirov писал(а):
ЗЫ. Схемы Каустика окончательной в варианте картинки доступной с планшетника так и не выложили.

Да, все время забываю! Теперь выложил, ссылки на pdf-ки тут: http://ltcaustic.org/for-developers/schematics.html


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 11:22 
Не в сети
Аксакал форума
Аватар пользователя

Зарегистрирован: 12 авг 2011, 16:55
Сообщений: 7514
Откуда: Барнаул, Алтайский край (не путать с республикой Алтай) :-)
Тоже реализовал приём пакета, но по своему - аппаратно таймером, как и предлагал. :)
Использовал Таймер3 и ножку PA6.
На Кокосе проект, библиотека SPL.

Код:
#include "stm32f0xx.h"
#include "stm32f0xx_crc.h"
#include "stm32f0xx_dma.h"
#include "stm32f0xx_exti.h"
#include "stm32f0xx_flash.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_syscfg.h"
#include "stm32f0xx_i2c.h"
#include "stm32f0xx_pwr.h"
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_rtc.h"
#include "stm32f0xx_spi.h"
#include "stm32f0xx_tim.h"
#include "stm32f0xx_usart.h"


#ifndef bool

                        #define bool unsigned char

                        #define true 1

                        #define false 0

#endif



GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef timer3;
GPIO_InitTypeDef port;
TIM_ICInitTypeDef TIM_ICStructure;

void init_pwm_TIM3(void){

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
   GPIO_StructInit(&port);
   port.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN;
   port.GPIO_Pin = GPIO_Pin_6;
   GPIO_Init(GPIOA, &port);

//   GPIO_PinAFConfig(GPIOA,GPIO_Pin_6,GPIO_AF_1);
   GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_1);
   TIM_TimeBaseStructInit(&timer3);
   timer3.TIM_Prescaler = /*72*/(SystemCoreClock/1000000)-1;//считаем микросекунды
    TIM_TimeBaseInit(TIM3, &timer3);

    TIM_ICStructure.TIM_Channel = TIM_Channel_1;//первый канал
    TIM_ICStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; // по заднему фронту
    TIM_ICStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // прямо с ножки
    TIM_ICStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // без делителя
    TIM_ICStructure.TIM_ICFilter = 0; // без фильтра

    // эта функция и включает режим PWM input - автоматически настраивает комплементарный канал
              // правда в стандартной библиотеке работает на 1 и 2 канале, на 3 и 4 - не умеет
    TIM_PWMIConfig(TIM3, &TIM_ICStructure);

    /* Выбираем источник для триггера: вход 1 */
    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
    /* По событию от триггера счётчик будет сбрасываться. */
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
    /* Включаем события от триггера */
    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

    // это третий канал, для таймаута. Таймаут 15мс, поскольку максимальный бит (старт) 13.5мс
    TIM_OCInitTypeDef TIM_OCStructure;
    TIM_OCStructure.TIM_OCMode = TIM_OCMode_Timing;
    TIM_OCStructure.TIM_OutputState = TIM_OutputState_Disable;
    TIM_OCStructure.TIM_OutputNState = TIM_OutputNState_Disable;
    TIM_OCStructure.TIM_Pulse = 15000;
    TIM_OC3Init(TIM3, &TIM_OCStructure);

    /* Разрешаем таймеру генерировать прерывание по захвату */
    TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
    // и по таймауту третьего канала
    TIM_ITConfig(TIM3, TIM_IT_CC3, DISABLE /*ENABLE*/);

    TIM_ClearFlag(TIM3, TIM_FLAG_CC1);
    TIM_ClearFlag(TIM3, TIM_FLAG_CC3);

    /* Включаем таймер */
     TIM_Cmd(TIM3, ENABLE);
     //устанавливаем приоритет, долен быть больше 11 для корректной работы FreeRTOS
     NVIC_SetPriority(TIM3_IRQn, 12);
     // разрешаем прерывания
     NVIC_EnableIRQ(TIM3_IRQn);
}


//Определим перечисляемый тип для событий ИК-приемника
enum Rx_Event {
            NOT_EVENT,       //нет событий
            RX_COMPLETE,    //принят пакет
            RX_MESSAGE_COMPLETE,//принято сообщение
            RX_ERROR      //ошибка приема пакета
            };
typedef enum Rx_Event trx_event; //Определим перечисляемый тип для событий ИК-приемника


enum damage_zone{
   zone_4,
   zone_3,
   zone_2,
   zone_1
};
typedef enum damage_zone TDamageZone;
#define ZONE_RX_BUFFER_SIZE   40 //Размер буффера приемника зон поражения
volatile uint8_t zone3_rx_buffer[ZONE_RX_BUFFER_SIZE];    //Буффер ИК-приемника

void set_zone_buffer_bit (TDamageZone zone, uint8_t index, bool value){
   uint8_t byte_index;
   uint8_t bit_index;
   byte_index = index/8; //Определяем, в каком байте нахадится нужный бит
   bit_index = index - (byte_index*8);//Определяем номер бита в байте


            switch(zone)
            {
               case zone_1:
               {
//                  if(value) zone1_rx_buffer[byte_index]|= (1<<(7-bit_index));

//                  else zone1_rx_buffer[byte_index] &= ~(1<<(7-bit_index));

               }
               break;
               case zone_2:
               {

//                  if(value) zone2_rx_buffer[byte_index]|= (1<<(7-bit_index));

//                  else zone2_rx_buffer[byte_index] &= ~(1<<(7-bit_index));
               }
               break;
               case zone_3:
               {

                  if(value) zone3_rx_buffer[byte_index]|= (1<<(7-bit_index));

                  else zone3_rx_buffer[byte_index] &= ~(1<<(7-bit_index));
               }
               break;
               case zone_4:
               {

//                  if(value) zone4_rx_buffer[byte_index]|= (1<<(7-bit_index));

//                  else zone4_rx_buffer[byte_index] &= ~(1<<(7-bit_index));
               }
               break;
            }

}



enum recStatus{
   REC_Idle,
   REC_Recording,
   REC_Captured
};
typedef enum recStatus TRecStatus;

volatile TRecStatus tim3_rec_state=REC_Idle;
volatile uint16_t tim3_ir_rx_count=0;
#define IR_RAW_BUFFER_SIZE 256 //размер буфера ИК-приемника
#define IR_START_BIT_DURATION 2400   // Длительность Старт-Бита (в микросекундах)
#define IR_ONE_BIT_DURATION 1200   // Длительность Бита, соотретствующего единичке (в микросекундах)
#define IR_ZERO_BIT_DURATION 600   // Длительность Бита, соотретствующего нулю (в микросекундах)
#define IR_SPACE_DURATION 600      // Длительность Бита, соотретствующего интервалу между битами (в микросекундах)

#define IR_TOL                      20 //Допустимая погрешность при приеме ИК пакета (в процентах


volatile trx_event Zone3RxEvent;//события 3-ей зоны

// этот дефайн просто сравнивает значения с заданной точностью в процентах
#define checkVal(var,val,tol) (var>(val*(100-tol)/100) && var<(val*(100+tol)/100))

void TIM3_IRQHandler(void)//3-я зона
{

   uint16_t cnt1, cnt2;
           if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) {
                   TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
                   TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

                   cnt1 = TIM_GetCapture1(TIM3);
                   cnt2 = TIM_GetCapture2(TIM3);

                   if (tim3_rec_state == REC_Recording)
                   {

                      if (tim3_ir_rx_count  < IR_RAW_BUFFER_SIZE) {
                         if(tim3_ir_rx_count==0)//первым должен идти заголовок
                         {
                            if(checkVal(cnt2,IR_START_BIT_DURATION,IR_TOL))//проверяем заголовок на ошибку
                            {
                               tim3_ir_rx_count++;
                            }
                            else //заголовок "битый"
                            {
                               // запрещаем прерывания по переполнению третьего канала
                               TIM_ITConfig(TIM3, TIM_IT_CC3, /*ENABLE*/DISABLE);
                               tim3_rec_state = REC_Idle;
                               tim3_ir_rx_count=0;
                        }
                         }
                         else //заголовок уже получен, идет прием данных
                         {
//                            TIM3_IR_RX_RAW_BUFFER[tim3_ir_rx_count-1].Period=cnt1;
//                              TIM3_IR_RX_RAW_BUFFER[tim3_ir_rx_count-1].Pulse=cnt2;

                            if(checkVal(cnt2,IR_ONE_BIT_DURATION,IR_TOL)&&checkVal(cnt1,IR_ONE_BIT_DURATION+IR_SPACE_DURATION, IR_TOL))
                            {
                               set_zone_buffer_bit(zone_3,tim3_ir_rx_count-1,true);//это единица
                               tim3_ir_rx_count++;
                            }
                            else if (checkVal(cnt2, IR_ZERO_BIT_DURATION,IR_TOL)&&checkVal(cnt1,IR_ZERO_BIT_DURATION+IR_ZERO_BIT_DURATION,IR_TOL))
                            {
                               set_zone_buffer_bit(zone_3,tim3_ir_rx_count-1,false);//это ноль
                               tim3_ir_rx_count++;
                            } else {//ошибка
                               TIM_ITConfig(TIM3, TIM_IT_CC3, /*ENABLE*/DISABLE);
                               tim3_rec_state = REC_Idle;
                               tim3_ir_rx_count=0;
                        }



                         }
                           }
                      else {//слишком длинный пакет - ошибка
                          // запрещаем прерывания по переполнению третьего канала
                              TIM_ITConfig(TIM3, TIM_IT_CC3, /*ENABLE*/DISABLE);
                               tim3_rec_state = REC_Idle;
                               tim3_ir_rx_count=0;
                  }

                   }


                   if (tim3_rec_state == REC_Idle) {
                           //Пришел первый фронт, начинаем запись
                      //разрешаем прерывания по 3 каналу, предварительно очистив флаг
                      TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
                      TIM_ITConfig(TIM3, TIM_IT_CC3, ENABLE);
                      tim3_rec_state = REC_Recording;
   //                        captCount = 0;

                   }

           }//[if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) ]

           if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET) {//если таймаут по приёму
                   TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
                   if (tim3_rec_state == REC_Recording) {

                      if((tim3_ir_rx_count==14)||(tim3_ir_rx_count==24))
                      {
                         cnt2 = TIM_GetCapture2(TIM3);
                         if(checkVal(cnt2,IR_ONE_BIT_DURATION,IR_TOL))
                         {
                            set_zone_buffer_bit(zone_3,tim3_ir_rx_count-1,true);//это единица
//                            tim3_ir_rx_count++;
                         }
                         else if (checkVal(cnt2, IR_ZERO_BIT_DURATION,IR_TOL))
                         {
                         set_zone_buffer_bit(zone_3,tim3_ir_rx_count-1,false);//это ноль
//                         tim3_ir_rx_count++;
                         } else {//ошибка
                                     TIM_ITConfig(TIM3, TIM_IT_CC3, /*ENABLE*/DISABLE);
                                     tim3_rec_state = REC_Idle;
                                     tim3_ir_rx_count=0;
                                    Zone3RxEvent=RX_ERROR;
//                                    xSemaphoreGiveFromISR( xZone3Semaphore, &xHigherPriorityTaskWoken);

                               }

                         tim3_rec_state = REC_Captured;
                         if(tim3_ir_rx_count==14)Zone3RxEvent=RX_COMPLETE;
                         else Zone3RxEvent=RX_MESSAGE_COMPLETE;
//                         xSemaphoreGiveFromISR( xZone3Semaphore, &xHigherPriorityTaskWoken );

                      }
                      else {//ошибка
                         tim3_rec_state = REC_Idle;
                         Zone3RxEvent=RX_ERROR;
//                         xSemaphoreGiveFromISR( xZone3Semaphore, &xHigherPriorityTaskWoken );
                  }

                      // запрещаем прерывания по переполнению третьего канала
                      TIM_ITConfig(TIM3, TIM_IT_CC3, /*ENABLE*/DISABLE);
      //                tim5_rec_state = REC_Idle;

                      tim3_ir_rx_count=0;
                      //xSemaphoreGiveFromISR( xZone4Semaphore, &xHigherPriorityTaskWoken );
                   }

           }



}



int main(void)
{
   init_pwm_TIM3();
    while(1)
    {

    }
}



_________________
Ваше оружие становиться значительно эффективней, если его снять с предохранителя!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 15:54 
Не в сети
Старожил

Зарегистрирован: 18 мар 2015, 13:19
Сообщений: 574
Откуда: Нижний Новгород
Pingvin писал(а):
Тоже реализовал приём пакета, но по своему - аппаратно таймером, как и предлагал. :)
Использовал Таймер3 и ножку PA6.
На Кокосе проект, библиотека SPL.

Понятно, что это прототип, но тем не менее позволю себе несколько замечаний по поводу кода. Вот некоторые вещи, которые бросились в глаза:
Читать тяжело, с отступами что-то не так. Чтобы мигом всё исправить, можете использовать утилиту для автоматического форматирования кода:
Код:
astyle --style=bsd <filename>

Или инструменты вашей IDE.
Не выделено никакого API для работы с приемником. Какие функции нужно вызывать, чтобы получить данные и т.п.
Зачем там разные зоны поражения? Судя по коду, работает только номер 3. Для одного датчика несколько зон - это перебор...
Почему пакеты, для которых не выполняется условие
Код:
if((tim3_ir_rx_count==14)||(tim3_ir_rx_count==24))
считаются испорченными? Умный датчик не должен ничего знать о протоколе, в том числе и о возможной длине сообщений.
Ну и по поводу SPL много раз уже высказывался...

Вот мой вариант гораздо короче (примерно в 2 раза). И тоже использует аппаратный захват.
Вот заголовочный файл:
https://github.com/DAlexis/lasertag-sma ... receiver.h
Вот сам код:
https://github.com/DAlexis/lasertag-sma ... receiver.c


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 16:46 
Не в сети
Аксакал форума
Аватар пользователя

Зарегистрирован: 12 авг 2011, 16:55
Сообщений: 7514
Откуда: Барнаул, Алтайский край (не путать с республикой Алтай) :-)
Да просто хотел запустить прием пакета, скопипастил код настройки и прерывания.
Была тут пара "подводных камней" (особенности нулевой серии) - разобрался.
Функции API - не успел вставить, но они есть, конечно.
Но они для получения значений урона, ИД, команд и прочего из "сырых" данных пакета или сообщения.
То есть для анализа содержимого.
Если не нужно анализировать пакет, то и не надо ничего дополнительного - всё уже есть в приведённом коде.
Данные складываются в буфер, по окончании приема генерируется событие.
Хотел показать как работает аппаратный прием.
Зона конечно одна останется.


Если у Вас аппаратный захват, зачем это тогда?
Код:
void ir_task_tick()
{
uint16_t ticks_count = htim14.Instance->CNT;
uint16_t ticks_diff = ticks_count - last_edge_ticks;
if (receiver_state == RS_WAITING_HEADER)
{
last_edge_ticks = ticks_count;
} else if (ticks_to_us(ticks_diff) > IR_MSG_END_DELAY)
{
memcpy(&user_buffer, &temporary_buffer, sizeof(temporary_buffer));
data_ready = 1;
reset_receiver();
}
}


У меня сразу и период и длительность импулься в регистрах таймера лежат, не надо ничего вычислять.
А в случае таймоута по приему генерит прерывание третий канал таймера.
Весь прием - в одном обработчике прерывания.
"Наружу" в главный цикл выдается событие и буфер с полученными данными.


На самом деле - это простенькая штучка, тут вариантов можно разных напридумывать, ничего страшного, лишь бы протокол обмена был единый.
Я просто удовлетворяю своё любопытство. ;) :)
За наводку на утилиту - спасибо!

_________________
Ваше оружие становиться значительно эффективней, если его снять с предохранителя!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 17:47 
Не в сети
Старожил

Зарегистрирован: 18 мар 2015, 13:19
Сообщений: 574
Откуда: Нижний Новгород
Pingvin писал(а):
Если у Вас аппаратный захват, зачем это тогда?
Код:
void ir_task_tick()


Функция void ir_task_tick() проверяет таймаут из главного потока программы, чтобы не нагружать лишней работой прерывание, и чтобы не было проблем в случае, если один из фронтов будет пропущен по каким-то причинам, например пришло два передних фронта подряд без заднего, и соответствующее прерывание не сработало.

Pingvin писал(а):
У меня сразу и период и длительность импулься в регистрах таймера лежат, не надо ничего вычислять.
А в случае таймоута по приему генерит прерывание третий канал таймера.
Весь прием - в одном обработчике прерывания.
"Наружу" в главный цикл выдается событие и буфер с полученными данными.

Я не уверен, что ваш код работает во всех ситуациях корректно. Вы его тестировали с реальным сигналом?
Не ясно например, что происходит при переполнении таймера. У вас нигде в коде не задается его период (в поле timer3.TIM_Period лежит мусор к моменту вызова TIM_TimeBaseInit(TIM3, &timer3) ), а также не обрабатывается прерывание по его переполнению.
Хотя я не разобрал полностью логику вашего обработчика, слишком много всего вместе...


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 17:52 
Не в сети
Аксакал форума
Аватар пользователя

Зарегистрирован: 12 авг 2011, 16:55
Сообщений: 7514
Откуда: Барнаул, Алтайский край (не путать с республикой Алтай) :-)
Конечно проверял! :lol:
http://www.youtube.com/watch?v=tiMkHheKCco
Переполнения таймера быть не может - сработает третий канал - сгенерирует прерывание, если будет отсутствие сигнала более 15 mS.

Как могут прийти два фронта без спада - я вообще не понял! :?

Логика простая!
Изображение

Приходит фронт - счетчик обнуляется.
Первый канал считает до спада.
Спад пришел - в первом канале длительность импульса.
Второй канал ловит фронт, фронт пришел - во втором канале имеем полный период, и тут же по фронту сброс счётчика и все по новой.

А в IC1 и IC2 имеем длительность импулься и период! ;) :)

Если же более 15 mS фронт не пришел - таймаут по приёму (третий канал произведёт захват и выставит флаг прерывания TIM_IT_CC3)- обрабатываем.

Код:

    // это третий канал, для таймаута. Таймаут 15мс, поскольку максимальный бит (старт) 13.5мс
    TIM_OCInitTypeDef TIM_OCStructure;
    TIM_OCStructure.TIM_OCMode = TIM_OCMode_Timing;
    TIM_OCStructure.TIM_OutputState = TIM_OutputState_Disable;
    TIM_OCStructure.TIM_OutputNState = TIM_OutputNState_Disable;
    TIM_OCStructure.TIM_Pulse = 15000;
    TIM_OC3Init(TIM3, &TIM_OCStructure);

    /* Разрешаем таймеру генерировать прерывание по захвату */
    TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
    // и по таймауту третьего канала
    TIM_ITConfig(TIM3, TIM_IT_CC3, DISABLE /*ENABLE*/);

Никакого переполнения не будет.

Цитата:
(в поле timer3.TIM_Period лежит мусор к моменту вызова TIM_TimeBaseInit(TIM3, &timer3) ),


Это не мусор!!!

Код:
 TIM_OCStructure.TIM_Pulse = 15000;


Это 15000 uS = 15 mS
Таймаут!

Счетчик таймера тикает каждую микросекунду! ;) :)

Код:
 timer3.TIM_Prescaler = (SystemCoreClock/1000000)-1;//считаем микросекунды

_________________
Ваше оружие становиться значительно эффективней, если его снять с предохранителя!


Последний раз редактировалось Pingvin 26 дек 2016, 18:28, всего редактировалось 9 раз(а).

Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 18:10 
Не в сети
Аксакал форума
Аватар пользователя

Зарегистрирован: 12 авг 2011, 16:55
Сообщений: 7514
Откуда: Барнаул, Алтайский край (не путать с республикой Алтай) :-)
Как у Вас происходит захват?
Я так и не понял... :?

_________________
Ваше оружие становиться значительно эффективней, если его снять с предохранителя!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 26 дек 2016, 18:52 
Не в сети
Аксакал форума

Зарегистрирован: 29 авг 2011, 11:08
Сообщений: 1849
Pingvin писал(а):
Как происходит захват?
Тоже интересно стало, глянул код одним глазком 8-)

1. "Заряжается" таймер для счётчика измерения длительности, подробности надо уточнить, практически это самое интересное ;)
2. Функция обратного вызова срабатывает после импульса на ножке или по таймеру?, интересно на любую
ножку можно повесить такую функцию ? И на каждую ножку будет нужен свой обработчик ?
Есть ли ограничение на количество ножек, ну кроме корпуса МК?
3. Импульс разбирается на соответствие части пакета с помощью автомата.
4. По результату разбора пакета - автомат обнуляется.
5. Полученный пакет хранится в буфере и забирается по мере необходимости.

_________________
"За 2 месяца максимум можно чертёж сделать, еще за 3 фундамент." (c) Номернабис


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Умный датчик. Smart sensor.
СообщениеДобавлено: 27 дек 2016, 13:26 
Не в сети
Старожил

Зарегистрирован: 18 мар 2015, 13:19
Сообщений: 574
Откуда: Нижний Новгород
Pingvin писал(а):
Переполнения таймера быть не может - сработает третий канал - сгенерирует прерывание, если будет отсутствие сигнала более 15 mS.
...
Приходит фронт - счетчик обнуляется.
Первый канал считает до спада.
Спад пришел - в первом канале длительность импульса.
Второй канал ловит фронт, фронт пришел - во втором канале имеем полный период, и тут же по фронту сброс счётчика и все по новой.

А в IC1 и IC2 имеем длительность импулься и период! ;) :)
Если же более 15 mS фронт не пришел - таймаут по приёму (третий канал произведёт захват и выставит флаг прерывания TIM_IT_CC3)- обрабатываем.
Никакого переполнения не будет.

Цитата:
(в поле timer3.TIM_Period лежит мусор к моменту вызова TIM_TimeBaseInit(TIM3, &timer3) ),

Это не мусор!!!
Код:
 TIM_OCStructure.TIM_Pulse = 15000;

Это 15000 uS = 15 mS
Таймаут!
Счетчик таймера тикает каждую микросекунду! ;) :)
Код:
 timer3.TIM_Prescaler = (SystemCoreClock/1000000)-1;//считаем микросекунды


Вы не точно прочитали мое сообщение, я там другой фрагмент кода "цитировал".
Таймер - это счетчик, который начинает считать в вашем случае по внешнему событию (триггеру) до некоторого значения, затем автоматически сбрасывается, и считает заново с нуля. Каналы таймера отвечают за события, происходящие по достижении таймером определенных значений, или реакцию на внешние события. Но каналы не имеют своего счетчика, счетчик один на всех, и на предел счета код инициализации каналов не влияет никак. Предел счета определен при инициализации самого таймера, в случае 16-бит таймера он не превышает 65535. Инициализация периода таймера у вас происходит именно в том коде, про который я говорил:
Код:
TIM_TimeBaseInitTypeDef timer3;
...
 TIM_TimeBaseStructInit(&timer3);
   timer3.TIM_Prescaler = /*72*/(SystemCoreClock/1000000)-1;//считаем микросекунды
    TIM_TimeBaseInit(TIM3, &timer3);

"Мусором" называется то, что лежит в неинициализированных переменных. Вы явно не инициализируете поле timer3.TIM_Period ничем. Но я ошибся, мусора там нет, я незаметил вызов TIM_TimeBaseStructInit(&timer3), в качестве периода по-умолчанию внутри неё задается 0xFFFF - максимальное значение (посмотрите её код). Это плохая практика, полагаться на значения по-умолчанию, но именно это спасает ваш код. Иначе таймер бы переполнялся через непредсказуемое время.

А поля структуры TIM_OCStructure, о которой вы пишите, не имеют никакого отношения к периоду таймера.

Pingvin писал(а):
Как могут прийти два фронта без спада - я вообще не понял! :?

Когда быстро приходят два фронта, обработчик прерывания вызывается на первый фронт, в это время приходит второй, но обработчик ещё работает, поэтому ничего не происходит. Вне зависимости от того, где вы очищаете флаг прерывания, такая штука может произойти. Я не уверен, что с вашим кодом будут проблемы в данной ситуации, но из него не очевидно, что проблем не будет.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 169 ]  На страницу Пред.  1, 2, 3, 4, 5, 6 ... 17  След.

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8


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

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB