|
Програмный 1-wire на прерываниях таймера, Красивый выход из прерывания с переключением контекста |
|
|
|
Sep 25 2018, 09:18
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 3-07-11
Пользователь №: 66 028

|
Моя первая реазилация 1-wire была на прерываниях от таймера и чисто на switch case, это было дикая спагетти кода, потом частично завернул в функции, но все равно не нравилось как получилось, последний раз написал на protothreads, уже как-то глаз радует, а теперь сижу и опять не доволен не охото к каждому проекту пихать protothreads, + оборачивать макросами PT_BEGIN,PT_END Как можно красиво написать похожее чисто на си ? Думаю в сторону переключения адреса, но как это сделать красиво ? на protothreads получилось такое: Код //PT_YIELD(pt); - выход из функции, + сохранение место выхода #define SetDelay_us(value) TCCR3B=0x01; TCNT3H=(0xFFFF-value*(CPU_CLK/1000000))>>8;\ TCNT3L=(0xFFFF-value*(CPU_CLK/1000000));\ PT_YIELD(pt);\
PT_THREAD(Wire_Reset_thread(struct pt *pt,unsigned char *ReturnValue)){ static unsigned short int Ack[2]; PT_BEGIN(pt); //--------------------------------------------- Ack[0]=0; Ack[1]=0; //--Переключаем линию на выход и записываем 0-- Switch_Out(); SetDelay_us(480); //--Переключаем линию на выход----------------- Switch_In(); //--------------------------------------------- SetDelay_us(80); //--------------------------------------------- Ack[0]=T1; //--------------------------------------------- SetDelay_us(250); //--------------------------------------------- Ack[1]=T1; //--------------------------------------------- if((Ack[0] == 0)&&(Ack[1] ==1)){ *ReturnValue=SENSOR_INIT_VALIDATION_SUCCESS; }else{ //------------------------------------------------------------------------------------------ //*ReturnValue=SENSOR_INIT_VALIDATION_FAIL; if((Ack[0]==1)&&(Ack[1]==1)){ *ReturnValue=TYPE_T_SHORT_CIRCUIT_1; }else{ *ReturnValue=TYPE_T_SHORT_CIRCUIT_0; } //------------------------------------------------------------------------------------------ } //--------------------------------------------- PT_END(pt); }
|
|
|
|
|
 |
Ответов
|
Sep 28 2018, 11:15
|

Местный
  
Группа: Участник
Сообщений: 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.
|
|
|
|
|
Sep 28 2018, 12:02
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Arlleex @ Sep 28 2018, 14:15)  Кстати, попутно тут хочу узнать, как красиво организовать счётчик, который считает до, например, 5 и сбрасывается в 0 без условия if(). Ну то есть вычитая, сдвигая... Интересно можно ли так сделать. Для ровных битовых чисел, как в коде выше, как видно, я битовой маской обнуляю. А вот интересно, как быть с числами, не являющихся степенями 2. Код int i, i1; i1 = i - 5 >> 31; i = i - i1 & i1; Будет 3 или 4 команды (в зависимости от оптимизации). Цитата(Arlleex @ Sep 28 2018, 14:54)  Почему? Именно по сравнению: как только заданный период прошёл (счётчик таймера сравнялся с указанным значением сравнения), формируется прерывание, в котором регистр сравнения перенастраивается на следующий интервал, а лапка дергается в соответствующую сторону  А чтение значения ноги когда? Если по этому прерыванию, то так делать - ненадёжно, так как будет зависимо от задержек входа в ISR. К тому же - требует в 2 раза большей частоты прерываний. Цитата(Arlleex @ Sep 28 2018, 14:54)  А захват - это защёлкивание текущего значения таймера по какому-либо событи'юю, как я понимаю эту всю кухню. Вот именно. А потом анализируем защёлкнутое значение и решаем что это было - 0 или 1.
|
|
|
|
|
Sep 28 2018, 12:07
|

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

|
Цитата(jcxz @ Sep 28 2018, 15:02)  Код int i, i1; i1 = i - 5 >> 31; i = i - i1 & i1; Будет 3 или 4 команды (в зависимости от оптимизации). Благодарю! Потестирую
|
|
|
|
|
Sep 28 2018, 13:08
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Arlleex @ Sep 28 2018, 15:07)  Благодарю! Потестирую  Можно ещё проще, но значения чисел будут не через 1, а через большие промежутки. Типа так: Код #define LIMIT 5 #define STEP ((u32)(((1u << 31) + LIMIT - 1) / LIMIT)) //значение шага округлённое до ближайшего бОльшего целого u32 i; i = __USAT(i + STEP, 31); Всего две операции.  Значения шагов будут: STEP*0, STEP*1, STEP*2, STEP*3, STEP*4, а на следующем шаге получим опять STEP*0. Для switch-а такие значения конечно неудобны.  Ещё вариант - использовать отрицательный диапазон чисел: Код enum {LIMIT = 5}; int i = -LIMIT; i -= i >> 31 | LIMIT; //-5,-4,-3,-2,-1,0 Всего 3 операции
|
|
|
|
Сообщений в этой теме
pokk Програмный 1-wire на прерываниях таймера Sep 25 2018, 09:18 Forger Цитата(pokk @ Sep 25 2018, 12:18) Как мож... Sep 25 2018, 12:46 pokk ЦитатаВзять что-нибудь уже готовое: тыц.
Ну так та... Sep 26 2018, 01:15 Forger Коли вы так боитесь RTOS, то пользуйтесь и дальше ... Sep 26 2018, 05:22 jcxz Цитата(pokk @ Sep 26 2018, 04:15) Ну так ... Sep 26 2018, 06:30  MegaVolt Цитата(jcxz @ Sep 26 2018, 09:30) Учитесь... Sep 26 2018, 09:49   jcxz Цитата(MegaVolt @ Sep 26 2018, 12:49) С ч... Sep 26 2018, 09:51    Forger Имхо, вся эта тема какая-то бессмысленная. Как-буд... Sep 26 2018, 09:55 pokk ЦитатаУчитесь обходиться без задержек, это я умею ... Sep 26 2018, 07:33 uriy При отсутствии аппаратного 1wire принято использов... Sep 26 2018, 18:45 jcxz Цитата(uriy @ Sep 26 2018, 21:45) При отс... Sep 26 2018, 22:07  Forger Цитата(jcxz @ Sep 27 2018, 01:07) то объя... Sep 27 2018, 05:04   Smen Цитата(Forger @ Sep 27 2018, 10:04) для э... Sep 27 2018, 05:23    Forger Цитата(Smen @ Sep 27 2018, 08:23) Т.е. ис... Sep 27 2018, 05:30 Aner Да использовал я такое ранее, инвертора от тини-ло... Sep 26 2018, 19:08 Forger Цитата(Aner @ Sep 26 2018, 22:08) Особенн... Sep 26 2018, 19:13  Aner QUOTE (Forger @ Sep 26 2018, 22:13) Какие... Sep 26 2018, 19:36   Forger Цитата(Aner @ Sep 26 2018, 22:36) Ну ка р... Sep 26 2018, 19:48 k155la3 Цитата(pokk @ Sep 25 2018, 12:18) . . . К... Sep 26 2018, 19:35 Aner Потому вы и есть любители, не разу не прошедшие се... Sep 26 2018, 19:51 rx3apf Т.е. по делу сказать нечего ? Кто б сомневался... Sep 26 2018, 19:55 VAI Когда-то я выкладывал сюда код, работающий на STM3... Sep 27 2018, 10:50 toweroff 1-Wire вполне себе реализовывался на SPI 32bit. Пр... Sep 27 2018, 11:03 AlexandrY Цитата(toweroff @ Sep 27 2018, 14:03) 1-W... Sep 27 2018, 11:17  toweroff Цитата(AlexandrY @ Sep 27 2018, 14:17) Лу... Sep 27 2018, 11:25   Integro ЦитатаКрасивый выход из прерывания с переключением... Sep 27 2018, 12:29 uriy Решение на uart 1wire Отлично работает даже с usb-... Sep 28 2018, 04:54 jcxz Цитата(uriy @ Sep 28 2018, 07:54) Решение... Sep 28 2018, 05:24 jcxz Цитата(Arlleex @ Sep 28 2018, 14:15) Не з... Sep 28 2018, 11:21  Arlleex Цитата(jcxz @ Sep 28 2018, 14:21) Вы наве... Sep 28 2018, 11:54  toweroff Цитата(jcxz @ Sep 28 2018, 14:21) Вообще ... Sep 28 2018, 20:35   Forger Цитата(toweroff @ Sep 28 2018, 23:35) пре... Sep 28 2018, 20:55   jcxz Цитата(toweroff @ Sep 28 2018, 23:35) пре... Sep 28 2018, 21:54
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|