Jump to content
a_sergeevich

Язык Си Для Микроконтроллеров

Recommended Posts

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

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

А разве нельзя просто вызвать функцию main() как и любую другую?

И потом , есть же оператор EXIT  прекращающий программу на СИ. Разве он не сделает полный RESET  и не начнёт работу с  main() заново?  

Share this post


Link to post
Share on other sites
Только что, Alex сказал:

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

Не прощу, ибо вы невнимательны :)

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

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

 

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

А разве нельзя просто вызвать функцию main() как и любую другую?

Можно. А что при этом будет со стеком?

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

И потом , есть же оператор EXIT  прекращающий программу на СИ. Разве он не сделает полный RESET  и не начнёт работу с  main() заново?

exit() - это не оператор, а стандартная функция Си, которая прерывает исполнение main, по сути реализуя выход из main

Так как в embedded-системах нет "окружения", запускающего на исполнение программу, то завершение программы микроконтроллера никак и нигде не регламентировано. То есть я хочу сказать, что неизвестно, что будет после выхода из main

Но я на 100% уверен, что программа для микроконтроллеров AVR, скомпилированная при помощи AVR-GCC, после выхода из main не приведет к сбросу микроконтроллера, а скорее наоборот, превратит его в кирпич (будут запрещены все прерывания и запущен вечный пустой цикл).

Share this post


Link to post
Share on other sites
1 минуту назад, ARV сказал:

Не прощу, ибо вы невнимательны :)

Да вроде внимательно читал :) И судил по этому тексту :

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

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

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

который означает (по моему мнению, естественно), что continue нечего делать в switch и компилятор не даст его туда вставить.
Но если это не так, прошу прощения за недопонимание :)
 

Share this post


Link to post
Share on other sites

Высококачественные конденсаторы Panasonic для надежности вашей электроники!

Электролитические алюминиевые конденсаторы Panasonic отличаются повышенной надежностью, длительным сроком службы, низким импедансом и выдерживают большой ток пульсаций, в то время как семейства полимерных конденсаторов Panasonic SP-CAP, POSCAP, OS-CON и HYBRID характеризуют сверхнизкий ESR и увеличенная емкость, работа при высоких напряжениях и в расширенном температурном диапазоне. Приобретая продукцию Panasonic, вы гарантированно получаете самое передовое решение для ваших задач. Для облегчения вашего выбора, мы подготовили подборку полезных материалов.

Читать статьи

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

который означает (по моему мнению, естественно), что continue нечего делать в switch и компилятор не даст его туда вставить

Если сам swich не находится в цикле, то continue туда никак не встанет, вот что я имел ввиду.

Share this post


Link to post
Share on other sites
3 минуты назад, ARV сказал:

А что при этом будет со стеком?

Тот же вопрос .. а если вызвать main() через указатель? Разве не получим то же самое , забыл как называется когда функция саму себя вызывает?

 

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

превратит его в кирпич (будут запрещены все прерывания и запущен вечный пустой цикл).

Возможно. Я таких тонкостей не знаю. Ну тогда наверно  можно вызвать через asm::{"rjmp reset"}?

Share this post


Link to post
Share on other sites
                     

Вебинар "Как создать BLE-устройство на базе новейшего беспроводного микроконтроллера STM32WB55"

27 ноября 2019 года компания КОМПЭЛ приглашает разработчиков, технических руководителей и энтузиастов беспроводной связи на вебинар, посвященный новинке 2019 года – мультипротокольному беспроводному микроконтроллеру STM32WB55, который позволяет создавать устройства на базе стандартов BLE 5.0; BLE Mesh; 802.15.4/ZigBee и Thread. На вебинаре мы покажем, как с помощью привычных инструментов STM32Cube и STM32CubeMX можно создать свое первое, надежно работающее BLE-приложение.

Зарегистрироваться на вебинар

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

Если сам swich не находится в цикле, то continue туда никак не встанет, вот что я имел ввиду.

А, ну так-то да.

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

Разве не получим то же самое , забыл как называется когда функция саму себя вызывает?

Получим. Называется - рекурсия.

Share this post


Link to post
Share on other sites
7 минут назад, ARV сказал:

будут запрещены все прерывания и запущен вечный пустой цикл).

не будут прерывания запрещены, С-стандарт ничего не знает про прерывания.

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

Share this post


Link to post
Share on other sites
2 минуты назад, Alex сказал:

Получим. Называется - рекурсия.

Да , спасибо, именно так.

Share this post


Link to post
Share on other sites
2 минуты назад, Alex сказал:

А, ну так-то да.

Получим. Называется - рекурсия.

Я написал (и пример привел) что функция определяет, какая функция будет вызвана следующей, читайте внимательнее!

Это похоже на "рефлексию".

Share this post


Link to post
Share on other sites
Только что, ruhi сказал:

не будут прерывания запрещены, С-стандарт ничего не знает про прерывания.

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

Ну зачем так... А разве язык Си (или стандарт) что-нибудь знает, что будет после выхода из main в программе для персонального компьютера? Этот аспект выходит за рамки стандарта Си вообще, а не только для микроконтроллеров.

Что касается запрета прерываний, то я конкретно указал условия, когда это будет сделано: если программа (прошивка МК) скомпилирована AVR-GCC, то после выхода из main будет именно то, что я и сказал. Это я вам гарантирую.

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

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

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

Share this post


Link to post
Share on other sites
1 минуту назад, ARV сказал:

Что касается запрета прерываний, то я конкретно указал условия, когда это будет сделано: если программа (прошивка МК) скомпилирована AVR-GCC, то после выхода из main будет именно то, что я и сказал. Это я вам гарантирую.

Не верю :), после выхода по return, скорее процессор будет исполнять ФФ-неинициализированной памяти, пока не вернется к ресету все таки, но проверять лень.

А вот exit может и сделает что Вы написали, должен же он что то делать.

Share this post


Link to post
Share on other sites
Только что, ruhi сказал:

не спорю

А что так? Сомневаться в моих словах и не спорить?

Share this post


Link to post
Share on other sites
Только что, ARV сказал:

А что так? Сомневаться в моих словах и не спорить?

Тоже хочешь авторитетом задавить? :)

Share this post


Link to post
Share on other sites
Только что, ruhi сказал:

Тоже хочешь авторитетом задавить?

Всего лишь хотел бабла срубить. Но вы предложили тоже нормальный вариант.

Share this post


Link to post
Share on other sites
24 минуты назад, ruhi сказал:

Я написал (и пример привел) что функция определяет, какая функция будет вызвана следующей, читайте внимательнее!

Что внимательнее читать ? :blink:
Я цитировал вопрос :

30 минут назад, SDD39 сказал:

а если вызвать main() через указатель? Разве не получим то же самое , забыл как называется когда функция саму себя вызывает?

И имел в виду, что неважно через чего вызывать - через указатель, или напрямую.

Share this post


Link to post
Share on other sites
1 час назад, Alex сказал:

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

кнопок всего две, 20*8 = 160мсек за 19 циклов =>  3 секунды, которые нужно жать кнопку, чтобы перейти на процедуру записи в еепром.

8 - это коэффициент деления тактовой частоты МК (тиньки 13) с помощью фьюза CLKDIV8. 

ALEX, Спасибо за участие, обязательно по разбираюсь с вашим вариантом, просто столько информации сразу, голова кругом:wacko:

Share this post


Link to post
Share on other sites
2 минуты назад, wws63 сказал:

8 - это коэффициент деления тактовой частоты МК (тиньки 13) с помощью фьюза CLKDIV8.

Ух, какие сложности :)
А нельзя сразу настроить так, чтобы значения в delay_ms совпадали с реальными ? :huh:

Кстати, по поводу вот этого кода :

		Value_ee = eeprom_read_byte(&data_0); // считываем байт из EEPROM и помещаем его в "Value_ee"
			if (Value_ee == 0xFF)
			   {            
				Value_ee = 0;
				eeprom_write_byte(&data_0, Value_ee); // записываем "Value_ee" в EEPROM  
				setbit (PORTB, SIG);
				_delay_ms(125);
				clrbit (PORTB, SIG);
				goto CYCLE;
			   }
			else
			   {
				Value_ee = 0xFF;
				eeprom_write_byte(&data_0, Value_ee); // записываем "Value_ee" в EEPROM  
				setbit (PORTB, SIG);
				_delay_ms(16);
				clrbit (PORTB, SIG);
				goto CYCLE;
			   }

У Вас 2 одинаковых куска. Зачем их плодить ?
А в итоге, просто инвертируется значение в ячейке еепрома.
Как вариант :

eeprom_write_byte(&data_0, ~eeprom_read_byte(&data_0));
setbit (PORTB, SIG);
_delay_ms(125);
clrbit (PORTB, SIG);

Разницу чувствуете ? :)

Share this post


Link to post
Share on other sites

Поискал немного по гуглу. Лучше всего делать программный ресет через сторожевой таймер. http://www.stepwood.com/mcucodes/2012/04/09/programmnyiy-perezapusk-mikrokontrollerov-avr/

И вот здесь нашёл интересный код на Си http://radiokot.ru/forum/viewtopic.php?t=11330

Цитата

Есть прерывание по 0 адресу – то бишь ресет 
void (*funcptr)( void ) = 0x0000;//Программный RESET 
Обращаешься как funcptr();

Только не понял как это работает. 

Share this post


Link to post
Share on other sites

@SDD39 , нельзя так делать. Будет вызов функции по адресу 0x0000, а не сброс.

Share this post


Link to post
Share on other sites
Только что, SDD39 сказал:

Лучше всего делать программный ресет через сторожевой

Как-то неожиданно с Си перешли на сброс... к чему бы это?

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

Только не понял как это работает

объявляется указатель на функцию без параметров и без возврата значения, этому указателю присваивается адрес 0x0000, а потом обращение к функции по этому указателю по сути осуществляет переход на этот адрес...

Этот подход плох лишь тем, что не инициализирует аппаратную периферию микроконтроллера, что аппаратно делается при сбросе. Поэтому вариант по watchdog предпочтительнее - там генерируется настоящий сброс МК.

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

Разницу чувствуете ?

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

Share this post


Link to post
Share on other sites
5 минут назад, ARV сказал:

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

Да, я уже предусмотрел в голове вариант, на этот случай :

eeprom_write_byte(&data_0, Value_ee = ~eeprom_read_byte(&data_0));

Но, судя по предоставленному коду, она временная и дальше не понадобится. Разве что, только мигнуть каким-нибудь светиком с разной длительностью. Но и это не проблема :

_delay_ms(Value_ee ? 16 : 125);

Или через if.

Share this post


Link to post
Share on other sites
2 минуты назад, Alex сказал:

Да, я уже предусмотрел в голове вариант, на этот случай :


eeprom_write_byte(&data_0, Value_ee = ~eeprom_read_byte(&data_0));

 

У меня там ещё и длительность сигнала SIG, зависит от записанного значения в еепром

Share this post


Link to post
Share on other sites
1 минуту назад, wws63 сказал:

У меня там ещё и длительность сигнала SIG, зависит от записанного значения в еепром

Да, видел. Только что обновил своё сообщение.  Не успел сразу :)

6 минут назад, Alex сказал:

Но, судя по предоставленному коду, она временная и дальше не понадобится. Разве что, только мигнуть каким-нибудь светиком с разной длительностью. Но и это не проблема :


_delay_ms(Value_ee ? 16 : 125);

Или через if.

 

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • By Артемон
      Всем привет. Просьба посодействовать в исправлении кода для термометра. Так как сам я в этом новичек, то код собирал из трех чужих проектов. Реализация такова, подключение термопары через микруху Max6675 к Atmega и вывод данных на LCD экран. В архиве прилагаю проект Atme Studio 7 и принт скрин из Протеуса. Ошибка заключается в неправильных показаниях температуры

      Test1.rar
      Вот код, чтоб не скачивать проект.

      #define F_CPU 1000000UL #include <util/delay.h> #include <avr/io.h> #include "max6675.h" #include "LCD.h" uint16_t gettemp(void); //Funktionsdeklarationen void initavr(void); //gettemp () returns absolute Temperature in Temp * 4 °C - in 1/4°-steps // uint16_t gettemp(void){ //Temperatur holen. uint8_t bit = 0, bitnr = 12; //Variablen uint8_t foo1 = 0; uint16_t Rohdata = 0; CS_Port &= ~(1 << CS); //Chip select anlegen for(foo1 = 0 ; foo1 < 16 ; foo1++){ //16 Bits einlesen bit = 15 - foo1; //Die Aktuelle Bitnr berechnen. SCK_Port |= (1 << SCK); //SCK hi if((bit <= 14) && (bit >= 3)){ //Einfach mal die 12 relevanten von den 16 Bits ausfiltern if((SO_Pin & (1 << SO))){ //WENN SO 1 ist, dann... bitnr--; //zдhlen wir runter... Rohdata |= (1 << bitnr); // und schieben eine 1 an bit x }else{ //WENN dem NICHT so ist, dann... bitnr--; //zдhlen wir runter... Rohdata &= ~(1 << bitnr); //und schieben eine 0 an bit x } }else{ //weis au nimmer, was das soll. bitnr = 12; } SCK_Port &= ~(1 << SCK); //SCK LO } CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. return Rohdata; //Das ist doch mal was ;D } // getTC() returns 0 if Thermocouple is not connected, 255 if thermocuple is connected // (to enable this feature T- must be connected to GND) uint8_t getTC(void){ //Temperatur holen. //Variablen uint8_t TC = 0; uint8_t foo1 = 0; CS_Port &= ~(1 << CS); //Chip select anlegen for(foo1 = 0 ; foo1 < 16 ; foo1++){ //16 Bits einlesen //Die Aktuelle Bitnr berechnen. SCK_Port |= (1 << SCK); //SCK hi if(foo1 == 2){ //das 3. bit ist fьr uns relevant. if((SO_Pin & (1 << SO))){ //WENN SO 1 ist, dann... TC = 0; }else{ //WENN dem NICHT so ist, dann... TC = 255; } } SCK_Port &= ~(1 << SCK); //SCK LO } CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. return TC; //Das ist doch mal was ;D } //Initiates the MAX6675 and IO-pins void init_6675(void){ //AVR initialisieren SO_DDR &= ~(1 << SO); CS_DDR |= (1 << CS); SCK_DDR |= (1 << SCK); //IOs setzen SO_Port |= (1<<SO); //Pullups an. (Wichtig fьr MAX6675, der kann nicht anders, hab ich festgestellt... CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. SCK_Port &= ~(1 << SCK); //SCK LO } int main(void) { init_port();// инициализируем порт ЖКИ lcd_init();// инициализируем ЖКИ init_6675(); while (1) { char buffer[8]; int temp; temp = gettemp(); temp /=4; lcd_gotoxy(0,0);//перемещаем курсор в верхний левый угол sprintf(buffer, "t=%i\xdf\C ", temp); // так как тут не плавающая запятая то числа с запятой записываются так %i.%i, код градуса записывается так \xdf lcd_putstring(buffer); } }
      вставляете код пользуйтесь тегами [CОDE][/CОDE] редактора сообщений, кнопка <>
    • By igoryan
      нужно ли обрабатывать RESET просто компилятор не видит RESET_vect?
    • By P32L
      Натолкните на мысль пожалуйста.Смысл в следующем.Нужно изменять задержку(Delay) из EEPROM. Контроллер PIC , язык СИ.
      Как реализовать чтение числа из ипрома ? Если не затруднит, то кусочек кода был бы очень кстати.
    • By Zver2011
      Здравствуйте! Недавно начал изучать МК AVR. Читаю книги Белова. Пользуюсь программами CVAVR и Proteus. По урокам, собирал все в железе. По готовым примерам кода конечно же мне легко учиться и все в принципе понятно из описания, хоть и в программировании не силен, но как только начинаешь создавать что то свое - начинаются проблемки.
      В общем я создаю что то вроде музыкального светильника, который должен включаться от звука (голоса). Датчик звука пытаюсь реализовать на компараторе, плавное включение света - ШИМ, а генерация мелодии (пищалки) благодаря таймеру Т1 и его прерыванию. Куски кода брал из разных чужих самоделок, вот только объединить не удается.
      В железе работает как будто цветомузыка какая-то. Мелодия не играет, Я думаю это из-за неправильной конфигурации компаратора, а также схемы. Вот это основной вопрос у меня. Ну и собственно основной цикл программы, там я думаю тоже накосячил.
      Помогите мне разобраться до конца, понять ошибки в коде, мне самому интересно вот только С - язык тяжеловатый на мой взгляд и без помощи знающих не обойтись))

      КОД.txt
    • By sensey88
      Продам счетчики бета-гамма излучения новые заводская упаковка
      Си1Г (79г) 62 шт. 5000р
      Си21БГ (79г) 49 шт. 350р
      Си22БГ (79г) 70 шт. 700р
      Си3БГ (84г) 20 шт. 300р
      Си3БГ (78г) 46 шт. 250р
      Си3БГ (77г) 10 шт. 250р
      Си3БГ (79г) 18 шт. 250р
      Си3БГ (75г) 10 шт. 200р
      Си37Г (80г) 40 шт. 400р
      Си37Г (76г) 24 шт. 350р
      Си37Г (79г) 16 шт. 350р
      Си33Г (78г) 28 шт. 450р
      Си33Г (77г) 15 шт. 450р
      СБТ13 (78г) 2 шт. 3000р
      СБТ13 (76г) 3 шт. 2700р
      СБТ13 (69г) 3 шт 2500р.
      Си8Б (79г) 1 шт. 2500р
      Си8Б (78г) 1 шт. 2500р
      СБТ10 (79г) 3 шт. 4500р
      8 (910) 7051241 Евгений
      bishop-x@yandex.ru
  • Сообщения

    • Утюг - это ИП, а лампочка - СД? Или наоборот?  Правильная аналогия: Стабилитрон можно включить параллельно нагрузке, а можно последовательно. Это зависит от того, что Вы хотите достичь его применением. Так вот, ТС включил стабилитрон последовательно.   Опять выгорает только вторая пара?
    • Потому, что не дурак. Будете оспаривать? 
    • Жертвуем полным уровнем и делим входной сигнал в необходимое число раз. Удобно для данного случая делить на 2. Для этого уменьшаем R2  и R4 до 255 кОм, на OUT  получаем половину от напряжения на аккумуляторе. Это учитываем для последующего сдвига значения при вычислении. И ещё одно. Не всякий ОУ будет работать при 3 - х вольтовом питании. Надо выбрать подходящий с rr in.
    • Да, на снимке нормализованная АЧХ. Но и приведенная к 1 вт покажет не высоту взлета, а глубину падения, если правильно смотреть.  По п.1-4 и далее, я писал - образное сравнение конкретной замены.  Причем, не учитывая, что ФИ, рассчитанный под 25гд, усугубляет...
    • О, как здорово - за меня уже всё продумано и расписано, не надо напрягаться. Весьма признателен, только Почему "не сможет" и почему "не захочет"? Жду продолжения описания моих качеств.   Других нет и взять их неоткуда.   Угу и это в наших интересах, значит и заниматься этим, и контролировать нам. У верхушки и начальства интересы другие.
    • Да куплены и поменены,на много не поменялось нечего Теперь вон по модному ставят полностью светодиодные,так если gayss то температурный цвет раскидан в одном светильнике от 5000К до 6500К ,на помойке подбирают или на распродажу с заводов,вот iek нет таких косяков,все ровно ,но и они не те десятки тысяч часов наработки...в линейках цепочки по 4 светодиода паралельно ,жуть
    • С таким же успехом можно утверждать, что включенная утюг в одну розетку с лампочкой нанесет ей вред. Вот, для понимания сути. Нарисовал, как мог:  
×
×
  • Create New...