Перейти к содержанию

Язык СИ для микроконтроллеров


Рекомендуемые сообщения

9 часов назад, ARV сказал:

Корректно написанный код будет работать всегда так, как написано.

В теории да, но на практике в Си слишком много Undefined Behaviour. В ряде случаев приходится полагаться на конкретные реализации.

Цитата

Одно из таких же неписанных правил приличия для программиста звучит так: если функция не умещается целиком на одном экране - это плохо написанная функция.

 

Отчего ж неписаных. Во всей литературе по стилям кодирования. Очень рекомендую почитать Макконнела "совершенный код", где вопросы форматирования рассмотрены весьма подробно.

Цитата

Ну а если так? Мне кажется весьма удобно после IF  сделать обе кавычки , чтоб сразу видеть , что он выполнит по выполнению условия.
if(...){...}

Для коротких выражений такое применять можно, но только без else, потому что иначе теряется иерархия. Исключение - конструкции вроде

if(strcmp(cmd, "CMD1")==0){...}
  else if(strcmp(cmd, "CMD2")==0){...}
  else if(strcmp(cmd, "CMD3")==0){...}
Цитата

И ещё актуальный вопрос. Есть оператор * умножения и  указатель типа  *temp   к примеру. Как здесь не путаться где умножение а где указатель?

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

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Вставлю свои 5 копеек. Я использую goto в одном случае, когда к примеру нужно что то распарсить, если натыкаюсь на неверное значение или символ, смысла парсить дальше нет, строка битая.Тогда по goto можно перейти в конец функции и вернуть к примеру false, всё это строго в пределе одной маленькой функции. Можно заменить это дело do{...}while(0); если что то не так, то делать break из цикла. Но тогда после завершения цикла не ясно, вылетел он по брейку или выполнился до конца, нужен какой то флаг, а с goto не нужен. В java для этого дела есть система исключений ну и конструкции  try{...}catch(){...}. 

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

3 часа назад, SDD39 сказал:

Т е иногда это может выглядеть так  a**temp

Лично я действую по принципу "скобок много не бывает" :) ща меня закидают тапками "профессионалы", но любителям я рекомендую расставлять скобки всегда, когда от этого вам понятнее. Особенно в "многоэтажных" выражениях. Плевать, что умножение и деление имеют приоритет выше, чем сложение и вычитание - ставьте скобки, и будет вам счастье.

 

1 час назад, COKPOWEHEU сказал:

на практике в Си слишком много Undefined Behaviour

Практически всегда можно написать так, чтобы избегать этого. Нет, конечно, лёгкие пути не для всех подряд, но всё же - можно избегать...

38 минут назад, GOR23 сказал:

Я использую goto в одном случае,

На самом деле требование избегать goto - это далеко не безусловно полезное требование. Чаще всего - да, полезное, но немало случаев, когда вредное или даже противоречивое. Например, MISRA требует, чтобы из любой функции возврат результата осуществлялся из единственной точки выхода. Т.е., например, switch с разными return в разных case будет нарушением требования. Ну представьте себе, как быть, если в этом switch у вас куча циклов, да и сам switch внутри пары вложенных циклов - как без goto сделать нормальный выход "по ошибке"? 

Чисто теоретически можно что-то придумать, но лично я такого напряжения мозга не всегда выдерживаю. В общем, про goto надо так: стараться, но не перенапрягаться. Пара goto на проект из десятка файлов - не страшно :)

1 час назад, COKPOWEHEU сказал:

Для коротких выражений такое применять можно, но только без else, потому что иначе теряется иерархия. Исключение - конструкции вроде

Все-таки очень часто приходится при "улучшении" что-то добавлять или удалять, поэтому в одну строку записывать if без else даже с фигурными скобками не желательно... А вот ваше исключение - поддержу. Только я всегда делаю один уровень у первого if и последующих else if - так зрительно они выглядят как один очень длинный многоальтернативный if - типа switch без break-ов :) 

Кстати, последнее время увлекся расширением GCC к стандарту C99, которое позволяет работать с диапазонами значений в switch - порой получается красивее, чем многоэтажный if...

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

44 минуты назад, ARV сказал:

Все-таки очень часто приходится при "улучшении" что-то добавлять или удалять

Если выражение перестает помещаться на одном экране по горизонтали, его придется разделить на несколько строк с нормальным форматированием. А вот если там что-то вроде

if( !file_out ){printf("Some error\n"); return -1;}
49 минут назад, ARV сказал:

Практически всегда можно написать так, чтобы избегать этого.

UB в Си может быть все что угодно: переполнение переменной, сдвиги, выделение памяти на стеке, сами размеры переменных. От всего не застрахуешься.

 

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

18 минут назад, COKPOWEHEU сказал:

От всего не застрахуешься

Я не такой пессимист :)

По поводу стека - мимо кассы, т.к. Си тут ни при чем, если ОЗУ мало.

Сдвиги - поведение определено стандартом, даже не знаю, что там может быть неопределено... может, мало знаю.

Переполнение переменной легко обходится при программировании, на что ж иначе голова программисту?! Плюс контроль значений, если остро стоит вопрос надежности ПО.

Размеры переменных - stdint в помощь и стандарт С99.

В общем, моё мнение: было бы желание написать качественный код :) - все можно.

18 минут назад, COKPOWEHEU сказал:

Если выражение

Да я не настаиваю. Я поделился своим представлением о красивом и удобном форматировании... Я считаю смешение подходов (многострочные блоки с однострочными) не красивым, стремлюсь делать все однообразно. А после того, как почитал MISRA, так от безблочных if-ов, for-ов и тому подобных while-ов теперь тоже откажусь - для порядку :)

Может, после смерти в рай перфекционистов пустят...

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

13 часа назад, wws63 сказал:

Как убрать goto, чтобы все так же было понятно

Вот это :

		CYCLE:
		if(bitisset (PINB, CANNAL_1)) 
		  {
		  sec_3 = 0; 
		  goto m_0;
		  }
		else 
		    {
			 _delay_ms(20);
			 sec_3++;
             cli ();
            } 
		 if (sec_3 ==19)
		   {
		     sec_3 = 0;
			 goto   m_3;
		   }  
		  	                  
		 else goto CYCLE;
m_3:  

у Вас обычный счётчик до 19-ти, с выходом из него по PINB, CANNAL_1 , который можно написать так :

do{


}while(sec_3<19);
sec_3 = 0;

Далее. Вот этот else :

		else 
		    {
			 _delay_ms(20);
			 sec_3++;
             cli ();
            } 

бессмыселен. Ибо этот блок в любом случае будет выполняться, если не выполнится блок if, находящийся выше. По этому, инкремент можно засунуть сразу в условие, а задержку с cli (кстати, а зачем он там ? ) в сам цикл :

do{
    _delay_ms(20);
    cli ();
}while(++sec_3<19);
sec_3 = 0;

Остаётся только сделать выход из цикла по PINB, CANNAL_1, с пропуском дальнейших действий с eeprom.
Можно сделать так :

do{
    _delay_ms(20);
    cli ();
}while((++sec_3<19) && !(bitisset (PINB, CANNAL_1)));
sec_3 = 0;

if(!bitisset (PINB, CANNAL_1)){
    Value_ee = eeprom_read_byte(&data_0); // считываем байт из EEPROM и помещаем его в "Value_ee"
    ...............
    ...............
}

Или так :

do{
    if(bitisset (PINB, CANNAL_1))   break;
    _delay_ms(20);
    cli ();
}while(++sec_3<19);
sec_3 = 0;

if(!bitisset (PINB, CANNAL_1)){
    Value_ee = eeprom_read_byte(&data_0); // считываем байт из EEPROM и помещаем его в "Value_ee"
    ...............
    ...............
}

Либо выход с установкой флага, если не уверены, что уровень на входе будет неизменным в течении некоторых тактов.

А можно, вообще, вот так написать :

sec_3 = 20;
do{
    if(bitisset (PINB, CANNAL_1))   break;
    _delay_ms(20);
    cli ();
}while(--sec_3);

if(sec_3){      // Если прошла секунда, а не выход по "PINB, CANNAL_1"
    Value_ee = eeprom_read_byte(&data_0); // считываем байт из EEPROM и помещаем его в "Value_ee"
    ...............
    ...............
}

Или через for сделать.


PS: Вот и весь Ваш код, без всяких goto и огромных простыней :)

Ссылка на комментарий
Поделиться на другие сайты

Нет, алгоритм немного другой.

В первом  блоке

		CYCLE:
		if(bitisset (PINB, CANNAL_1)) 
		  {
		  sec_3 = 0; 
		  goto m_0;
		  }
		else 
		    {
			 _delay_ms(20);
			 sec_3++;
             cli ();
            } 
		 if (sec_3 ==19)
		   {
		     sec_3 = 0;
			 goto   m_3;
		   }  
		  	                  
		 else goto CYCLE;
m_3:  

Мы опрашиваем состояние кнопки CANNAL_1, если она не нажата, сбрасываем счетчик 3 секунд,  и уходим на метку m_0, там будем опрашивать другую кнопку.

Если CANNAL_1 нажата, через каждые (20*8) мс опрашиваем её заново, запрещаем прерывание (у нас оно запущено в начале программы)и так в течении 3 секунд, (если конечно она нажата). Итак, если  CANNAL_1  нажата более 3 секунд, идем на метку m_3 ( считывание значения ячейки ЕЕПРОМ и т.д.)

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

ALEX, спасибо,  с вашими примерами сейчас буду разбираться. 

 

Изменено пользователем wws63

Опыт - это то, что получаешь, не получив того, что хотел

Ссылка на комментарий
Поделиться на другие сайты

Только что, wws63 сказал:

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

Это не надо делать. Не стоит перекладывать ассемблерный подход на методику программирования на Си. Смысл функции в том, чтобы она всегда отрабатывала свои задачи и всегда возвращала управление туда, откуда была вызвана. Если этот смысл искажать, то и смысл функции пропадает.

Вы читали мою статью?

У вас, например, работа с кнопками размазана по меткам. Это не хороший подход. Вы должны сформулировать решение своей задачи так, чтобы каждый элемент программы представлял собой логически и функционально самостоятельный блок. То есть опрос ВСЕХ кнопок в одной функции в одном месте. Эта функция возвращает код нажатой кнопки, а далее при помощи if-else или switch вы отрабатываете реакцию на каждую кнопку. Если у вас длительность нажатой кнопки влияет на реакцию, следовательно, должно быть два варианта обработки - для короткого и для длительного. И так далее. Тогда ваша программа будет выглядеть как-то так

while(1){ // главный цикл
  do_every_time(); // функция, которая делает то, что делается всегда и в любом случае, например, обновляет дисплей
  button = get_button_pressed(); // функция, которая возвращает код нажатой кнопки
  switch(button){ // обработка нажатых кнопок
    case BNT_1: // нажата кнопка 1
      execute_btn_1(); // функция реакции на кнопку 1
      break;
    case BTN_2: // нажата кнопка 2
	  execute-btn_2(); // функция реакции на кнопку 2
      break;
    case BTN_3:
      // а вот кнопка 3 может досрочно прекратить дальнейшую работу и начать главный цикл заново
      if(execute_btn_3() == ERROR){
        continue; // досрочное начало цикла
      }
      break;
      // далее аналогично все кнопки
      ...
    default:
      // что-то делаем, когда ни одна кнопка не нажата
      execute_no_pressed_button();
  }// конец обработк кнопок
  // делаем что-то еще, если надо, например, ждем отпускания кнопки или истечение заданного в какой-то функции ранее таймера
  while(get_button_pressed() != 0){ // пока нажата любая кнопка
    if(timer_out()) // проверяем таймер 
      break; // и выходим из цикла ожидания, если он истек
  }
} // конец главного цикла
      

Как видите, все абсолютно логично, структурировано и понятно. Все "непонятные" функции имеют самоговорящее (я для примера все именовал по шаблону "делаем_что_то, но на самом деле называть их надо осмысленно, например, blink_led - мигнуть светодиодом, calculate_power - вычислить мощность и т.д.) название и решают свои задачи "где-то там". Чтобы понять общий алгоритм программы не требуется даже структурного алгоритма - по основному циклу все ясно.

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

И не надо "в другом месте опрашивать другую кнопку"...

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

11 час назад, ARV сказал:

По поводу стека - мимо кассы, т.к. Си тут ни при чем, если ОЗУ мало.

Сдвиги - поведение определено стандартом, даже не знаю, что там может быть неопределено... может, мало знаю.

Переполнение переменной легко обходится при программировании, на что ж иначе голова программисту?! Плюс контроль значений, если остро стоит вопрос надежности ПО.

По поводу стека Си не позволяет это отследить.

На счет сдвигов, вроде как сдвиг знаковых чисел вправо не определен, и сдвиг (uint8_t<<9) тоже.

Переполнение переменной вы всегда контролируете вручную? Или все-таки полагаетесь на то что при переполнении счетчика он обнулится.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Только что, COKPOWEHEU сказал:

По поводу стека Си не позволяет это отследить.

И что из этого следует? Корыто тоже океан не переплывет. Не подходит молоток для закручивания шурупов? Так надо брать отвертку, а не ругать молоток.

Только что, COKPOWEHEU сказал:

На счет сдвигов, вроде как сдвиг знаковых чисел вправо не определен, и сдвиг (uint8_t<<9) тоже.

Ну вот не знаю. Как-то необходимости разбираться не было, но можно заглянуть в стандарт... Правда их теперь тоже развелось... Попробую в С99 поискать, хотя очень лень. Проще думать, прежде чем двигать. Мы же знаем, что сдвиг закового числа может быть с непредсказуемым результатом? Что может нас заставить двигать его, нарываясь на это? Можно применить деление, если уж знак важен - поведение однозначно определено. Говорю же: всегда можно избежать, если знаешь, какая опасность тебя поджидает.

Только что, COKPOWEHEU сказал:

Переполнение переменной вы всегда контролируете вручную? Или все-таки полагаетесь на то что при переполнении счетчика он обнулится

Когда знаю, что обнулится - полагаюсь. Когда надо быть уверенным, что не обнулится - контролирую. Когда наплевать - ничего не делаю. Главное - последствия от переполнения переменной, если они для меня недопустимы - необходимо контролировать. А что не так?

Я могу попасть впросак по причине незнания стандарта - я лишь верхушек из него нахватался. Но что может заставить специалиста, знающего стандарт от и до наступить на грабли неопределенного поведения компилятора?! Стандарт же об этом предупреждает, не умалчивает.

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

Только что, SDD39 сказал:

что в SWITCH  можно применять только BREAK , а CONTINUE  в  нём не применяется???

break приводит к выходу их текущего блока {}. Поэтому и в любом цикле, и в любом switch break работает одинаково - выбрасывает за закрывающую фигурную скобку. 

continue однозначно обозначает "продолжение работы цикла", и ничего более - что он может делать в switch?! это же оператор "однократного прохода", а не многократного.

Поэтому continue не применим нигде, кроме циклов. Компилятор просто не даст вам это сделать

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

12 минуты назад, ARV сказал:

Можно применить деление, если уж знак важен - поведение однозначно определено.

Мы же на микроконтроллерном форуме. Тут важны скорость и размер а не переносимость.

14 минуты назад, ARV сказал:

Когда знаю, что обнулится - полагаюсь.

Например, какие-нибудь счетчики секунд с начала работы устройства. Неужели будете отслеживать переполнение?

16 минут назад, ARV сказал:

Но что может заставить специалиста, знающего стандарт от и до наступить на грабли неопределенного поведения компилятора?!

Да все что угодно! Нарушение стандарта конкретным компилятором. Оптимизация. Недостаточное знание стандарта. Спешка. Лень. Желание выпендриться. Желание сделать код неработоспособным на других компиляторах

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Только что, COKPOWEHEU сказал:

Да все что угодно! Нарушение стандарта конкретным компилятором. Оптимизация. Недостаточное знание стандарта. Спешка. Лень. Желание выпендриться. Желание сделать код неработоспособным на других компиляторах

Вы еще не забыли, о чем вообще речь-то идет? О том, что соблюдение стандарта навредить никак не может, и программа, написанная в строгом соответствии со стандартом, будет работоспособна всегда. Что вы тут перечислили? Что это доказывает? Что можно сделать кривую программу по разным причинам? Так никто и не спорит.

Компилятор, который криво реализует стандарт и не оговаривает это в документации, - это программа с багом. Само собой, ориентироваться на баг - это глупость. Мы всегда рассчитываем на то, что либо багов нет, либо они все документированы.

Только что, SDD39 сказал:

Получается что в кейсах всё же можно применять CONTINUE  для  цикла в который 

вложен SWITCH ?

Вы должны понимать, что continue, где бы он не обнаружился, найдет самый ближний к нему цикл и начнет с его начала. Хоть внутрь switch его засунь, хоть внутрь if - без разницы. Точно так же, как break выскочит за пределы ближайшего к нему блока цикла или switch-a

Нашел вот что

Цитата

An expression is shifted by a negative number or by an amount greater than or equal to the width of the promoted expression (6.5.7).

An expression having signed promoted type is left-shifted and either the value of the expression is negative or the result of shifting would be not be representable in the promoted type (6.5.7).

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

Изменено пользователем ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

4 часа назад, wws63 сказал:

...

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

 

Если хотите что то похитрее, можно использовать указатель на функцию.

в главном цикле вызывать функцию по указателю и внутри функции присваивать этому указателю функцию которая должна быть вызвана следующей:

typedef uint32_t (*ptrFunc)(void);//можно определить параметры, но они у всех операций должны быть одинаковыми

ptrFunc actionFunc;

uint32_t operation1(void)

{ ваш код операции со вставками переходов в виде: actionFunc = operationХХХ;}//где operationХХХ - функция которая должна быть вызвана следующей.

uint32_t operation2(void)

{ ваш код операции со вставками переходов в виде: actionFunc = operationХХХ;}//где operationХХХ - функция которая должна быть вызвана следующей.

...

main()

{

actionFunc = operation1;

while(1)

{

//можно оставить:

do_every_time(); // функция, которая делает то, что делается всегда и в любом случае, например, обновляет дисплей

actionFunc();

}

 

}

 

Изменено пользователем ruhi

Можно сделать все! Но чем больше можно, тем больше нельзя!

Ссылка на комментарий
Поделиться на другие сайты

9 минут назад, ruhi сказал:

в главном цикле вызывать функцию по указателю и внутри функции присваивать этому указателю функцию которая должна быть вызвана следующей

Вы представляете себе, насколько сложно будет понять работу этой программы? То, что так сделать МОЖНО, еще не означает, что результат будет лучше... чем с goto :)

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, ARV сказал:

О том, что соблюдение стандарта навредить никак не может

Может ухудшить производительность и читаемость. Именно из-за попыток избежать UB.

2 часа назад, ARV сказал:

Само собой, ориентироваться на баг - это глупость. Мы всегда рассчитываем на то, что либо багов нет, либо они все документированы.

Пусть документированы, это нарушение стандарта языка и программисту приходится (или удобно) на это полагаться. Часто этим страдают программисты на cvavr, еще на msvs.

2 часа назад, ruhi сказал:

Если хотите что то похитрее, можно использовать указатель на функцию.

Если он будет это использовать вместо goto то получит проблемы со стеком. Тут лучше чем @ARV и не скажешь - надо сразу писать правильно а не городить костыли вокруг кривого кода. Функции что в Си что в Асме всегда возвращают управление туда откуда вызваны. Возвращать управление куда-то в другое место нужно крайне редко.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, ARV сказал:

еще не означает, что результат будет лучше... чем с goto :)

Я потихонечку борюсь с портянкой и goto. В первом блоке от goto уже избавился. Но все равно, тяжко. :(

Смех заключается в следующем, делал простенький проект на ПИКушке, на асме. Сделал все включая схему, программку, рисунок печатки буквально  за час.

Решил сделать также версию на тиньке, они копеечные, для изготовления партии в самый раз.  А так как там в асме  команд поболее, лень разбираться, решил попробовать на Си.... И все, началось, чем дальше в лес, тем толще партизаны.:D Но, интересно, поэтому буду потихоньку осваивать.

Опыт - это то, что получаешь, не получив того, что хотел

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, ARV сказал:

Вы представляете себе, насколько сложно будет понять работу этой программы? То, что так сделать МОЖНО, еще не означает, что результат будет лучше... чем с goto :)

А какая разница что вы блоки пишете в кейсах под свичом, а что блок принадлежащий функции???

А если логика переходов достаточно большая, то ее все равно надо бы где то отдельно описывать, хоть свич мы используем, хоть указатель на функции!

Изменено пользователем ruhi

Можно сделать все! Но чем больше можно, тем больше нельзя!

Ссылка на комментарий
Поделиться на другие сайты

Только что, COKPOWEHEU сказал:

Может ухудшить производительность и читаемость. Именно из-за попыток избежать UB

Все это так. За всё надо платить. Правильно (и качественно) работать всегда сложнее, чем как-нибудь, и не только в программировании. Так какой вывод следует из этого? Если работать с зубилом в рукавицах, очках и с защитным щитком неудобно, а без них - опасно? Какой вывод из ваших опасений в конце-концов следует сделать? Договаривайте уж.

Только что, COKPOWEHEU сказал:

Часто этим страдают программисты на cvavr, еще на msvs

Поводов страдать и не страдать всегда одинаково, все зависит от того, с какой стороны смотреть на ситуацию :)

Только что, ruhi сказал:

А какая разница что вы блоки пишете в кейсах под свичом, а что блок принадлежащий функции???

В кейсах хоть видно, что происходит...

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

7 часов назад, wws63 сказал:

Если CANNAL_1 нажата, через каждые (20*8) мс опрашиваем её заново, запрещаем прерывание (у нас оно запущено в начале программы)и так в течении 3 секунд, (если конечно она нажата). Итак, если  CANNAL_1  нажата более 3 секунд, идем на метку m_3 ( считывание значения ячейки ЕЕПРОМ и т.д.)

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

 

7 часов назад, wws63 сказал:

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

Не нужно этого всего. Отбрасывайте АСМ-подходы из головы. В Си, при нормальном подходе, такого не понадобится.

Кстати, судя по Вашему коду, у Вас не будет 20*8 мс. Если кнопки не нажаты (я так понял, их 8 штук ?), то будут постоянные переходы, без задержки.

Ссылка на комментарий
Поделиться на другие сайты

4 часа назад, ARV сказал:

Поэтому continue не применим нигде, кроме циклов. Компилятор просто не даст вам это сделать

Простите меня великодушно, но это заблуждение.

while(1){

    ......
    ......
    ......
    ......

    switch(a){
        case 1:
            ......
        break;
        case 2:
            ......
        break;
        case 3:
            ......
            continue;   // Тут прилетим вначало цикла while(1)
        break;
    
    }

}

Компилятор спокойно даст применить continue в switch-case.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Сообщения

    • Согласен, очень криво объяснил. Это работа трёх вольтовой линии, просто на диод шотки сдвоенный, на один анод приходит сигнал напрямую с трансформатора, а на второй через дроссель. Вольт/деление 5 вольт в клетке, тайминг по моему 10 МС. Третья фотография это сигнал на катодах уровень земли ровно по центру экрана. Но все линии по итогу в порядке 3.3 в, 5, в, 12 в и -12 в. Нагрузить все линии не могу сразу ,так как тут же выгорают транзисторы (имеется нагрузка 250 ватт по 10 ампер на каждую линию за исключением-12в), поэтому нагружаю 3.3 вольтовую линию на 10 ампер,  подключаю переменный резистор 50 ватт на 15 ом на 5 вольтовую линию и постепенно довожу до той той картины с перекосом (это гдето  50 ватт общее). По поводу микросхемы, вверху имеется скрин где между импульсами проскакивает мини импульс, если так можно сказать, он проскакивает и на одной  и на второй ноге (7,8). Микросхема не tl 494, а lw4933/abx942.1/c9421646. Далее они приходят на базы транзисторов 945g  коллекторы этих транзисторов соединены с  выводами трансформатора. Просто схема типовая, легче мне кажется просто привести фото самого блока, для тех кто разбирается будет гораздо информативне.  Диод шотки по 12 вольтовой линии был подгоревший, заменил на донора. Приводить скрины не буду что бы не захламлять тему. В итоге, пока все так же, при достижении определенной нагрузки суммарно где-то 50 ватт, появляется этот "выброс и перекос". По этому имеются мысли на два варианта, это микросхема , этот мини импульс между периодами, на низкой нагрузке особо не влияет, но при достижении определенной приводит с самовозбуждению входной цепи и непроизвольному открытию транзистора нижнего плеча. Либо дело в "горячей части", плавающий дефект в обвязке силовых ключей.  Спасибо за ответ.
    • @Gomerchik а вы контролировали как меняется уровень сигнала на А1 ардуины?
    • Спасибо за совет. Автором данного проекта я не являюсь, мне нужно было воссоздать уличный датчик для метеостанции взамен пропавшего(( Из разного найденного в интернете этот проект работает с моей станцией Орегон (спасибо автору). В понедельник попробую последовать Вашему совету. Но все равно куча непоняток  как блин это работает)) Если дело в неправильной отправки команды, то как на это влияет подключение датчика температуры? Если совсем не подключать таймер, то передача идет один раз (как и прописано в программе), станция принимает и отображает, но минут через сколько-то естественно станция уже ни чего не показывает, но с таймером питание полностью не пропадает с ардуинки, но передача сигнала каким-то образом работает по таймеру.  В моем понимании данная команда подается один раз потому, что таймер должен отключать питание МК после передачи сигнала и каждые 43 сек снова подавать питание (так того требует станция).  Ардуино передает показания температуры отключается полностью и 43 секунды мк не работает.  Сейчас у меня питание пока сделано на подпитке от солнечной батареи, но пару пасмурных дней и аккумулятор съедается до отключения(
    • thickman Так и сделаю. Вытащу из бу БП.  Буду знать, как отличить. Благодарю. Заменил транзисторы на IRFB20N50K. Картина стала, совсем другой.  Похоже трудность не в драйвере, на момент подвозбуда, переходные процессы, в нем, завершены. Увеличил затворные резисторы до 50ом, стало немного лучше.  Не понятно, почему верхний ключ греется несколько сильнее. Возможно, стоит посмотреть ток в коллекторе.  Снабберные емкости временно удалил, изменений не произошло.  Замена ТГР на другой, на кольце MSTN-16A-TH, так же, результата не принесла.   irfb20n50k.pdf
    • А что нить из ассортимента активных щупов производства СССР..))
    • Типа такого: https://aliexpress.ru/item/2044864227.html?sku_id=58855020183
  • Похожий контент

×
×
  • Создать...