|
Опрос клавиатуры на С, Как написать компактный и "красивый" код? |
|
|
|
 |
Ответов
(1 - 80)
|
Jun 23 2018, 06:38
|

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

|
Цитата(Make_Pic @ Jun 23 2018, 08:17)  Опрос клавиатуры на С -> Как написать компактный и "красивый" код? Дайте pls примеры опроса матрицы клавиш на С (C++ не надо). В своих проектах разделяю опрос клавиатуры (неважно какая, матричная или обычная) на два разных этапа: 1) опрос существующего состояния кнопок с заданной периодичностью, обычно раз в 50мс, чтобы потом не "воевать" с дребезгом. 2) анализ (сравнение) текущего и предыдущего состояния клавиатуры, тем самым выделяя события отпускания и нажатия далее в зависимости от проекта реализовывал систему подписки на различные события, если в двух словах, то речь про колбэки и их продвинутые аналоги. Модули, которым нужно ждать события от клавиатуры, "подписываются" на нужные события и кнопки, "обращаясь" к модулю клавиатуры. События всего два - отпускание и нажатие. Этого обычно вполне достаточно. Долгое удержание или т. п. реализуется уже в самом модуле. Такая схема дает возможность напрочь отвязаться от способа реализации клавиатуры: будь то "примитивные" кнопки на пинах и внешние проводные или беспроводное клавиатуры (например, пульты оператора). Т.е. я жестко разделяю опрос клавиатуры от тех модулей/блоков, которые ждут от нее реакцию. Примеры приводить не буду, т. к. вы "запретили" тут использовать C++. Однако, на голом С все описанное выше тоже реализуется, но уже несколько "топорно" и далеко не так "компактно и красиво". К счастью (кому-то к сожалению) давно не использую подобный инструментарий и поэтому примеров на нем, увы, не сохранилось (( Добавлю, что использую RTOS, т. к. под ней это реализуется значительно проще: не нужно "колдовать" с таймерами и самодельными генераторами/приемниками событий. зы. В проектах с одной/двумя кнопками все реализую значительно проще, но аналогично - периодический опрос и сравнение двух состояний: предыдущего и текущего.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 08:05
|

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

|
Цитата(Make_Pic @ Jun 23 2018, 10:20)  Я не запрещал, но понимаю, что на плюсах удобнее - приведите свой пример pls! Честно говоря, мне влом "выдерать" его из кода, чтобы было понятно, что тут происходит Поэтому выше я на словах довольно подробно описал сам принцип. Имхо, так будет намного понятнее, особенно кто ни разу ничего подобного не делал. Вообще, стараюсь документировать свой код визуально (использую для этого XMind). Не вдаваясь в нюансы и детали, но чтобы в целом все было все понятно сходу через энное время. Однако, с клавиатурами пока этого не делал, пока в планах. Пока копался в исходниках, нашел, что в одном из проектов делал чуть иначе: для работы с некой кнопкой нужно наследовать свой класс от шаблона Button<>, потом реализовать пару виртуальных методов, где нужно обрабатывать реакцию на отпускание/нажатие. Если реакция, скажем, на отпускание не нужна, то можно вообще не реализовывать соотв. метод. В моем случае функционал класса кнопки еще умеет и управлять собственной подсветкой: on/off/blink и т. п. После этого нужно лишь "подключить" этот экземпляр класса к нужной клавиатуре (в одном проекте может быть не одна клавиатура, например, распределенная система). Цитата(x893 @ Jun 23 2018, 11:03)  То есть у Вас модули в runtime подписываются/отписываются от событий клавиатуры ? В принципе, это возможно, но на практике мне пока не приходилось это использовать.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 13:40
|

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

|
Цитата(Make_Pic @ Jun 23 2018, 10:20)  Я не запрещал, но понимаю, что на плюсах удобнее - приведите свой пример pls! Ох уж эти местные плюсисты. Вот все могут, только показать ничего нормальное не могут. Спрашивается на кой было в руки брать плюсы если не способен даже модульную архитектуру создать чтобы ничего не "выдирать" из кода. Но я хочу показать еще один универсальный способ создания софта. Вот модель сканирования клавиатуры в Simulink -
А вот код на C который сгенерился по этой модели CODE /* * File: KeyboardScanModule.c * * Code generated for Simulink model 'KeyboardScanModule'. * * Model version : 1.5 * Simulink Coder version : 8.14 (R2018a) 06-Feb-2018 * C/C++ source code generated on : Sat Jun 23 17:02:12 2018 * * Target selection: ert.tlc * Embedded hardware selection: ARM Compatible->ARM Cortex * Code generation objectives: * 1. Execution efficiency * 2. Traceability * Validation result: Not run */
#include "KeyboardScanModule.h"
/* Block signals and states (default storage) */ DW rtDW;
/* External outputs (root outports fed by signals with default storage) */ ExtY rtY;
/* Real-time model */ RT_MODEL rtM_; RT_MODEL *const rtM = &rtM_; static void rate_scheduler(void);
/* * This function updates active task flag for each subrate. * The function is called at model base rate, hence the * generated code self-manages all its subrates. */ static void rate_scheduler(void) { /* Compute which subrates run during the next base time step. Subrates * are an integer multiple of the base rate counter. Therefore, the subtask * counter is reset when it reaches its limit (zero means run). */ (rtM->Timing.TaskCounters.TID[1])++; if ((rtM->Timing.TaskCounters.TID[1]) > 2) {/* Sample time: [3.0s, 0.0s] */ rtM->Timing.TaskCounters.TID[1] = 0; } }
/* Model step function */ void KeyboardScanModule_step(void) { int32_T uyIdx; int32_T currentOffset; int32_T nSampsAtBot; int32_T rtb_Add[9]; boolean_T rtb_RelationalOperator[9]; boolean_T rtb_TmpSignalConversionAtDelayI[9]; boolean_T rtb_Delay[9]; int32_T rtb_Switch[9]; uint8_T rtb_FixPtSum1; boolean_T rtb_Buffer2[3]; boolean_T rtb_Buffer1[3]; boolean_T rtb_Buffer[3]; int32_T i; int32_T rtb_Add_d; if (rtM->Timing.TaskCounters.TID[1] == 0) { for (i = 0; i < 9; i++) { /* Sum: '<S1>/Add' incorporates: * Constant: '<S1>/Constant3' * Delay: '<S1>/Delay1' */ rtb_Add_d = rtDW.Delay1_DSTATE[i] + 1;
/* RelationalOperator: '<S1>/Relational Operator' incorporates: * Constant: '<S1>/Constant2' */ rtb_RelationalOperator[i] = (10 > rtb_Add_d);
/* Delay: '<S1>/Delay' */ rtb_Delay[i] = rtDW.Delay_DSTATE[i];
/* Sum: '<S1>/Add' */ rtb_Add[i] = rtb_Add_d; } }
/* Buffer: '<S1>/Buffer2' incorporates: * Constant: '<S1>/Constant' * MultiPortSwitch: '<S1>/Multiport Switch' */ rtb_Add_d = 6; uyIdx = rtDW.Buffer2_inBufPtrIdx; if (6 - rtDW.Buffer2_inBufPtrIdx <= 1) { for (i = 0; i < 6 - rtDW.Buffer2_inBufPtrIdx; i++) { rtDW.Buffer2_CircBuf[rtDW.Buffer2_inBufPtrIdx + i] = false; }
uyIdx = 0; rtb_Add_d = rtDW.Buffer2_inBufPtrIdx; }
for (i = 0; i < rtb_Add_d - 5; i++) { rtDW.Buffer2_CircBuf[uyIdx + i] = false; }
rtDW.Buffer2_inBufPtrIdx++; if (rtDW.Buffer2_inBufPtrIdx >= 6) { rtDW.Buffer2_inBufPtrIdx -= 6; }
rtDW.Buffer2_bufferLength++; if (rtDW.Buffer2_bufferLength > 6) { rtDW.Buffer2_outBufPtrIdx = (rtDW.Buffer2_outBufPtrIdx + rtDW.Buffer2_bufferLength) - 6; if (rtDW.Buffer2_outBufPtrIdx > 6) { rtDW.Buffer2_outBufPtrIdx -= 6; }
rtDW.Buffer2_bufferLength = 6; }
if (rtM->Timing.TaskCounters.TID[1] == 0) { rtDW.Buffer2_bufferLength -= 3; if (rtDW.Buffer2_bufferLength < 0) { rtDW.Buffer2_outBufPtrIdx += rtDW.Buffer2_bufferLength; if (rtDW.Buffer2_outBufPtrIdx < 0) { rtDW.Buffer2_outBufPtrIdx += 6; }
rtDW.Buffer2_bufferLength = 0; }
uyIdx = 0; currentOffset = rtDW.Buffer2_outBufPtrIdx; if (rtDW.Buffer2_outBufPtrIdx < 0) { currentOffset = rtDW.Buffer2_outBufPtrIdx + 6; }
nSampsAtBot = 6 - currentOffset; rtb_Add_d = 3; if (6 - currentOffset <= 3) { for (i = 0; i < 6 - currentOffset; i++) { rtb_Buffer2[i] = rtDW.Buffer2_CircBuf[currentOffset + i]; }
uyIdx = 6 - currentOffset; currentOffset = 0; rtb_Add_d = 3 - nSampsAtBot; }
for (i = 0; i < rtb_Add_d; i++) { rtb_Buffer2[uyIdx + i] = rtDW.Buffer2_CircBuf[currentOffset + i]; }
rtDW.Buffer2_outBufPtrIdx = currentOffset + rtb_Add_d; }
/* End of Buffer: '<S1>/Buffer2' */
/* Buffer: '<S1>/Buffer1' incorporates: * Constant: '<S1>/Constant' * MultiPortSwitch: '<S1>/Multiport Switch2' */ rtb_Add_d = 6; uyIdx = rtDW.Buffer1_inBufPtrIdx; if (6 - rtDW.Buffer1_inBufPtrIdx <= 1) { for (i = 0; i < 6 - rtDW.Buffer1_inBufPtrIdx; i++) { rtDW.Buffer1_CircBuf[rtDW.Buffer1_inBufPtrIdx + i] = false; }
uyIdx = 0; rtb_Add_d = rtDW.Buffer1_inBufPtrIdx; }
for (i = 0; i < rtb_Add_d - 5; i++) { rtDW.Buffer1_CircBuf[uyIdx + i] = false; }
rtDW.Buffer1_inBufPtrIdx++; if (rtDW.Buffer1_inBufPtrIdx >= 6) { rtDW.Buffer1_inBufPtrIdx -= 6; }
rtDW.Buffer1_bufferLength++; if (rtDW.Buffer1_bufferLength > 6) { rtDW.Buffer1_outBufPtrIdx = (rtDW.Buffer1_outBufPtrIdx + rtDW.Buffer1_bufferLength) - 6; if (rtDW.Buffer1_outBufPtrIdx > 6) { rtDW.Buffer1_outBufPtrIdx -= 6; }
rtDW.Buffer1_bufferLength = 6; }
if (rtM->Timing.TaskCounters.TID[1] == 0) { rtDW.Buffer1_bufferLength -= 3; if (rtDW.Buffer1_bufferLength < 0) { rtDW.Buffer1_outBufPtrIdx += rtDW.Buffer1_bufferLength; if (rtDW.Buffer1_outBufPtrIdx < 0) { rtDW.Buffer1_outBufPtrIdx += 6; }
rtDW.Buffer1_bufferLength = 0; }
uyIdx = 0; currentOffset = rtDW.Buffer1_outBufPtrIdx; if (rtDW.Buffer1_outBufPtrIdx < 0) { currentOffset = rtDW.Buffer1_outBufPtrIdx + 6; }
nSampsAtBot = 6 - currentOffset; rtb_Add_d = 3; if (6 - currentOffset <= 3) { for (i = 0; i < 6 - currentOffset; i++) { rtb_Buffer1[i] = rtDW.Buffer1_CircBuf[currentOffset + i]; }
uyIdx = 6 - currentOffset; currentOffset = 0; rtb_Add_d = 3 - nSampsAtBot; }
for (i = 0; i < rtb_Add_d; i++) { rtb_Buffer1[uyIdx + i] = rtDW.Buffer1_CircBuf[currentOffset + i]; }
rtDW.Buffer1_outBufPtrIdx = currentOffset + rtb_Add_d; }
/* End of Buffer: '<S1>/Buffer1' */
/* Buffer: '<S1>/Buffer' incorporates: * Constant: '<S1>/Constant' * MultiPortSwitch: '<S1>/Multiport Switch3' */ rtb_Add_d = 6; uyIdx = rtDW.Buffer_inBufPtrIdx; if (6 - rtDW.Buffer_inBufPtrIdx <= 1) { for (i = 0; i < 6 - rtDW.Buffer_inBufPtrIdx; i++) { rtDW.Buffer_CircBuf[rtDW.Buffer_inBufPtrIdx + i] = false; }
uyIdx = 0; rtb_Add_d = rtDW.Buffer_inBufPtrIdx; }
for (i = 0; i < rtb_Add_d - 5; i++) { rtDW.Buffer_CircBuf[uyIdx + i] = false; }
rtDW.Buffer_inBufPtrIdx++; if (rtDW.Buffer_inBufPtrIdx >= 6) { rtDW.Buffer_inBufPtrIdx -= 6; }
rtDW.Buffer_bufferLength++; if (rtDW.Buffer_bufferLength > 6) { rtDW.Buffer_outBufPtrIdx = (rtDW.Buffer_outBufPtrIdx + rtDW.Buffer_bufferLength) - 6; if (rtDW.Buffer_outBufPtrIdx > 6) { rtDW.Buffer_outBufPtrIdx -= 6; }
rtDW.Buffer_bufferLength = 6; }
if (rtM->Timing.TaskCounters.TID[1] == 0) { rtDW.Buffer_bufferLength -= 3; if (rtDW.Buffer_bufferLength < 0) { rtDW.Buffer_outBufPtrIdx += rtDW.Buffer_bufferLength; if (rtDW.Buffer_outBufPtrIdx < 0) { rtDW.Buffer_outBufPtrIdx += 6; }
rtDW.Buffer_bufferLength = 0; }
uyIdx = 0; currentOffset = rtDW.Buffer_outBufPtrIdx; if (rtDW.Buffer_outBufPtrIdx < 0) { currentOffset = rtDW.Buffer_outBufPtrIdx + 6; }
nSampsAtBot = 6 - currentOffset; rtb_Add_d = 3; if (6 - currentOffset <= 3) { for (i = 0; i < 6 - currentOffset; i++) { rtb_Buffer[i] = rtDW.Buffer_CircBuf[currentOffset + i]; }
uyIdx = 6 - currentOffset; currentOffset = 0; rtb_Add_d = 3 - nSampsAtBot; }
for (i = 0; i < rtb_Add_d; i++) { rtb_Buffer[uyIdx + i] = rtDW.Buffer_CircBuf[currentOffset + i]; }
rtDW.Buffer_outBufPtrIdx = currentOffset + rtb_Add_d;
/* SignalConversion: '<S1>/TmpSignal ConversionAtDelayInport1' */ rtb_TmpSignalConversionAtDelayI[0] = rtb_Buffer2[0]; rtb_TmpSignalConversionAtDelayI[3] = rtb_Buffer1[0]; rtb_TmpSignalConversionAtDelayI[6] = rtb_Buffer[0]; rtb_TmpSignalConversionAtDelayI[1] = rtb_Buffer2[1]; rtb_TmpSignalConversionAtDelayI[4] = rtb_Buffer1[1]; rtb_TmpSignalConversionAtDelayI[7] = rtb_Buffer[1]; rtb_TmpSignalConversionAtDelayI[2] = rtb_Buffer2[2]; rtb_TmpSignalConversionAtDelayI[5] = rtb_Buffer1[2]; rtb_TmpSignalConversionAtDelayI[8] = rtb_Buffer[2]; for (i = 0; i < 9; i++) { /* Outport: '<Root>/PressFlags' incorporates: * Logic: '<S1>/Logical Operator2' */ rtY.PressFlags[i] = (rtb_RelationalOperator[i] && rtb_Delay[i]);
/* Outport: '<Root>/ReleasFlags' incorporates: * Logic: '<S1>/Logical Operator3' * Logic: '<S1>/Logical Operator4' */ rtY.ReleasFlags[i] = (rtb_RelationalOperator[i] && (!rtb_Delay[i]));
/* Switch: '<S1>/Switch' incorporates: * Constant: '<S1>/Constant4' * Logic: '<S1>/Logical Operator' */ if ((boolean_T)(rtb_Delay[i] ^ rtb_TmpSignalConversionAtDelayI[i])) { rtb_Switch[i] = rtb_Add[i]; } else { rtb_Switch[i] = 0; }
/* End of Switch: '<S1>/Switch' */ }
for (i = 0; i < 9; i++) { /* Update for Delay: '<S1>/Delay1' */ rtDW.Delay1_DSTATE[i] = rtb_Switch[i];
/* Update for Delay: '<S1>/Delay' */ rtDW.Delay_DSTATE[i] = rtb_TmpSignalConversionAtDelayI[i]; } }
/* End of Buffer: '<S1>/Buffer' */
/* Sum: '<S4>/FixPt Sum1' incorporates: * Constant: '<S4>/FixPt Constant' * UnitDelay: '<S3>/Output' */ rtb_FixPtSum1 = (uint8_T)(rtDW.Output_DSTATE + 1U);
/* Switch: '<S5>/FixPt Switch' */ if (rtb_FixPtSum1 > 2) { /* Update for UnitDelay: '<S3>/Output' incorporates: * Constant: '<S5>/Constant' */ rtDW.Output_DSTATE = 0U; } else { /* Update for UnitDelay: '<S3>/Output' */ rtDW.Output_DSTATE = rtb_FixPtSum1; }
/* End of Switch: '<S5>/FixPt Switch' */ rate_scheduler(); }
/* Model initialize function */ void KeyboardScanModule_initialize(void) { { int32_T i;
/* InitializeConditions for Delay: '<S1>/Delay1' */ for (i = 0; i < 9; i++) { rtDW.Delay1_DSTATE[i] = 1; }
/* End of InitializeConditions for Delay: '<S1>/Delay1' */
/* InitializeConditions for Buffer: '<S1>/Buffer2' */ rtDW.Buffer2_inBufPtrIdx = 3; rtDW.Buffer2_bufferLength = 3;
/* InitializeConditions for Buffer: '<S1>/Buffer1' */ rtDW.Buffer1_inBufPtrIdx = 3; rtDW.Buffer1_bufferLength = 3;
/* InitializeConditions for Buffer: '<S1>/Buffer' */ rtDW.Buffer_inBufPtrIdx = 3; rtDW.Buffer_bufferLength = 3; } }
/* * File trailer for generated code. * * [EOF] */
Тут важно то, что в алгоритме сколько кнопок столько и счетчиков для антидребезга. B такая генерация спасает от рутины громоздить огромное количество счетчиков и создания длинный битовых масок. Предупреждение. Файл имеет зависимости. Типы и функция main объявлены в других файлах.
|
|
|
|
|
Jun 23 2018, 14:13
|

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

|
Цитата(AlexandrY @ Jun 23 2018, 17:09)  Возьмем тон чуть конструктивней Другой разговор! Цитата "Героизм" - это про счетчик на каждую кнопку? Полагаю, что именно с этим вы и пытаетесь "бороться". Но в моем решении таймер всего один, да и тот используется в виде соотв. сервиса RTOS. Число кнопок, их принцип работы, размещение и т. п. никакого значения не имеют. Именно так выглядит модульное построение проекта - зависимости минимизированы и предельно абстрактны.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 14:22
|

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

|
Цитата(Forger @ Jun 23 2018, 17:13)  Другой разговор!
Полагаю, что именно с этим вы и пытаетесь "бороться".
Но в моем решении таймер всего один, да и тот используется в виде соотв. сервиса RTOS. Если RTOS нет, то нужен всего лишь один аппаратный таймер. Число кнопок, их принцип работы, размещение и т. п. никакого значения не имеют. Именно так выглядит модульное построение проекта - зависимости минимизированы и предельно абстрактны. Таймер то со счетчиком не путайте. Я прекрасно знаю как вы используете таймер. В вашем случае все так же надо хранить метки времени для каждой кнопки. И все также делать каскад сравнений. Метод ничего не упрощающий и не экономящий. Плюсы тут ни к селу ни к городу.
|
|
|
|
|
Jun 23 2018, 14:29
|

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

|
Цитата(AlexandrY @ Jun 23 2018, 17:22)  Таймер то со счетчиком не путайте. Я прекрасно знаю как вы используете таймер. Сильно сомневаюсь, что вы поняли мою реализацию. Однако, распишите, как вы это поняли? Цитата В вашем случае все так же надо хранить метки времени для каждой кнопки. Какие еще "временные метки"??? Перечитайте мой первый пост в этой теме. Ведь очень простое и очевидное решение. Я не сам его придумал, а как обычно - подсмотрел у более опытных комрадов. Цитата И все также делать каскад сравнений. Метод ничего не упрощающий. Да нут тут никаких "каскадов сравнений" (где вы берете такие архаичные термины? ) Есть один-два банальных цикла для сравнения двух "слепков" состояния кнопок - текущее и прежнее. В целом все очень компактно и просто. Именно так, как я описал в первых постах. Но конкретная реализация сильно зависит от программиста и его видения "проблемы". Цитата Плюсы тут ни к селу ни к городу. Да спрячьте вы уже свой "баян" или хотя бы разучите новые мотивы!
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 14:43
|

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

|
Цитата(Forger @ Jun 23 2018, 17:29)  Какие еще "временные метки"??? Перечитайте мой первый пост в этой теме. Ведь очень простое и очевидное решение. Я не сам его придумал, а как обычно - подсмотрел у более опытных комрадов. Че...? 50 мс? Да не смешите. Скажите это геймерам которые за миллисекунды трясутся на своей клавиатуре. Не, с такими упрощениями мне не интересно. Факт только в том, что я свой алгоритм сделал и выложил элементарно, а вы свой даже частями показать не можете. Он мне конечно не интересен, но мы же меряемся за принцип. Кста MATLAB может и на C++ сгенерить исходники, и под разные процессоры, и под RTOS и без RTOS. Т.е. показанная модель реально универсальна.
|
|
|
|
|
Jun 23 2018, 14:54
|

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

|
Цитата(AlexandrY @ Jun 23 2018, 17:43)  Че...? 50 мс? Да не смешите. Скажите это геймерам которые за миллисекунды трясутся на своей клавиатуре. Вы точно остались где-то в 90-х и пишите на паскале в DOSе. Для геймеров можно поставить 10мс, 1мс, 100мкс. Это - не проблема. Но мои проекты рассчитаны на обычных рядовых юзеров. А такой юзер не отличит реакции кнопки 50 мс от 100 мс. Можете сами убедиться. Цитата Не, с такими упрощениями мне не интересно. Ну, разумеется! Ведь ваш конек - создавать из воздуха проблемы и героически с ними бороться Цитата Факт только в том, что я свой алгоритм сделал и выложил элементарно, а вы свой даже частями показать не можете. Ваш код - практически нечитаем, крайне запутан и слишком сложен в реализации и необходимости применения сложных инструментариев (MATLAB) на ровном месте. Алгоритм, который я предложил, - прекрасно читаем (написан по-русски), просто и поэтому легко реализуем на любом языке практически любым программистом, Продолжать? Цитата но мы же меряемся за принцип.  Говорите лучше за себя. Цитата Кста MATLAB может и на C++ сгенерить исходники, и под разные процессоры, и под RTOS и без RTOS. Вы молодец - освоили MATLAB: теперь умеете "отрезать тонкие веточки" "промышленной бензопилой". Подравляю!
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 18:03
|

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

|
Цитата(iliusmaster @ Jun 23 2018, 20:17)  Обычно, чтобы ничего постояно не опрашивать, А в чем проблема периодического опроса, что его по-вашему следует избегать? Вот честно, не понимаю ) Обычно, чтобы избежать ненужной мгновенной реакции на очень медленное событие - реакция человека на различные действия, в т.ч. и действия его самого - делают как раз периодический опрос с такой частотой, с которой среднестатистический индивидуум никак не увидит разницы. А раз нет разницы, то зачем за это платить диким колхозом из нагромождений "временных меток", "каскадов сравнений" и подобной средневековой дикости?  Цитата все сигналы с кнопок через диоды собираются в одну точку и с этой точки в порт с прерыванием. По нажатию возникает прерывание - а уже в обработчике анлизируете матрицу. Ага, а вместе с таким сигналом прилетают множественные прерывания от дребезга. Чтобы его побороть, нужно делать задержки, ставить "аппаратные" фильтры, короче, открывать целые "институты" по решению копеешной проблемы.... очередная игра в "донкихота" По статистике реакция человека 100мс на визуальное событие - очень крутая реакция, доступная лишь очень крутым тренированным спортсменам. Цитата Вот тут можно время отклика до микросекунд уменьшить Почитайте название темы : "Опрос клавиатуры...", не управление ключами драйвера двигателя для соотв. формирования ШИМ, а опрос клавиатуры! Клавиатуру нажимает человек, а не робот. Именно из этой позиции и следует подходить к решению задачи с клавиатурой. Роботы еще не скоро займут место человека, но, если и займут, то клавиатура им точно не понадобится  Как-то в свое время ради интереса я собирал статистику: имеем задачу, которая занимается обработкой матричной клавиатуры 16х16, период - 50мс (дребезг в таких условия не грозит). Так вот нагрузка на CPU (мерял под RTOS) составляла сотые доли процента. Речь тогда была про "бытовые" кортексы STM32F103 на 72Мгц. Сокращая период до 25 мс, нагрузка на CPU соотв. удвоилась - но в итоге те же доли процента ... Поскольку события возникают лишь при изменении состояния клавиатуры, то в расчете на 10 событий в секунду (таких индивидуумов еще найти нужно) нагрузка возрастала до 0.1%. Вот и вся математика  Повторюсь - постоянный опрос клавиатуры 256 кнопок и 10 отпусканий/нажатий в секунду. Конкретный пример и конкретные цифры. Код простейший, построенный по алгоритму, как я описал во втором посте этой темы.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 19:56
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Ну развели... Проблема дребезга полностью освещена даже в Вики: https://ru.wikipedia.org/wiki/%D0%94%D1%80%...%82%D0%BE%D0%B2В частности программные методы борьбы: Цитата При программном формировании очищенного от дребезга контакта сигнала наибольшее распространение получили три из них:
1.Путём установки временной задержки — программа, обнаружив замкнутое состояния контакта, игнорирует его состояние на время, заведомо большее длительности дребезга, и спустя это время снова проверяет состояние контакта. Если после этого времени состояние контакта замкнутое, то соответствующая переменная меняет значение. 2.Методом подсчёта числа совпадающих значений сигнала замкнутости — программа многократно считывает состояние контакта, и, если последовало определённое количество подтверждений замкнутости в течение заданного промежутка времени (определяется экспериментально и выбирается в пределах от 10 до 100), контакт считается устойчиво замкнутым. 3.Методом подсчёта времени устойчивого состояния — программа в течение заданного времени многократно считывает состояние контакта. Если в течение заданного времени не обнаружено ни одного изменения состояния на противоположное, то контакт считается устойчиво замкнутым. В противном случае, если было обнаружено изменение состояния в течение заданного времени, то подсчёт времени прерывается (или продолжается, но с установкой флага или подсчётом количества изменений состояния для оценки физического состояния механических контактов) и контакт считается разомкнутым или с неустойчивым состоянием (если такая информация используется в программе). Время дребезга для контактов клавиатуры до нескольких миллисекунд (до 5). Forger по сути предложил метод №1 суть которого сравнить 2 измерения с временным промежутком времени завершения переходного процесса на контакте. Кстати, не обязательно постоянно опрашивать. Если есть необходимость глубоко дрыхнуть и просыпаться по сигналу нажатия, то никто не мешает в прерывании которое разбудило запустить таймер на те самые несколько мс в котором и принять решение чего это такого только что было... ЗЫ. На самом деле есть еще более тупой метод борьбы с дребезгом - RC-цепочка после контакта плюс триггер Шмитта который есть на входах многих современных контроллеров...
|
|
|
|
|
Jun 23 2018, 20:43
|

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

|
Цитата(ArtemKAD @ Jun 23 2018, 22:56)  Ну развели... Проблема дребезга полностью освещена даже в Вики В этой теме изначально о "проблеме" дребезге не было и речи, но прихожу к выводу, что "проблема" дребезга рождается в некоторых умах лишь при упоминании слова "клавиатура"  Цитата Если есть необходимость глубоко дрыхнуть и просыпаться по сигналу нажатия, В предложенном мной решении, для этого таймер периодического опроса клавиатуры можно временно перенастроить на период, скажем, в 1 сек. Этот таймер будет периодически будить проц. Для полного пробуждения достаточно удерживать "правильную" кнопку соотв. более 1 сек. Если же и это не годится, то кнопку пробуждения следует делать вообще отдельной от остальной части клавиатуры и заводить на соотв. пин проца.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 23 2018, 21:07
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (ArtemKAD @ Jun 23 2018, 22:56)  Forger по сути предложил метод №1 суть которого сравнить 2 измерения с временным промежутком времени завершения переходного процесса на контакте. Нет, у него другой метод, которым и я пользуюсь. Суть его в том, что от клавиатуры чисто электрически не может прийти ложный сигнал о нажатии (провода до кнопок короткие, подтяжки достаточно низкоомные). И если такой сигнал пришел - кнопку точно нажали. А проверять факт отпускания и/или повторного нажатия нужно не раньше, чем через время, заведомо большее времени дребезга, но меньшее времени возможного повторного нажатия. Если после нажатия считано разомкнутое состояние кнопки - значит ее или начали отпускать (попали в дребезг) или уже отпутили. Если в момент отпускания мы попали на дребезг и считали замкнутое сотояние кнопки - никакого криминала, в следующем цикле опроса считаем разомкнутое сотояние уже после окончания дребезга. Если кнопка дребезжит дольше 50 мс - ей место в помойке, поэтому 50 мс - вполне разумный компромисс между временем дребезга и временем реакции на изменение. А повторно нажать кнопку быстрее, чем через 100 мс не сможет даже неадекватный оператор (помешанных на играх опустим). QUOTE (ArtemKAD @ Jun 23 2018, 22:56)  ЗЫ. На самом деле есть еще более тупой метод борьбы с дребезгом - RC-цепочка после контакта плюс триггер Шмитта который есть на входах многих современных контроллеров... С натяжкой подходит для одиночных кнопок и не годится для матричных клавиатур.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 24 2018, 06:52
|

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

|
Цитата(ArtemKAD @ Jun 24 2018, 02:20)  Я б с таким подходом в автомобиле ноги бы точно протянул. Разве что провода действительно короткие. В автомобилях подтяжки ставят достаточно низкоомные. В одном из проектов для опроса такой кнопки мне пришлось ставить реально низкоомные резисторы, через которые при нажатии кнопки шел довольно немалый ток. Чтобы не спалить эти резисторы, питание на них подавалось кратковременно (около 1мс) и непосредственно перед опросом кнопок. Опрос - периодический (50мс). С "классической" постоянной подтяжкой (около 1мА) эти кнопки, которые находятся снаружи кабины камаза, через какое-то время эксплуатации переставали работать - постепенно окислялись контакты. Но относительно большой ток подтяжки (около 0,15 А), видать, "выжигал" тонкий слой окисла и кнопки работали как ни в чем не бывало. Глянул конкретные значения: 150 Ом (24В). А резисторы всего лишь в корпусе 1206. Но, если бы оставил постоянную подтяжку, то пришлось бы ставить 5..10 Вт резисторы. Один "минус" такой схемы - нужен доп. транзистор для программного управления подтяжкой.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 24 2018, 08:10
|

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

|
Цитата(ArtemKAD @ Jun 24 2018, 10:23)  Импульсную подтяжку еще и на кнопку - знаете вы толк в извращениях... Извращение как раз в противоположном - ставить 5 Вт резистор подтяжки для подобных кнопок. А если кнопок много, то ... К вашему сведению, я не придумал ничего нового - в данном случае также "традиционно" позаимствовал идею, обернув ее в свою обертку. Прочитайте мою подпись внизу каждого поста ...
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 24 2018, 08:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(iliusmaster @ Jun 23 2018, 20:17)  Обычно, чтобы ничего постояно не опрашивать, все сигналы с кнопок через диоды собираются в одну точку и с этой точки в порт с прерыванием. По нажатию возникает прерывание - а уже в обработчике анлизируете матрицу. . . . Постоянный опрос не есть "явное зло". Если он происходит раз в 10-20-50-100 мс (можно и больше) то это скорее благо. По предложенной Вами схеме на каждом дребезге контакта (если это обычный "сухой контакт" а не или матмодель или "через-триггер") на каждом нажатии-отжатии в течение интервала дребезга будет дергаться вектор прерывания (если, конечно, не прописать соотв-ие EI DI разрешения прерывания). Вопрос, так ли необходимо микросекундное "время отклика" системы при нажатии кнопки оператором ?Экономить на опросе нет смысла, тк он (для матрицы) сводится к двум коротким операциям - записи в порт маски опроса (столбцов) и чтения из него (рядов). чтения из него (рядов) и записи в порт маски опроса (столбцов). Это делается в векторе имеющегося таймера RTC или "тиков" RTOS. Если этот таймер очень "быстрый" - делается условный вход по софт-делителю с интервалом нескольких десятков мс. Дальнейшая обработка (по выставленному флагу интервала опроса клавиатуры и считанному скан-коду) выполняется вне вектора прерывания, с минимальным приоритетом. --- ps ООП имеет смысл применить для работы с очередью скан-кодов, полученных из драйвера клавиатуры.
|
|
|
|
|
Jun 24 2018, 09:38
|

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

|
Цитата(iliusmaster @ Jun 24 2018, 12:30)  а если клавиатура музыкального инструмента? Решили повторить копеечный китайский детский синтезатор, которые раздают на сдачу в супермаркетах? Ведь именно такой вы и описали В нормальных музыкальных электронных инструментах клавиатура - это не просто нажатие/отпускание, а еще как минимум контроль скорости нажатия. А в проф. инструментах еще и полная имитация "физики" клавиш настоящего механического рояля/пианины. Такие клавиатуры составляют основную стоимость самого инструмента. В эту область не пускают "простых смертных", коими мы практически все тут и являемся
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 24 2018, 11:11
|
Частый гость
 
Группа: Участник
Сообщений: 181
Регистрация: 15-04-17
Пользователь №: 96 556

|
Ну раз музыканты это специфика, то вот еще один пример. Есть у меня самодеятельный ЦАП с пультом управления. Пульт с многими кнопками, а питается для уменьшения габаритов от батареи типоразмера 2320. Так вот если мне каждые 100мс опрашивать кнопки, то батарейки придется часто менять. Можно даже придумать хитрый алгоритм, который будет увеличивать интервал между опросами, если длительное время отсутствует нажатие, но тогда я буду беситься от долгого времени отклика при первом нажатии. Диоды же, повешенные на прерывание, позволяют МК спать все время, пока не произошло нажатия. Время работы от батареи значительно вырастает.... Эти примеры я для чего привожу, что каждой задаче - свое решение. И вопрос как лучше опрашивать клавиатуру на Си, требует уточнения, какую клавиатуру и в каких условиях.
|
|
|
|
|
Jun 25 2018, 09:09
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Make_Pic @ Jun 25 2018, 05:06)  Тема ушла куда то "налево"  А хотелось просто увидеть код хорошего простого решения по клавиатуре... Нет, тема идет полностью так, как Вы ее задали в первом посте. Цитата Опрос клавиатуры на С -> Как написать компактный и "красивый" код? Вот Вам и рекомендуют не сам код, а как его писать "красиво", те выбрать правильный алгоритм. Как его перенести на код - это уже дело техники. т.е. Вы хотите увидить готовый код - драйвер клавиатуры ? Хотя это несколко противоречит цитате выше  (я свой драйвер матрицы 4x4 выложу, позднее). Вот реализация на С от Ti Low power keyb PDF SLAA773
|
|
|
|
|
Jun 25 2018, 10:35
|

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

|
Цитата(k155la3 @ Jun 25 2018, 12:09)  Вот реализация на С от Ti Тут надо сразу предупредить, что такая клавиатура надежно дает определить только одно нажатие. Если речь идет о клавиатуре скажем PC где надо обрабатывать несколько нажатий одновременно, то такая клавиатура не годится. Надо добавить диоды как минимум. А алгоритм соответственно не адаптирован к условиям сильных помех.
|
|
|
|
|
Jun 25 2018, 12:13
|

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

|
Цитата(Herz @ Jun 25 2018, 13:02)  А зачем в "рядовых" машинах подтяжка с кнопки педали тормоза? Под рядовыми я понимаю бюджетные ширпотребные авто не самых "бородатых" годов (скажем, до 10лет), где все же производится хотя бы какой-нить целостность стоп-ламп, тем более, если авто с коробкой-автомат. Но это уже офф. Цитата(AlexandrY @ Jun 25 2018, 13:35)  Тут надо сразу предупредить, что такая клавиатура надежно дает определить только одно нажатие. Если речь идет о клавиатуре скажем PC где надо обрабатывать несколько нажатий одновременно, то такая клавиатура не годится. Надо добавить диоды как минимум. Вы верны своей "традиции" - очередной "пук в лужу" Любая матричная клавиатура позволяет однозначно обрабатывать условия, когда даже ВСЕ кнопки нажаты и уж тем более в любом сочетании любого числа одновременно нажатых кнопок. Никакие диоды тут не нужны. Достаточно лишь ряда резисторов подтяжки на столбцы или строки.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 25 2018, 12:32
|

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

|
Цитата(AlexandrY @ Jun 25 2018, 15:24)  А над этим предлагаю вам подумать еще раз. Согласен, поторопился с выводами. Без диодов в таком случае не обойтись. Однако, в случае с клавиатурой, у которой сопротивление нажатых кнопок относительно большое (пленочные клавиатуры), это решаемо без диодов. Но усложняется алгоритм опроса - нужен импульсный (ШИМ) или даже аналоговый способ измерений. Судя по всему именно такой и применяется в клавиатурах ПК, для выявления подобных "коллизий".
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 26 2018, 05:30
|
Частый гость
 
Группа: Участник
Сообщений: 181
Регистрация: 15-04-17
Пользователь №: 96 556

|
Цитата(AlexandrY @ Jun 26 2018, 08:17)  Что за блажь использовать низкоомную подтяжку для механических контактов. Кто этот миф распускает, интересно? Т.е. интересует первоисточник. Например.http://omronfs.omron.com/en_US/ecb/products/pdf/en-b3sn.pdf. Советские ТУ на кнопочные переключатели. Есть такое понятие как минимальный ток срабатывания. У нормальных(грамотных) производителей на любое контактное соединение оно приводится. Контакты у реле, кнопок и контакторов не идеальные, образуется оксидная пленка, которая при малом токе не разрушается и контакта полноценного не образуется. Вот для нормального функционирования кнопок с незолотыми и палладиевыми контактамии нужен увеличенный ток через контактную группу. Да и для золотых и палладиевых есть проблемы при токах меньше 1-10 мка.
|
|
|
|
|
Jun 26 2018, 05:44
|

Знающий
   
Группа: Участник
Сообщений: 794
Регистрация: 4-09-06
Из: Москва(ЗелАО), РФ
Пользователь №: 20 055

|
Цитата(iliusmaster @ Jun 26 2018, 08:30)  Есть такое понятие как минимальный ток срабатывания. У нормальных(грамотных) производителей на любое контактное соединение оно приводится. Контакты у реле, кнопок и контакторов не идеальные, образуется оксидная пленка, которая при малом токе не разрушается и контакта полноценного не образуется. Вот для нормального функционирования кнопок с незолотыми и палладиевыми контактамии нужен увеличенный ток через контактную группу. Да и для золотых и палладиевых есть проблемы при токах меньше 1-10 мка. * Вообще-то оксидная пленка пробивается не током , а НАПРЯЖЕНИЕМ, минимальное значение которого и указывают для коммутационных устройств. Писанина про "минимальный ток" - бессмысленное словоблудие. Единственный физический эффект, который может создать сверхмалый ток -это дробовой шум, вызванный неравномерностью потока электронов и дискретностью их заряда. Но этот шум никак не влияет на наличие контакта.
Сообщение отредактировал =L.A.= - Jun 26 2018, 05:48
--------------------
-Кто-то работает на совесть, а кто-то на других заказчиков.-
|
|
|
|
|
Jun 26 2018, 06:32
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (=L.A.= @ Jun 26 2018, 13:44)  Писанина про "минимальный ток" - бессмысленное словоблудие. И тем не менее в документе на кнопку есть CODE Minimum applicable load (reference value) 10 μA at 1 VDC (resistive load) Видимо ток играет роль.
--------------------
Выбор.
|
|
|
|
|
Jun 26 2018, 06:52
|

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

|
Имхо, физика процесса тут не очень однозначная: разрушение тонкой пленки может происходить как от пробоя так и от ее выгорания (или и то и то). Разрушения этой пленки можно добиться лишь подняв до максимума напряжения на контакта нажатой кнопки с такими контактами. По сути в таком виде кнопка в нажатом состоянии имеет некое сопротивление, скажем, несколько кОм. Если резистор подтяжки будет сравним с сопротивлением нажатой кнопки с такими "окисленными" контактами, то схема попросту не "увидит" состояние кнопки. Чтобы уменьшить сопротивление такой нажатой кнопки, нужно "пробить/сжечь" эту пленку. Самый простой путь: значительно уменьшить сопротивление подтягивающего резистора - в разы меньше, чем сопротивление "окисленной" нажатой кнопки. Тогда на ней будет напряжение, близкое к напряжению питания. Вижу два варианта исхода: 1) кратковременный локальный разогрев этого паразитного сопротивления нажатой кнопки и оксидный слой выгорит от перегрева. 2) слой будет разрушен от пробоя более высоким напряжением. Я считаю, что в реальных схемах с относительно невысоким напряжением питания 1й вариант более вероятен. Цитата В любом случае образование тонких высокоомных слоев на поверхности контактов мощных реле неизбежно и требует учета при разработке и эксплуатации реле.
Пленки оксидов и сульфидов обладают свойствами изоляторов или даже полупроводников, но благодаря туннельному эффекту тонкие слои оказывают незначительное влияние на рост переходного сопротивления. При увеличении толщины слоя (например, при работе негерметичного реле на открытом воздухе) растет его сопротивление. Для создания надежного контакта непроводящий слой при срабатывании реле должен быть разрушен. В правильно спроектированных реле разрушение слоя происходит механическим путем (контакты ударяются и трутся друг о друга) и термоэлектрическим способом при протекании тока большой величины через контакты. Взято тут: https://www.atof.ru/pea/relay/rl_010.shtml
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 26 2018, 07:42
|

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

|
Цитата(iliusmaster @ Jun 26 2018, 08:30)  Например.http://omronfs.omron.com/en_US/ecb/products/pdf/en-b3sn.pdf. Советские ТУ на кнопочные переключатели. А подумать? "Minimum applicable load" в 10 мкА означает что при меньшем токе вы будете ловить токи утечки кнопки, поскольку у нее довольно маленькое сопротивление утечки, всего 100Мом. Т.е. при 250 В вы получите 2.5 мкА утечки. Вот ребята вас и предупреждают. Токи величиной в микроамперы гуляют по воздуху туда сюда просто из-за атмосферного электричества и электромагнитных полей. Я же под низкоомной нагрузкой полагал сопротивление максимум в пару десятков Ом. Вот где такие рекомендации? А загрязнение контактов реле отдельная тема. Если посмотреть на эти контакты под микроскопом, то видно что основная проблема у них - это эрозия и выгорание от коммутации больших токов. Грязь там появляется вследствии горения. Поэтому совет противоположный - никогда не коммутировать при низкоомной нагрузке.
|
|
|
|
|
Jun 26 2018, 07:49
|

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

|
Цитата(AlexandrY @ Jun 26 2018, 10:42)  Поэтому совет противоположный - никогда не коммутировать при низкоомной нагрузке. Видать, вы еще не сталкивались с подобными проблемами коммутации контактов относительно мощных концевиков/переключателей. Поэтому я пришел к выводу, что понятия большой и малый ток, нагрузка и т. п. весьма относительны. В любом случае источником информации является документация на тот или иной коммутационный элемент.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 26 2018, 08:41
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Make_Pic @ Jun 23 2018, 08:17)  . . . .Как написать компактный и "красивый" код? . . . Дайте pls примеры . . . . Вот пример моего кода (из первых версий), без претензий на красивость и компактность. Скорее наоборот. Претензии - на функциональность. (обработка в "событийном" режиме, очередь, скан-коды, обработка удержания). Без комментариев  Обрабатывать напильником до требуемой формы. CODE // MSP430, S_M_V // -------- keyb --------- #define S_PORT_KEYB_IN P6IN #define S_PORT_KEYB_OUT P6OUT // P6.0 . . . P6.3 - входные линии матрицы, подтянуты через 100к на GND // P6.4 . . . P6.7 - выходные линии матрицы (опрос линии установкой в 1)
static char key_wr = 0, key_rd = 0, keyCodeScan_old = 0; char keyCodeScan = 0, KeyCode = 0; char KeyCodeRep = 0; // запомнить код удерживаемой клавиши char f_repeat = 0; // флаг удержания нажатия
t16_sint time_repeat; // таймаут удержания клавиши, после которого работает автоповтор
// процедура сканирования клавиатуры (аппаратный опрос линий) // void OS::system_timer_user_hook() // Периодически вызывается в тиках OS или в обработчике таймера void KEY_Scan_R(void) { static char F_Press_now = 0, F_Press_old = 0, KKeyCode = 0; // ================== KEY =================================== SOUND_OFF;
keyCodeScan_old = keyCodeScan; // проверка изменения коорд. нажатия F_Press_old = F_Press_now; // контроль событий нажатия-отжатия
key_rd = S_PORT_KEYB_IN & 0x0F; // Read keyLines 0...3 (InData) from PORT keyCodeScan = (key_wr << 4) & 0xF0; // номер скан-линии 0 1 2 3 (row) keyCodeScan |= key_rd & 0x0F; // считанные столбцы (col)
if( keyCodeScan & 0x0F ) // нажата как минимум 1 клавиша { // нажата ли любая кнопка ? 0F маска - читаем из порта только "приемные" линии F_Press_now = 1; if( keyCodeScan != keyCodeScan_old ) // изменен скан-код ? { // первый вход по нажатию клавиши time_repeat = 0; // сбросить таймаут f_repeat = 0; } else // повторные входы по нажатой клавише { if( f_repeat == 0 ) // пока нет события "удержание", ++ таймера { if( time_repeat > 62 ) //4 // 62 цикла по 16 мс - около 1с { time_repeat = 0; // сбросить таймаут f_repeat = 1; } else time_repeat++; } }
} else // клавиша не нажата { F_Press_now = 0; // холостой проход - без нажатий }
// ---------- выдать скан-линию для следующего цикла -------- if( !F_Press_now ) // продолжаем сканировать линии - тк нет нажатия { // далее только если не нажата кнопка if( key_wr == 3 ) key_wr = 0; else key_wr++; // счетчик скан-линий ++ // ---------------------- if( key_wr == 3 ) S_PORT_KEYB_OUT = 0x80; // A B C D выбор столбца D0 D1 D2 D3 if( key_wr == 2 ) S_PORT_KEYB_OUT = 0x40; // 3 6 9 # if( key_wr == 1 ) S_PORT_KEYB_OUT = 0x20; // 2 5 8 0 if( key_wr == 0 ) S_PORT_KEYB_OUT = 0x10; // 1 4 7 * }
// заменить switch на перекодировку по ассоц.массиву // ------- скан для матрицы 4x4 --------------------- // перекодировка в KKeyCode - для PCB F5438A с подключением на мембр. кл-ру 4x4 // кабелем 9-w и HDR'10 на PCB switch( keyCodeScan ) { // key_wr == 0 1 4 7 * case (0x00 | 0x01): KKeyCode = 0x31; break; // 1 case (0x00 | 0x02): KKeyCode = 0x34; break; // 4 case (0x00 | 0x04): KKeyCode = 0x37; break; // 7 case (0x00 | 0x08): KKeyCode = 0x2E; break; // * ekeyPoint // ---------------- // key_wr == 1 2 5 8 0 case (0x10 | 0x01): KKeyCode = 0x32; break; // 2 case (0x10 | 0x02): KKeyCode = 0x35; break; // 5 case (0x10 | 0x04): KKeyCode = 0x38; break; // 8 case (0x10 | 0x08): KKeyCode = 0x30; break; // 0 // ---------------- // key_wr == 2 3 6 9 # case (0x20 | 0x01): KKeyCode = 0x33; break; // 3 case (0x20 | 0x02): KKeyCode = 0x36; break; // 6 case (0x20 | 0x04): KKeyCode = 0x39; break; // 9 case (0x20 | 0x08): KKeyCode = 0x04; break; // # ekeyEnter // ---------------- // key_wr == 3 A B C D case (0x30 | 0x01): KKeyCode = 0x01; break; // A F1 case (0x30 | 0x02): KKeyCode = 0x02; break; // B F2 case (0x30 | 0x04): KKeyCode = 0x03; break; // C F3 case (0x30 | 0x08): KKeyCode = 0x05; break; // D F4
default: KKeyCode = 0x00; break; // ekeyNO }
KeyCode = KKeyCode; // ================= /KEY ===================================
if( F_Press_old && !F_Press_now ) // KEY_OFF { // обработка отжатия time_repeat = 0; if ( f_repeat == 2 ) // если был режим "отпуск-удержания" (2) { KEY_push( (t16_sint) (KeyCodeRep | 0x4000) ); // (стоп удержания) маска 0x40 //KEY_pushBf( (t16_sint) ( 0x99 | 0x4000) ); f_repeat = 0;
} }
if( !F_Press_old && F_Press_now ) // KEY_ON { // обработка нажатия
SOUND_ON; KEY_push( (t16_sint) KKeyCode ); // тк буфер 16-битный }
if( F_Press_old && F_Press_now ) // KEY_ON_ON_ON { // обработка удержания
if( f_repeat == 1 ) { f_repeat = 2; // положить в буфер код "удержания", переключиться в след. цикле на // ожидание "отпуск-удержания" (режим 2)
KEY_push( (t16_sint) (KKeyCode | 0x8000) ); // (старт удержания) маска 0x80 // --------- системный ресет -------------------- if( KKeyCode == 0x31 ) // Reset на удержание клавиши <1> { SLEEP(100); WDTCTL = WDTPW | WDTHOLD; asm ("push &0xfffe"); asm ("ret"); } // -------- /системный ресет -------------------- KeyCodeRep = KeyCode; // сохранить для выдачи кода отжатия } }
}// KEY_Scan(void)
|
|
|
|
|
Jun 27 2018, 04:35
|

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

|
Цитата(haker_fox @ Jun 27 2018, 05:32)  Ну это зависит от цены проекта и стоимости часа разработчика  Спорно. С этой чудо-микросхемой плата выйдет сложнее и само собой дороже. Код - тоже спорно: с чудо-микросхемой нужно читать-писать соотв. регистры по I2C, т.е. писать по сути для нее драйвер. Без нее - простой цикл опроса матричной клавиатуры (см. второй пост этой темы). Короче, из пушки по воробьям Имхо, вижу единственное разумное применение такой "микрульки" - батарейное питание: проц. всегда спит и просыпается по прерыванию от этой микросхемы, которая в режиме ожидания потребляет около 1мкА. Но это решаемо и без нее: перед входом в сон "тянем" вниз все линии клавиатуры (скажем, строки), и ждем прерывания по любому из столбцов. Т.е. ждем нажатия любой кнопки. После просыпания делает все по обычной схеме, определяя какая именно кнопка нажата.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 27 2018, 05:08
|

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

|
Цитата(Jenya7 @ Jun 26 2018, 17:35)  В последних проектах юзаем ADP5589. Изначально я был против. Теперь - категорически рекомендую.Опрос клавиатуры на С получается красивый и лаконичный. Я выбрал AS1115-BSST Дополнительно поддерживает еще и семисегментный дисплей. Тема неплохо экономит ресурсы. Когда управляешь двигателями и кучкой SMPS-ов одновременно то реально не хватает ног да и лишние прерывания ни к чему.
|
|
|
|
|
Jun 27 2018, 06:36
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Forger @ Jun 26 2018, 18:24)  Код в студию! . . . чип полезный в хозяйстве, но малодоставабельный, по крайней мере у нас. Разве что для фирмы брать партией. Решение с таким чипом полезно, когда "морда" прибора имеет клавиатуру и дисплей на отдельной PCB. Если у обоих - I2C (например LCD TIC32) то получится очень неплохо. Хотя сейчас пошли в работу емкостные матрицы как на спец. контроллерах, так и на базе обычных контроллеров или с узлом периферии touch-sense (см. Texas instr. MSP430 и тд)
|
|
|
|
|
Jun 27 2018, 07:22
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Forger @ Jun 27 2018, 12:35)  Спорно. Ну так я и написал: QUOTE (haker_fox @ Jun 27 2018, 10:32)  Ну это зависит от цены проекта и стоимости часа разработчика  QUOTE (Forger @ Jun 27 2018, 12:35)  С этой чудо-микросхемой плата выйдет сложнее и само собой дороже. Почему она будет сложнее? Таже матрица, ну добавиться пара конденсаторов на питание этой микросхемы, и резистор на подтяжку прерывания. На счёт "дороже". Время конторы тоже денег стоит. И оно может оказаться значительно дороже одной микросхемы. QUOTE (Forger @ Jun 27 2018, 12:35)  Код - тоже спорно: с чудо-микросхемой нужно читать-писать соотв. регистры по I2C, т.е. писать по сути для нее драйвер. Ну писать всё-равно что-то придётся) QUOTE (Forger @ Jun 27 2018, 12:35)  Короче, из пушки по воробьям  Ага, AD просто так пушку делает))) Кто-то же покупает. В одном из приборов мы сделали клавиатуру на отдельной плате, и поставили на неё копеечный кортекс-а0 в корпусе tqfp32. Связывается с основной платой последовательным интерфейсом. Это было дешевле, и проще, чем тащить широкий шлейф. На этом же кортексе опрашивается резистивный тач-скрин. Без микросхем на подобии tsc2007. При этом на основном МК были высвобождены ценные GPIO, и ещё остались в резерве. Я понимаю, что может быть "проще" было заказать другой МК, в другом корпусе. Но когда для основного всё есть, включая печатную плату, вопрос "дороже" или "дешевле" очень не однозначен. Иногда, например, дешевле и проще поставить 10 резисторов по 1 кОм последовательно, чем 1 по 10 кОм.
--------------------
Выбор.
|
|
|
|
|
Jun 28 2018, 15:55
|
Частый гость
 
Группа: Участник
Сообщений: 181
Регистрация: 15-04-17
Пользователь №: 96 556

|
Цитата(AlexandrY @ Jun 26 2018, 10:42)  А подумать? "Minimum applicable load" в 10 мкА означает что при меньшем токе вы будете ловить токи утечки кнопки, поскольку у нее довольно маленькое сопротивление утечки, всего 100Мом. Т.е. при 250 В вы получите 2.5 мкА утечки. Вот ребята вас и предупреждают.
Токи величиной в микроамперы гуляют по воздуху туда сюда просто из-за атмосферного электричества и электромагнитных полей.
Я же под низкоомной нагрузкой полагал сопротивление максимум в пару десятков Ом. Вот где такие рекомендации?
А загрязнение контактов реле отдельная тема. Если посмотреть на эти контакты под микроскопом, то видно что основная проблема у них - это эрозия и выгорание от коммутации больших токов. Грязь там появляется вследствии горения.
Поэтому совет противоположный - никогда не коммутировать при низкоомной нагрузке. Какой воздух? Какие прогулки тока? Такая уверенность в своей правоте иногда умиляет. Прочитайте классические книги о конструировании контактных групп и узнаете, что такое минимальный коммутируемый ток. Слой окисла на контактах перед замыканием может образоваться и без выгорания, простая химия. Удаляет защитную пленку не НАПРЯЖЕНИЕ, а ТОК! Именно протекание тока и выделяемое при этом тепло в зоне контакта приводит к тепловому разрушению оксидной пленки! Напряжение же нужно только чтобы создать достаточный ток.
|
|
|
|
|
Jun 28 2018, 16:04
|

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

|
Цитата(iliusmaster) Цитата(rx3apf) Вот: https://electronix.ru/forum/index.php?showt...p;#entry1568887Там же есть ссылка на "литературу".
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 28 2018, 19:40
|

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

|
Цитата(iliusmaster @ Jun 28 2018, 18:55)  Удаляет защитную пленку не НАПРЯЖЕНИЕ, а ТОК! Именно протекание тока и выделяемое при этом тепло в зоне контакта приводит к тепловому разрушению оксидной пленки! Напряжение же нужно только чтобы создать достаточный ток. Где ссылки вот с такой вот версией ? От производителей современной компонентной базы. Чтоб прямо так говорили про какой-то там пробой оксидации и проч. муть. Открываю список мер предосторожности на реле Omron (делаю одолжение и обсуждаю реле, хотя тема реле подброшена сюда тем кому уже нечего сказать про кнопки) Никакой рекомендации пробивать оксидацию током или напряжением не видим. Но за то видим такой график надежности реле
Т.е. чем больше ток тем ресурс у реле меньше. Просто производитель на 1 мА гарантирует сопротивление контактов в неких пределах через миллион циклов. И даже при таком токе видна деградация сопротивления контактов
Ну так чё, будем продолжать пробивать контакты током?
|
|
|
|
|
Jun 28 2018, 20:27
|

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

|
Цитата(Herz @ Jun 28 2018, 22:49)  Коллега, ничего смешного не вижу. Или Вы намеренно прикалываетесь? https://en.wikipedia.org/wiki/Wetting_currentС каких пор википедия стала производителем реле? Может перекинем спор на германиевые транзисторы и эффекты в них. Так мы располземся по всей истории. А если бы не ленились и почитали бы по списку публикаций в конце статьи википедии по вашей ссылке, то узнали бы что речь идет о непрекращающемся! токе через контакты в течении всего времени когда они замкнуты. И эффект заключается не в некоем пробое, а в электромиграции, когда вместе с током переносится материал. Это и не дает захватить пленке контакты. Но электромиграция эта та же деградация. Так что палка о двух концах. Факт в том что Omron не дает никаких рекомендаций по пробою, а советует для микротоков просто взять реле в двойными контактами. И не оставлять на месяцы контакты без движения. Цитата(rx3apf @ Jun 28 2018, 23:11)  Хотите про кнопки - извольте. http://www.ia.omron.com/products/family/28...cification.html, картинка с "micro load area". Вообще-то все это общеизвестно с незапамятных времен, и физика с тех пор не изменилась. То же самое - электромиграция для долгое время замкнутых контактов.
|
|
|
|
|
Jun 29 2018, 05:08
|

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

|
Цитата(AlexandrY @ Jun 29 2018, 07:36)  У юридических консультантов ... у врачей-проктологов Ну, тут вам виднее  В этих областях я профан, моё - схемотехника/программирование ... Цитата Вы еще у врачей-проктологов проконсультируетесь по поводу реле. И не стоит так утруждаться с "полезными" советами, ваша позиция тут уже давно всем хорошо ясна: "существуют только два мнения - ваше и неправильное".
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 29 2018, 05:50
|

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

|
Цитата(AlexandrY @ Jun 29 2018, 08:39)  Ищите надежные пруфы и я с удовольствием изменю свое мнение.  По-ходу, у вас несколько завышенное самомнение  Эта тема посвящена не вам. Ссылки были не для вас, а для всех. Цель их, не кого-то конкретного убедить в чем-то, а в том, чтобы поделиться опытом и знаниями с другими участниками форума. По-моему, это - одно из основных назначений этого форума. Кстати, насчет ссылок: от вас так и не последовало ни одной, одни лишь "голые" утверждения, неизвестно на чем основанные, в стиле: Цитата(AlexandrY) Что за блажь использовать низкоомную подтяжку для механических контактов. Цитата(AlexandrY) Поэтому совет противоположный - никогда не коммутировать при низкоомной нагрузке.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 29 2018, 06:40
|

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

|
Цитата(Forger @ Jun 29 2018, 08:50)  По-ходу, у вас несколько завышенное самомнение  Эта тема посвящена не вам. Ссылки были не для вас, а для всех. Цель их, не кого-то конкретного убедить в чем-то, а в том, чтобы поделиться опытом и знаниями с другими участниками форума. По-моему, это - одно из основных назначений этого форума. Кстати, насчет ссылок: от вас так и не последовало ни одной, одни лишь "голые" утверждения, неизвестно на чем основанные, в стиле: Эй полегче, еще поделитесь опытом что земля плоская. От вас не опыт, а одни пузыри. Еще раз - где надежные пруфы, да хотя бы пруфы вашего опыта. И не превращаете ветку в выяснение отношений.
|
|
|
|
|
Jun 29 2018, 06:51
|

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

|
Цитата(AlexandrY @ Jun 29 2018, 09:40)  От вас не опыт, а одни пузыри. Перечитайте обязанности модератора еще раз. Там не указано: принимать решения у кого "опыт", а у кого "пузыри". Цитата Еще раз - где надежные пруфы, да хотя бы пруфы вашего опыта. Пруфы моего опыта, это - мои слова. Если вас это не устраивает - игнорируйте, проходите мимо. Это не сложно. Впрочем, я уже писал об этом. Цитата И не превращаете ветку в выяснение отношений. Аналогично: https://electronix.ru/forum/index.php?s=&am...t&p=1569752
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 29 2018, 06:56
|

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

|
Цитата(Forger @ Jun 29 2018, 09:51)  Пруфы моего опыта, это - мои слова. Если вас это не устраивает - игнорируйте, проходите мимо. Это не сложно. Впрочем, я уже писал об этом. Также вам предлагаю помолчать относительно меня и моего опыта. Модераторы обсуждаются в отдельной ветке. Форум для того и создан чтобы разбивать в хлам ничем не обоснованные утверждения. Ярлык "опыт" присвоенный им самими же авторами ни от чего их не защищает.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|