— доступны в любом месте программы -значит можно читать их значения и присваивать переменным значения там где вам требуется — в любом месте программы после их объявления.
5) описание функций — обработчиков прерываний
6) описание других функций используемых в программе
Программа на Си начинает работу с функции main()
по необходимости из main()вызываются другие функции программы, из которых может быть вызов следующих функций, по завершении работы функции программа возвращается по той же цепочке как вызывались функции.
. какой то код программы .
вызов функции_1; //программа перейдет в функцию_1
строка программы; // будет выполнятся после
// возврата из функции_1
. какой то код программы .
Поразрядные (побитные) логические операции. Примеры применения.
Поразрядные (побитные) логические операции:
И» (AND — только 1 и 1 дают 1) могут быть и другие побитные логические операции:
| «ИЛИ» (OR только 0 и 0 дают 0)
Чем отличается МИКРОКОНТРОЛЛЕР и МИКРОПРОЦЕССОР
^ «Исключающее ИЛИ» (XOR изменить бит напротив «1»)
~ «инвертирование битов» (INV изменить биты регистра)
и арифметические операции: + — * / %
Примеры
00010010 | 01001111 // «ИЛИ» — только 0 и 0 дают 0 // англ. название OR 01011111 // это результат // только биты_5 в обоих числах были нули |
00010010 И» — только 1 и 1 дают 1 // англ. название AND 00000010 // это результат // только биты_2 в обоих числах были единицы |
00010010 ^ 01001111 /* «исключающее ИЛИ» — результат любое из пары чисел в котором инвертированы (изменены) биты напротив битов равных «1» в другом числе. англ. название XOR */ 01011101 // это результат /* изменились биты во втором числе напротив установленных битов 4 и 1 первого числа. */ |
~ 01001111 /* инвертировать биты те что были «1» станут «0» и наоборот */ 10110000 // это результат |
Результатом поразрядных (побитных)
логических операций :
Которое может быть интерпретировано компилятором как «истина»
если оно не ноль и «ложно» если число ноль.
Логические операции:
|| // «ИЛИ» — только «ложь» и «ложь» // дают «ложь» // «И» — только «истина» и «истина» // дают «истина» ! // «НЕ» — логическое отрицание /*Правило — в Си считается: «Ложь» (False) только ноль. «Истина»(True)- не ноль. или так: (!0) */ !(истина) // дает «ложь» !(ложь) // дает «истина» |
Арифметические операции на языке Си. Арифметические операции без оператора присваивания. Операторы сравнения (или отношения). Примеры применения.
Уроки Arduino #1 — структура программы и типы данных
Арифметические операции в Си
x + y// сложениеx — y// вычитаниеx * y// умножение x / y/* деление. Если числа целые результат — целое число с отброшеннойдробной частью — не округленное ! т.е. если в результате деления на калькуляторе получается 6.23411 или 6.94 то результат будет просто целое число 6 — запомните ! Если числа с плавающей точкой, то есть float или double и записываются с точкой и числом после точки, то и результат будет число с плавающей точкой без отбрасывания дробной части 131.9739 / 6.18 даст 21.355 */ x % y// вычислить остаток от деления нацело // примеры: 5 / 2// даст 2 5 % 2// даст 1 75 / 29// даст 2 75 % 29// даст 17 |
Операторы сравнения (или отношения):
используются для сравнения переменных, чисел (констант) и выражений.
Источник: allrefrs.ru
Структура программы
Рассмотрим синтаксические особенности ассемблера AVR на примере небольшой тестовой программы для микроконтроллера ATmega8, приведенной ниже. Программа формирует на выводе PB2 импульсы с частотой следования ≈ 2.5 Гц при частоте внутреннего RC-генератора 1 МГц.
1. ; Тестовая программа для ATmega8. 2. // Светодиод подключен к выводу PB0 микроконтроллера. 3. /* Биты конфигурации: Low Fuse High Fuse BODLEVEL = 1 RSTDISBL = 1 BODEN = 1 WDTON = 1 SUT1 = 1 SPIEN = 1 SUT0 = 0 CKOPT = 1 CKSEL3 = 0 | EESAVE = 1 CKSEL2 = 0 |_ RC-генератор BOOTSZ1 = 1 CKSEL1 = 0 | 1 МГц BOOTSZ0 = 1 CKSEL0 = 1 | BOOTRST = 1 */ 4. .nolist ;подключение стандартного заголовочного файла 5. .include «m8def.inc» 6. .list 7. .equ PAUSE = 50000 ;задержка времени 8. .equ LED = PB2 ;вывод для подключения светодиода 9. .def temp = R16 ;регистр для промежуточных операций 10. .def buffer = R17 ;регистр для чтения порта 11. .cseg 12. .org 0 13. rjmp initial ;0xC01F 14. rjmp 0 ;rjmp service_INT0 ;внешнее прерывание 0 0xCFFE 15. rjmp 0 ;rjmp service_INT1 ;внешнее прерывание 1 0xCFFD 16. rjmp 0 ;rjmp service_OC2 ;совпадение TCNT2 и OCR2 0xCFFC 17. rjmp 0 ;rjmp service_OVF2 ;переполнение TCNT2 0xCFFB 18. rjmp 0 ;rjmp service_ICP1 ;захват в ICP1 0xCFFA 19. rjmp 0 ;rjmp service_OC1A ;совпадение TCNT1 и OCR1A 0xCFF9 20. rjmp 0 ;rjmp service_OC1B ;совпадение TCNT1 и OCR1B 0xCFF8 21. rjmp 0 ;rjmp service_OVF1 ;переполнение TCNT1 0xCFF7 22. rjmp 0 ;rjmp service_OVF0 ;переполнение TCNT0 0xCFF6 23. rjmp 0 ;rjmp service_SPI ;прерывание от модуля SPI 0xCFF5 24. rjmp 0 ;rjmp service_URXC ;получение байта по USART 0xCFF4 25. rjmp 0 ;rjmp service_UDRE ;опустошение UDR в USART 0xCFF3 26. rjmp 0 ;rjmp service_UTXC ;передача байта по USART 0xCFF2 27. rjmp 0 ;rjmp service_ADCC ;прерывание от АЦП 0xCFF1 28. rjmp 0 ;rjmp service_ERDY ;завершение записи в EEPROM 0xCFF0 29. rjmp 0 ;rjmp service_ACI ;прерывание от компаратора 0xCFEF 30. rjmp 0 ;rjmp service_TWI ;прерывание от модуля TWI 0xCFEE 31. rjmp 0 ;rjmp service_SPMR ;завершение выполнения spm 0xCFED 32. .org 0x20 33. initial: ldi temp,low(RAMEND) ;0xE50F 34. out SPL,temp ;0xBF0D 35. ldi temp,high(RAMEND) ;0xE004 36. out SPH,temp ;0xBF0E 37. cbi PORTB,LED ;0x98C2 38. sbi DDRB,LED ;0x9ABA 39. ldi temp,1«LED ;0xE004 40. main: in buffer,PORTB ;0xB318 41. eor buffer,temp ;0x2710 42. out PORTB,buffer ;0xBB18 43. rcall delay ;0xD001 44. rjmp main ;0xCFFB 45. delay: ldi XH,high(PAUSE) ;0xECB3 46. ldi XL,low(PAUSE) ;0xE5A0 47. sbiw XH:XL,1 ;0x9711 48. brne PC-1 ;0xF7F1 49. ret
В строках 1…3 приведено 3 возможных варианта оформления комментариев. Комментарий в строке 1, начинающийся со знака “;”, распознается любым ассемблером и поэтому является наиболее предпочтительным. Комментарии в строках 2 и 3 подобны тем, которые используются в нотациях языков высокого уровня.
Последний из них дает возможность выделить сразу несколько строк (маркерами начала и конца фрагмента текста является “/*” и “*/” соответственно). В строке 5 директивой .include к программе подключается стандартный заголовочный файл «m8def.inc». Необязательные директивы .nolist и .list (строки 4 и 6 соответственно) запрещают вывод содержимого подключаемого файла в файл листинга. Все директивы допускается размещать в одной строке. Так, например, можно было бы записать
.nolist .include «m8def.inc» .list Несмотря на это, желательно придерживаться правильного стиля программирования, в соответствии с которым в одной строке должна быть расположена только одна директива ассемблера. Объявление констант находится в строках 7 и 8. Константе LED присваивается номер линии ввода-вывода PB2 = 2, описание которой находится в заголовочном файле.
В строках 9 и 10 двум рабочим РОНам назначаются пользовательские имена. Секция рабочего кода открывается директивой .cseg в строке 11. Директива .org 0 (строка 12) устанавливает начальный адрес в памяти программ. В строке 13 должна находиться инструкция перехода на метку начала основной программы initial. Метка представляет собой адрес в пределах секции кода или данных.
В ассемблере AVR она должна быть записана в начале строки и завершаться в конце двоеточием. Конечно, адрес в команде может быть указан и явно. В данном примере его можно задать безошибочно (rjmp 0x20 вместо rjmp initial). Но, это возможно только потому, что директива .org 0x20 (строка 32) заставляет компилятор поместить команду в строке 33 по адресу 32-го слова FLASH-памяти программ.
Однако, в большинстве случаев, адрес размещения той или иной команды заранее неизвестен и, кроме того, он может изменяться по мере того, как в программу будут вноситься изменения. Именно поэтому предпочтительней использовать метки. Назначение их адресов производится автоматически на этапе компиляции.
Да и символьные имена меток, предоставляют об объектах намного больше информации, чем просо какие-то числа. На месте каждого неиспользуемого в программе прерывания желательно поставить “заглушки” в виде команды возврата rjmp 0 или reti, как это сделано в строках 14…31. В строках 33…39 производится инициализация ресурсов микроконтроллера.
Любая программа обязательно должна начинаться с установки начального значения указателя стека (если он имеется). В строках 33…36 в SPH:SPL заносится значение RAMEND = 0x045F (вершина стека перемещается в самый верх SRAM). Для выделения младшего и старшего полубайтов константы RAMEND используются встроенные функции low(RAMEND)=0x5F и high(RAMEND)=0x04 соответственно. Далее разряд LED в регистре данных порта B сбрасывается на 0 (стока 37), а сама линия управления светодиодом настраивается на вывод (стока 38). В строке 39 в регистр temp заносится константа 1
ldi temp,(1«PB0)|(1«PB5) или ldi temp,(1«PB0)+(1«PB5) ;temp
Код в строках 40…44 представляет собой тело основной программы. В регистр buffer считывается текущее состояние порта данных PORTB (строка 40). Далее между содержимым buffer и temp производится операция “Исключающее ИЛИ” (строка 41), после чего модифицированное содержимое buffer снова выводится в порт (строках 42).
В результате такого действия логический уровень на линии PB2 изменится на противоположный. В строке 43 происходит вызов подпрограммы задержки времени delay (≈200 мс), а в строке 44 расположена инструкция перехода на метку main.
Так образуется основной цикл программы, в котором происходит постоянное повторение операторов в строках 40…44: инвертирование уровня на выводе LED, задержка, затем снова инвертирование и т.д. Внутри подпрограммы delay в регистровую пару XH:XL заносится число PAUSE = 50000, определяющее длительность задержки времени (строки 45, 46).
В строке 47 из содержимого XH:XL вычитается 1. Команда условного перехода в строке 48 проверяет, значение флага Z из SREG. Если Z = 1 (результат предыдущей операции не равен нулю), то управление передается на строку 47. Так будет повторяться до тех пор, пока не выполнится условие XH:XL = 0 (т.е. пока не пройдет 50000 циклов вычитания).
Команда выхода ret в строке 49 возвращает управление в то место основной программы, с которого произошел вызов delay. Отдельно стоит обратить внимание на встроенную в ассемблер переменную PC в строке 48. Она представляет собой текущее содержимое программного счетчика. Адрес PC-1 будет указывать на предыдущее слово в памяти программ микроконтроллера.
В данном случае в этом слове находится команда sbiw XH:XL,1. Использовать PC очень удобно для программных переходов в небольших пределах. Однако здесь всегда необходимо помнить, что у микроконтроллеров AVR имеются команды, которые имеют размер в 2 16-разрядных слова программ (lds Rd,k, jmp k и др.), из-за чего при вычислении смещения необходимо будет добавлятьотнимать к PC значение 2 вместо 1 на каждую такую инструкцию. Справа, в листинге приведен машинный код, который будет сгенерирован после компиляции программы. Перейти к следующей части: Макросы
Теги:
Котов Игорь Юрьевич
Опубликована: 2012 г.
0
Вознаградить Я собрал 0 0
Источник: cxem.net
Программирование микроконтроллеров на языке C. Часть 1
Приветствую всех жителей и гостей Датагор.ру!
Года полтора назад мы с Радиком Галимовым, более известным как камрад Galrad, обсуждали возможность совместной публикации о программировании микроконтроллеров на языке Си.
Далее закружились всякие важные и не очень события и стало как-то не до того.
А недавно меня настигла и сокрушила новость о том, что Радика с нами больше нет. Об этом сообщил в редакцию нашего журнала камрад Александр (mazr).
Отдавая дань уважения, я решил всё же написать статью и посвятить её памяти этого замечательного Человека.
↑ Предисловие
Данная работа является логическим продолжение серии статей «Ассемблер для микроконтроллеров с нуля», в которой достаточно подробно освещены:
• Общие принципы устройства и работы микроконтроллера (МК).
• Система тактирования и прерывания.
• Назначение и функциональные возможности таких модулей МК, как порт ввода/вывода, АЦП, таймер.
• Механизм компиляции и сборки проекта средствами GCC, включая содержимое файлов Makefile и сценария компоновщика LinkerScript.
• Подключение к проекту сторонних объектных файлов и библиотек.
• Структура программы и её оптимизация посредством макроопределений/макросов, функций и хидер-файлов.
• Основные ошибки, допускаемые программистом, и методы их поиска и устранения.
Поскольку вся вышеуказанная информация пригодится нам и при изучении Си, я буду время от времени ссылаться на соответствующий раздел вышеуказанной статьи, для краткости именуя её «Ассемблер. » и лишь в особо важных случаях — дублировать фрагмент текста.
Цель остаётся прежней — освоить базовые знания и навыки в программировании МК, используя для разных платформ единые среду программирования и компилятор.
↑ Необходимые детали и устройства
Для практических занятий нам понадобятся:
1. Микроконтроллер ATmega8
Если у вас не оказалось под рукой нужного микроконтроллера, ничего страшного: достаточно внести некоторые изменения в пару файлов, адаптировав их под ваш МК, о чём — чуть ниже.
↑ Установка и настройка ПО
↑ Компилятор, тулчейны, загрузчики, SPL и SDK
Скачайте и установите компилятор, тулчейны и загрузчики согласно раздела 3.2 первой части «Ассемблер. ». Кроме того, потребуются SPL (Standard Peripheral Library) для STM32F401 и SDK (Software Development Kit) для nRF52832, которые необходимо скачать и сохранить в папку GNU.
В случае, если вы используете STM32 с иным ядром, при скачивании SPL ориентируйтесь на первую цифру после буквы «F» в названии МК.
↑ Редактор VS Code
За последний год, дети «подсадили» меня на редактор Visual Studio Code , который имеет перед Notepad++ ряд преимуществ, приведу из которых пару:
а) Более продвинутый интерфейс, включая систему авто-подстановки.
б) Подключение соответствующего расширения даёт возможность писать в этом же редакторе приложения под Windows, Android, iOS (на Java, Python и др.) для обмена информацией с устройством на МК.
В ходе установки следует выставить галочки для подключения опции «Открыть с помощью VS Code».
Рисунок 1. Подключение опции «Открыть с помощью VS Code»
Коротко об основных полях и вкладках редактора.
Рисунок 2. Основные вкладки и поля VS Code
Слева располагается панель инструментов, наиболее часто из вкладок которой используются «Проводник» (при кодировании) и «Расширения» (для подключения новых расширений).
В окне редактора мы будем писать наши программы. Здесь же отображаются функции расширения, предполагаемого к установке, а так же опции при настройке редактора через File/Preferences/Settings.
Окно консоли, открываемое комбинацией Control + Shift + тильда, будет использоваться для запуска программа make с целью компиляции кода и загрузки hex-файла в МК.
Поскольку в практических примерах предполагается передача данных в компьютер посредством UART, установим соответствующее расширение, для чего:
1. Пройдём во вкладку «Расширения» панели инструментов и в окне поиска наберём «serial».
2. Выберем из списка расширение «Serial monitor»
3. Нажмём кнопку «Install» в правой части редактора.
Рисунок 3. Установка расширения «Serial monitor»
После установки расширения в одном поле с консолью должна появиться вкладка «Serial Monitor», к настройкам и применению которой вернёмся позже.
↑ Шаблонные файлы
Скачайте архив папки шаблонных файлов под ваш МК. Распакуйте папку, зайдите в неё и кликните по свободному месту правой клавишей мыши. Выберите в открывшемся контекстном меню пункт «Открыть с помощью Code / Open with Code».
Рисунок 4. Переход к редактору VS Code
Информацию о структуре и назначении шаблонных фалов можно почерпнуть из 2-й части и 7-й части «Ассемблер. ».
В окне проводника редактора, последовательно выбирая нижеуказанные файлы, внесите следующие правки.
Для всех МК в файле c_cpp_properties.json из папки .vscode изменить на свой путь в 8-й строке.
Для AVR при использовании иного микроконтроллера, исправить на соответствующее название МК (например, attiny2313 или atmega328p) в 3-й строке файла variables.mk.
Для STM32F401
1. Изменить на свои пути в строках 8, 9 и 10 файла variables.mk.
2. При использовании МК с другим ядром изменить на соответствующие:
а) в файле variables.mk:
• тип ядра (например, cortex-m0 или cortex-m3) в 3-й строке,
• название файла startup.s в 14-й строке,
• название конфигурационного файла в 48-й строке.
б) в файле LinkerScript.ld:
• начальные адреса и размеры ОЗУ и флэш-памяти в 64-й и 65-й строках, соответственно, ориентируясь на данные из даташита.
↑ Проверка ПО и МК
Чтобы убедиться в исправности и работоспособности софта и «железа», подключим программатор к компьютеру с одной стороны, а к МК — с другой, соединив для Atmega8 одноимённые пины согласно Рисунка 5.
Рисунок 5. Распиновка а) MK ATmega8 и б) программатора USBasp
В случае с STM32F401 пины, используемые для прошивки, выведены в правую часть макетной платы, причём пин SWCLCK обозначен как SCK, а SWDIO – как DIO. Распиновка макетной платы nRF52832 обозначена на её оборотной стороне.
Рисунок 6. Распиновка макетной платы а) STM32F401 и б) nRF52832 и в) программатора st-link v2
Далее создадим папку нашего первого проекта с именем first, скопируем в неё шаблонные файлы для интересующего нас МК и откроем с помощью VS Code. Скомпилируем файл main.c из папки src, набрав в консоли «make» + Enter. В случае успешной компиляции должна быть автоматически создана папка exe с elf- и hex- файлами. Осталось прошить МК, набрав в консоли «make upload» + Enter. Если компилятор не выдал в консоль сообщения об ошибках, значит мы готовы перейти непосредственно к Си.
Но, об этом — в следующий раз.
Продолжение следует!
↑ Всё железо списком
↑ Файлы
Архивы шаблонных файлов под ваш МК:
atmega8-template.7z 1.5 Kb ⇣ 20
Наш файловый сервис предназначен для полноправных участников сообщества «Datagor Electronics».
Для получения файла зарегистрируйтесь и войдите на сайт с паролем.
nrf52832-template.7z 2.51 Kb ⇣ 13
Наш файловый сервис предназначен для полноправных участников сообщества «Datagor Electronics».
Для получения файла зарегистрируйтесь и войдите на сайт с паролем.
Наш файловый сервис предназначен для полноправных участников сообщества «Datagor Electronics».
Для получения файла зарегистрируйтесь и войдите на сайт с паролем.
Источник: datagor.ru