
- •Основы языка си для микроконтроллеров avr
- •1. Основы языка Си для микроконтроллеров avr
- •Препроцессор языка Cи его команды
- •Директива #include
- •Директивы #define, #undef
- •Директивы #if, #ifdef, #ifndef, #else и #endif
- •Встроенные макросы
- •Директива #line
- •Директива #error
- •Директивы #asmи #endasm
- •Зарезервированные ключевые слова
- •Идентификаторы
- •Комментарии
- •Константы
- •Переменные
- •Массивы
- •Типы данных
- •Операнды и операции
- •Унарные операции
- •Бинарные операции
- •Приоритеты операций и порядок вычислений
- •Операторы
- •If-else
- •Оператор for
- •Do-while
- •Continue
- •Оператор-выражение
- •Пустой оператор
- •Составной оператор
- •Функции
- •Указатели
- •Доступ к регистрам ввода/вывода
- •Побитовый доступ к регистрам ввода/вывода
- •Доступ к eeprom-памяти
- •Использование прерываний
- •Организация памяти sram
Оператор-выражение
Любое выражение, которое заканчивается точкой с запятой, является оператором.
Выполнение оператора-выражения заключается в вычислении выражения. Полученное значение выражения никак не используется.
Пример:
/* Оператор — выражение */
++х; // Этот оператор-выражение увеличивает значение переменной х на единицу
а=5; // Этот оператор-выражение присваивает переменной а значение 5
y=function(х); // Этот оператор-выражение включает в себя операции присваивания (у=...) и вызова функции (function(х))
Пустой оператор
Пустой оператор состоит только из точки с запятой. При выполнении этого оператора ничего не происходит. Синтаксис:;
Пустой оператор позволяет поставить метку перед закрывающей скобкой (}) составного оператора или указать пустое тело в операторах цикла, где по синтаксису требуется хотя бы один оператор.
Синтаксис языка Си требует, чтобы после метки обязательно следовал оператор. Фигурная же скобка оператором не является. Поэтому, если требуется передать управление на фигурную скобку, следует использовать пустой оператор.
Пример:
/* Пустой оператор */
int function ( ) // определение функции function
{
{
if (...) // Если условие оператора if выполняется,
goto Label; // то осуществляется переход на метку Label, т. е. на скобку
{
Label: ; } // метка Label с пустым оператором, после которой следует скобка
return (...) ;
Пример:
/* Пустой оператор */
/* Организация бесконечного цикла с помощью пустого оператора */
while (1) // Условие в скобках всегда истинно
/* Тело цикла while */
; // Пустой оператор
Составной оператор
Составной оператор представляет собой несколько операторов и объявлений. Для объединения объявлений и операторов в составной оператор или блок используются фигурные скобки ({ }). Одним из примеров такого типа являются фигурные скобки, в которые заключаются операторы, составляющие функцию.
Синтаксис:
{[объявление] оператор; [оператор];}
Выполнение составного оператора заключается в последовательном выполнении составляющих его операторов.
Пример:
/* Составной оператор */
/* Пример полного определения функции, которая возвращает максимальное из трех значений переменных */
int maximum(int a, int b, int с) // Объявление функции maximum, которая возвращает целое значение, т. к. перед именем функции стоит int
После первой фигурной скобки, которая завершает блок (составной оператор), в языке Си точка с запятой НИКОГДА не ставится. В Code VtsionA VR ДОПУСКАЕТСЯ ставить точку с запятой.
/* Составной оператор */
{
int d; // Объявление целой переменной d
d = (а>b)? a : b; return!(d>c)? d : c); // Переменной d присваивается максимальное из значений переменных а и b. Функция возвращает максимальное из значений переменных d и с (Тернарные операции)
}
Функции
В отличие от других языков программирования высокого уровня в языке Си нет деления на процедуры, подпрограммы и функции, здесь вся программа строится только из функций.
Функция — это совокупность объявлений и операторов, обычно предназначенная для решения определённой задачи. С использованием функций в языке Си связаны три понятия:определение функции (описание действий, выполняемых функцией),объявление функции (задание формы обращения к функции) ивызов функции.
Каждая функция должна иметь имя, которое используется для её объявления, определения и вызова.
В любой программе должна быть функция с именем main (главная функция), и именно с этой функции, в каком бы месте программы она ни находилась, начинается выполнение программы.
Определение функции задаёт тип возвращаемого значения, имя функции, типы и число формальных параметров, а также объявления переменных и операторы, называемые телом функции и определяющие действие функции. В определении функции также может быть задан класс памяти.
Синтаксис для объявления функции:
[<класс памяти>] [<тип>]имя_функции ( [<список параметров;»] {
тело функции (список операторов)
}
Необязательный спецификатор класса памяти задаёт класс памяти функции, который может бытьstaticилиextern(подробнее о классах памяти см. Переменные).
Спецификатор типа функции задаёт тип возвращаемого значения и может задавать любой тип. Если спецификатор типа не задан, то предполагается, что функция возвращает значение типаint. Для функций, не возвращающих никакого значения, должен быть использован типvoid, указывающий на отсутствие возвращаемого значения.
Функция не может возвращать массив или функцию, но может возвращать указатель на любой тип, в том числе и на массив, и на функцию.
Список формальных параметров — это последовательность объявлений формальных параметров, разделённая запятыми. Формальные параметры — это переменные, используемые внутри тела функции и получающие значение при вызове функции путем копирования в них значений соответствующих фактических параметров. Список формальных параметров может заканчиваться запятой (,) или запятой с многоточием (,...); это означает, что число аргументов функции переменно. Однако предполагается, что функция имеет, по крайней мере, столько обязательных аргументов, сколько формальных параметров задано перед последней запятой в списке параметров. Такой функции может быть передано большее число аргументов, но над дополнительными аргументами не проводится контроль типов. Если тип формального параметра не указан, то этому параметру присваивается типint.
Если функция не использует параметров, то наличие круглых скобок обязательно, а вместо списка параметров рекомендуется указать слово void.
Тело функции — это составной оператор, содержащий операторы, определяющие действие функции.
Объявление функции имеет такой же вид, что и определение функции, с той лишь разницей, что тело функции отсутствует и имена формальных параметров тоже могут быть опущены. Чтобы объявить функцию, можно использовать функциональныепрототипы. Прототип — это явное объявление функции, которое предшествует её определению. Тип возвращаемого значения при объявлении функции должен соответствовать типу возвращаемого значения в определении функции.
Пример:
/* Прототип функции */
intfunction(inta,intb,intс) // Объявление функцииfunction, которая возвращает целое значение, т. к. перед именем функции стоит int
/* Фактическое определение функции может быть написано где-нибудь в другом месте программы */
int function(int a, int b, int с) // тело функции
{
[группа операторов]
}
При вызове функции ей при помощи аргументов (формальных параметров) могут быть переданы некоторые значения (фактические параметры), используемые во время выполнения функции. Функция может возвращать некоторое (но ТОЛЬКО ОДНО) значение. Это возвращаемое значение и есть результат выполнения функции, который при выполнении программы подставляется в точку вызова функции, где бы этот вызов ни встретился. Допускается также использовать функции, не имеющие аргументов, и функции, не возвращающие никаких значений. Действие таких функций может состоять, например, в изменении значений некоторых переменных, выводе некоторых значений и т.п.
Пример:
/* Вызов функции */
/* определение функции с формальными параметрами а, b, и с */
int function(int a, int b, int с)
{
return (a+b+c); // тело функции
}
/* Основная функция программы */
void main(void)
{
int x=5, y=6, z=10; // Объявляем и инициализируем целые переменные х, у и z int result; Объявляем целую переменную result
result=function(x,y,z); // Вызовем функцию function с фактическими параметрами х,у и z. В результате функция вернёт значение суммы этих параметров: result=5+6+10=21
}
В CodeVisionAVRне поддерживается так называемый старый стиль написания определений функций, при котором описание формальных параметров расположено между именем функции со списком формальных параметров и телом функции.
Пример:
/* определение функции в "старом стиле", которое CodeVisionAVR не поддерживает. Будет выдаваться синтаксическая ошибка!!! */
int maximum(a, b, с) int a, b, с; // тело функции
{
[группа операторов]
/* Правильное определение функции */
int function(int a, int b, int с) // тело функции
{
[группа операторов]
}
Параметры функций передаются через DataStack(Стек данных). Значения функций возвращаются в регистрыR30,R31,R22 иR23 (от младшего байта (LSB) к старшему (MSB)).