реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Програмный 1-wire на прерываниях таймера, Красивый выход из прерывания с переключением контекста
Aner
сообщение Sep 26 2018, 19:51
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 4 869
Регистрация: 28-02-08
Из: СПБ
Пользователь №: 35 463



Потому вы и есть любители, не разу не прошедшие сертификацию ваших поделок - недоделок.
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Sep 26 2018, 19:55
Сообщение #17


Гуру
******

Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047



Т.е. по делу сказать нечего ? Кто б сомневался...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Sep 26 2018, 22:07
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(uriy @ Sep 26 2018, 21:45) *
При отсутствии аппаратного 1wire принято использовать uart https://www.maximintegrated.com/en/app-note...ndex.mvp/id/214

Кем принято?
Открываем указанную ссылку, читаем:
Для сброса и обнаружения устройства нужно послать код 0xF0 на скорости 9600. И:
1) "если устройства нет, то на RX получим 0xF0"; Утверждение не вызывает сомнения.
2) "если устройство есть, то на RX получим что-то отличное от 0xF0"; А вот тут уже - фиг вам!
Открываем описание интерфейса 1-wire, читаем:
Чтобы сформировать сигнал «Reset», — «Мастер» должен притянуть уровень на шине к нулю на время не менее 480 мкс и не более 960 мкс (480 мкс ≤ TRSTL < 960 мкс). После этого он должен отпустить шину и, не менее, чем на 480 мкс, прекратить свою активность на шине (TRSTH > 480 мкс). «Слэйвы», не ранее, чем через 15 мкс, но и не позднее, чем через 60 мкс после того, как «Мастер» отпустит шину (15 мкс < TPDH < 60 мкс), должны сформировать на шине низкий уровень (это и есть сигнал присутствия), длительностью от 60 до 240 мкс (60 мкс < TPDL < 240 мкс), после чего они также отпускают шину.
Оп-ля - приехали! 05.gif
При скорости 9600 длительность бита == 104мкс. Предположим что частоты генераторов мастера и слэйва идеально совпадают. Тогда, после завершения передачи мастером младших 4-х бит кода 0xF0, на шине наступит фронт сигнала. И в это время UART мастера начнёт приём 4-го бита. Точка сэмплирования этого бита находится на расстоянии 104/2=52мкс от указанного фронта (конца RESET). Но ведь из описания выше следует, что слэйв имеет право начать формировать сигнал присутствия через 60мкс после завершения RESET. Т.е. - уже после того как мастер считает с шины состояние 4-го бита! И мастер получит в 4-м бите лог.1. smile3009.gif
Окей, ладно - может хоть в следующем бите мастер сможет узреть на шине несчастного слэйва?? fman.gif
Но опять же - из описания выше можно узнать, что сигнал присутствия генерируемый слэйвом, может быть длительностью всего 60мкс. Но ведь мы помним, что между точками сэмплирования RX-битов мастером расстояния == 104 мкс (1 бит UART). Получается, что если импульс присутствия начнётся через 60 мкс после конца RESET и продлится всего 60 мкс, то он аккурат проскочит между двумя точками сэмплирования UART.RX мастера. И мастер его просто не заметит!
Хотя мальчик-то есть, но вот колхоз на UART его не видит.... crying.gif
А значит такую реализацию уже нельзя считать 1-wire. Ну никак нельзя.
И это мы ещё даже не учли влияния разности частот генераторов мастера и слэйва, а также влияние ёмкости линии. А также не учли, что делитель UART-а может быть дробным (а длина бита UART - переменной). Там будет ещё веселее.
После этого дальше читать указанную ссылку смысла уже нет.

Цитата(Forger @ Sep 26 2018, 22:48) *
Да этому "стандарту" уже почти 30 лет, обсосан до костей.
Тайминги такие, что заведется с полпинка на любом античном МК даже на встроенном RC-генераторе.

Да ладно?
Не будем углубляться в приём/передачу, но раз "обсосан", то объясните как с помощью UART хотя-бы обнаружить такой слэйв-девайс, который в полном соответствии с мануалом, формирует импульс присутствия с началом через 15...60 мкс после завершения RESET, и длительностью 60...240 мкс?
Это ведь как ловить рыбку сетью, у которой размер ячеи больше размера самой рыбки - конечно есть вероятность что поймаешь, но можно и с голоду опухнуть biggrin.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение Sep 27 2018, 05:04
Сообщение #19


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ Sep 27 2018, 01:07) *
то объясните как с помощью UART хотя-бы обнаружить такой слэйв-девайс,
Я не использую для этого UART, для этого есть аппаратные таймеры.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Smen
сообщение Sep 27 2018, 05:23
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 211
Регистрация: 18-03-13
Из: Питер
Пользователь №: 76 081



Цитата(Forger @ Sep 27 2018, 10:04) *
для этого есть аппаратные таймеры
Т.е. используются и таймеры и УАРТ?
В чём смысл?
Go to the top of the page
 
+Quote Post
Forger
сообщение Sep 27 2018, 05:30
Сообщение #21


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(Smen @ Sep 27 2018, 08:23) *
Т.е. используются и таймеры и УАРТ?
Цитирую:
Цитата(Smen)
Я не использую для этого UART


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
VAI
сообщение Sep 27 2018, 10:50
Сообщение #22


Профессионал
*****

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



Когда-то я выкладывал сюда код, работающий на STM32 и на MSP430.
Вот, смотрите, может подойдёт для Вас. http://electronix.ru/forum/index.php?showt...p;#entry1089884


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
toweroff
сообщение Sep 27 2018, 11:03
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



1-Wire вполне себе реализовывался на SPI 32bit. Правда, делал его на древнем уже LPC2103
Главное - пин MOSI правильно настроить, чтобы только вниз тянул, push-pull отключить, если возможно, или сгородить на двух транзисторах

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Sep 27 2018, 11:17
Сообщение #24


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(toweroff @ Sep 27 2018, 14:03) *
1-Wire вполне себе реализовывался на SPI 32bit. Правда, делал его на древнем уже LPC2103
Главное - пин MOSI правильно настроить, чтобы только вниз тянул, push-pull отключить, если возможно, или сгородить на двух транзисторах

Прикрепленное изображение

Лучше вот такая схема:

По I2C работает идеально. wink.gif
Go to the top of the page
 
+Quote Post
toweroff
сообщение Sep 27 2018, 11:25
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(AlexandrY @ Sep 27 2018, 14:17) *
Лучше вот такая схема:
По I2C работает идеально. wink.gif

Не, ну кто бы спорил sm.gif
Вопрос в том, что у меня без всяких +200р к стоимости девайса... Хотя, если ценник ему ковырнадцать тысяч, то и DS2484 вполне себе уместна biggrin.gif
Go to the top of the page
 
+Quote Post
Integro
сообщение Sep 27 2018, 12:29
Сообщение #26


Частый гость
**

Группа: Свой
Сообщений: 167
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460



Цитата
Красивый выход из прерывания с переключением контекста

Вам нужно посмотреть на примеры реализации механизма callback.
Вкратце, реализовываете функцию для настройки таймера в one shot режиме и в прерывании таймера (через n us) вызываете необходимый вам callback
CODE
static void (*_cb)(void) = NULL;

void TIMERn_Handler(void) {
// TODO: Clear timer status or stop if neccesary
if( _cb ) {
_cb();
}
}

void setup_timer(uint32_t delay_us, void *callback ) {
_cb = callback ;
//TODO: configure hardware timer
}

Далее, набрасываем функции которые будут вызываться последовательно:
CODE
static void _save_t1(void);
static void _reset(void);

void start(void) {
Switch_Out();
setup_timer(480, _reset);
}

static void _reset(void) {
Switch_In();
setup_timer(80, _save_t1);
}

static void _save_t1(void) {
Ack[0]=T1;
//TODO ...
if(Ack[0] == 1) {
setup_timer(80, _something1);
} else {
setup_timer(10, _something2);
}
}

Думаю суть ясна, для начала транзакиции нужно вызвать start(), а дальше все пойдет по реализованной вами цепочке.
Если таких "прижков" выйдет много, локаничней релизовать таблицы для "линейных участков":
Код
static struct {
    uinr32_t delay_us;
    void *next_cb;
}_chain_init[] = {
    {.delay_ms = 480, .next_cb = _reset},
    {.delay_ms = 80, .next_cb = _save_t1},
};

Пользовать это можно так:
Код
    index++;
    setup_timer(_chain_init[index].delay_ms , _chain_init[index].next_cb);


Ну и понятно функция setup_timer, должны бать быстрой, что бы не поплыли микросекундные тайминги.
Код писал без проверки компиляции, так что извиняйте за описки.
Go to the top of the page
 
+Quote Post
uriy
сообщение Sep 28 2018, 04:54
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 2 429
Регистрация: 30-11-05
Из: Ижевск
Пользователь №: 11 606



Решение на uart 1wire Отлично работает даже с usb-uart преобразователем CP2102. CP2102 работает без кварца и скорее всего подстраивает частоту по SOF кадрам, думаю там разброс больше чем 20 ppm.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Sep 28 2018, 05:24
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(uriy @ Sep 28 2018, 07:54) *
Решение на uart 1wire Отлично работает даже с usb-uart преобразователем CP2102.
Кроме пустословия, по делу, есть что сказать?
Ещё раз читаем: Почему UART - не 1-wire

Цитата(uriy @ Sep 28 2018, 07:54) *
CP2102 скорее всего подстраивает частоту по SOF кадрам.
Бред.
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Sep 28 2018, 11:15
Сообщение #29


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Не знаю, зачем выделять на это целый UART... Я сделал на таймере в режиме сравнения. Благодаря этому можно использовать любую ножку свободную на МК. Обработчик таймера:
CODE
#define T1 4
#define T2 7
#define T3 51
#define T4 59
#define T5 89
#define T6 409
#define T7 499

// TypeOperation - тип запрашиваемой операции:
// ONE_WIRE_INIT - формирование импульса сброса;
// ONE_WIRE_GET_TIME_SLOT - формирование тайм-слота чтения;
// ONE_WIRE_SET_TIME_SLOT_0 - формирование тайм-слота записи лог. 0;
// ONE_WIRE_SET_TIME_SLOT_0 - формирование тайм-слота записи лог. 1.
//
// ResultOperation - результат чтения тайм-слота (только при чтении).
//
// StatusOperation - флаг завершенности работы автомата.
//
// Перед использованием автомата необходимо указать тип операции и включить
// таймер TIMER_START(). Затем дождаться завершения работы автомата.
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
static unsigned char FSMState = 0;

switch(TypeOperation)
{
// автомат формирования импульса сброса
case ONE_WIRE_INIT:
{
switch(FSMState)
{
case 0: TIM2->ARR = T7; RESET_LINE(WIRE); break;
case 1: TIM2->ARR = T5; SET_LINE(WIRE); break;
case 2: TIM2->ARR = T6; ResultOperation = GET_LINE(WIRE); break;
case 3: TIMER_STOP(); TIM2->ARR = T1; StatusOperation = 1; break;
}
FSMState = (FSMState + 1) & 0x3; break;
}

// автомат формирования тайм-слота чтения
case ONE_WIRE_GET_TIME_SLOT:
{
switch(FSMState)
{
case 0: TIM2->ARR = T1; RESET_LINE(WIRE); break;
case 1: TIM2->ARR = T2; SET_LINE(WIRE); break;
case 2: TIM2->ARR = T3; ResultOperation = GET_LINE(WIRE); break;
case 3: TIMER_STOP(); TIM2->ARR = T1; StatusOperation = 1; break;
}
FSMState = (FSMState + 1) & 0x3; break;
}

// автомат формирования тайм-слота записи
case ONE_WIRE_SET_TIME_SLOT_0: case ONE_WIRE_SET_TIME_SLOT_1:
{
switch(FSMState)
{
case 0: TIM2->ARR = (TypeOperation == HW_ONE_WIRE_SET_TIME_SLOT_0) ? T4 : T1; RESET_LINE(GPIO_ONE_WIRE); break;
case 1: TIM2->ARR = (TypeOperation == HW_ONE_WIRE_SET_TIME_SLOT_0) ? T1 : T4; SET_LINE(GPIO_ONE_WIRE); break;
case 2: TIMER_STOP(); TIM2->ARR = T1; ++FSMState; StatusOperation = 1; break;
}
FSMState = (FSMState + 1) & 0x3; break;
}
}

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
}


Кстати, попутно тут хочу узнать, как красиво организовать счётчик, который считает до, например, 5 и сбрасывается в 0 без условия if(). Ну то есть вычитая, сдвигая... Интересно можно ли так сделать. Для ровных битовых чисел, как в коде выше, как видно, я битовой маской обнуляю. А вот интересно, как быть с числами, не являющихся степенями 2.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Sep 28 2018, 11:21
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Arlleex @ Sep 28 2018, 14:15) *
Не знаю, зачем выделять на это целый UART... Я сделал на таймере в режиме сравнения.

Вы наверное перепутали: наверное всё-таки в режиме захвата (capture), а не сравнения (compare). rolleyes.gif
Да, это стандартное решение. Вообще не понимаю здешних товарищей, которые пытаются колхозить на чём угодно, только не делать как надо. cranky.gif
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th April 2024 - 20:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.015 секунд с 7
ELECTRONIX ©2004-2016