Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование микроконтроллеров AVR. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
Байту данных в языке С соответствует тип char. Он получил свое название от английского слова character, поскольку чаще всего использует­ся в программах для хранения символов (то есть их ASCII-кодов). Тем не менее, с его помощью можно обращаться и к небольшим числам в диапа­зоне от –128 до +127.
Переменная – это именованная величина определенного типа, кото­рая может изменяться в ходе выполнения программы. Для объявления пе­ременных (т. е. выделения для них памяти) в программе на С используется следующая конструкция:
тип_данных идентификатор1, идентификтор2, ….., идентификаторN;
где тип_данных – тип данных, которые можно хранить в переменной, от него зависит количество выделяемой для переменной памяти.
Например:
int i; // объявление целочисленной переменной i
int c1, c2; // объявление двух символьных переменных c1 и c2
Для доступа к переменной в программе используется ее идентифика­тор (обязательно после объявления переменной). Значения, присваивае­мые переменной, должны соответствовать ей по типу данных или прави­лам приведения типов.
Глобальные переменные – переменные с глобальной областью ви­димости, объявляемые вне какой-либо функции и доступные в любом ме­сте программы.
Локальные переменные – переменные с локальной областью види­мости, объявляемые в начале функций и доступные только в той функции, в которой они объявлены.
Приведение типов – принудительное преобразование значения одно- го типа к другому, совместимому с исходным. Это важно при выполнении арифметических операций, когда полученные значения могут выходить за допустимые пределы.
31
Приведение типов бывает явным и неявным. Неявное приведение ти-
пов используется в операторах присваивания, когда компилятор сам вы­полняет необходимые преобразования без участия программиста.

2.2. ПРАВИЛА ПРИВЕДЕНИЯ ТИПОВ КОМПИЛЯТОРА CODE VISION AVR

Если в выражениях встречаются операнды различных типов, то ком-
пилятор преобразовывает их к общему типу в порядке приоритета:
− если один из операндов типа float (плавающая точка), то другой опе-
ранд преобразовывается в этот же тип;
− если один из операндов типа long int (длинное целое) или unsigned long
(беззнаковое длинное), то другой операнд преобразовывается в этот же тип;
− если один из операндов типа int (целое) или unsigned int (беззнако-
вое целое), то другой операнд преобразовывается в этот же тип.
Типы char (символьный) и unsigned char (беззнаковый символьный)
получают самый низкий приоритет.
Таким образом, при вычислении выражений операнды преобразуются
к типу того операнда, который имеет наибольший размер.
Пример:
// объявление переменных
unsigned char ch; // объявление символьной переменной ch unsigned long long_int, result; // объявление длинных целых // переменных long_int и result int int_l, int_2; // объявление целых переменных int_1 и int_2 // определение длинной целой переменной result result=ch* (long_int + int__l/int__2); // присваиваем переменной result // значение выражения
/* При выполнении оператора присваивания операнды ch, int_l и int_2 будут преобразованы к типу unsigned long. Результат всего выражения бу­дет иметь тип unsigned long */
32
Приоритеты преобразования типов можно изменить. В любом выра-
1
Выражение
0
Справа налево
жении может быть осуществлено явное преобразование типов. Для явного приведения типа некоторой переменной перед ней следует указать в круг­лых скобках имя нового типа.
Пример:
int x; int y = 200; char c = 10; x = (int)с*10 + y; // переменная “с” приведена к типу int
Оператор – символ, указывающий компилятору, какие действия вы-
полнить над операндами.
Операторы, соединяющие операнды, представляют собой выраже-
ния. Выражения могут быть заключены в круглые скобки и отделяются друг от друга символом точки с запятой “;”.
В языке С операторы с высшими приоритетами выполняются первы-
ми. Наивысшим является приоритет, равный 1. Приоритеты и порядок операторов приведены в табл. 2.2 [3].
Таблица 2.2
Приоритеты и порядок операторов языка С
Приоритет Типы операторов Обозначение оператора Порядок выполнения
[]
->
2 Унарные -
~!
Слева направо
*
&
++
--
sizeof
type (приведение типов)
33
Окончание табл. 2.2
3
Мультипликативные
*
Слева направо
5
Сдвиг
>>
Слева направо
6
Отношение
<
>=
Слева направо
8
Побитное И
&
Слева направо
9
Побитное
^
Слева направо
10
Побитное ИЛИ
|
Слева направо
12
Логическое ИЛИ
||
Слева направо
13
Условный оператор
?:
Слева направо
14
Простое
=
^=
Справа налево
15
Последовательное
,
Слева направо
Приоритет Типы операторов Обозначение оператора Порядок выполнения
/
%
4 Аддитивные +
-
<<
>
<=
7 Отношение
(равенство)
исключающее ИЛИ
11 Логическое И && Слева направо
==
!=
Слева направо
Слева направо
Первой выполняется операция побитового логического отрицания (–) как имеющая самый высокий приоритет. После её выполнения все 1 в пе-
и составное присваивание
вычисление
*=
/=
%=
+=
-=
&=
|= >>= <<=
34
ременной х заменятся на 0, а 0 – на 1 (унарная операция). Затем выполня-
x = x + 1;
добавить 1
x++; или ++x;
x = x - 1;
вычесть 1
x--; или --x;
x = x + y;
прибавить y
x += y;
x = x - y;
вычесть y
x -= y;
x = x * y;
умножить на y
x *= y;
x = x / y;
поделить на y
x /= y;
x = x % y;
остаток от деления
x %= y;
x--;
вычесть 1
x -= 1;
x++;
добавить 1
x += 1;
ется операция побитного ИЛИ (|) полученного значения (0b00001111) с числом 0хАА = 0b10101010. При этом каждый бит первого операнда сравнивается с соответствующим битом второго операнда.
Если любой (или оба) из сравниваемых битов равен 1, то соответ-
ствующий бит результата устанавливается в 1, в противном случае – в 0 (бинарная операция). Последней выполняется операция побитного ИЛИ с присваиванием (&=) значения у и результата предыдущих операций (0b10101111). При этом каждый бит первого операнда сравнивается с со­ответствующим битом второго операнда. Если оба сравниваемых бита 1, то соответствующий бит результата устанавливается в 1, в противном слу­чае – в 0 (бинарная операция). Полученное значение (0b00101100) присва­ивается переменной у.
Результат: у = 0b00101100 */ С оператором присваивания используются сокращенные формы,
представленные в табл. 2.3.
Таблица 2.3
Сокращенные формы с применением оператора присваивания
Полная форма Смысл Сокращенная форма
35
В языке С есть операции, которые изменяют значение переменной
и без оператора присваивания: инкремент (++) и декремент (– –), которые удобно использовать для изменения значений различных переменных счетчиков, однако важно, где они применяются – перед переменной или после переменной:
a = 4; b = 7; a = b++;
/* взять значение переменной b, присвоить его переменной a, затем добавить 1 к переменной b и сохранить результат в b. В результате a будет содержать число 7, b будет содержать число */
Функция представляет собой «контейнер», содержащий некоторый фрагмент программного кода. Использование функций упрощает написа­ние и отладку программ, поскольку в них удобно размещать повторяющи­еся группы операторов. Любая программа на языке С содержит главную функцию под названием main(), эта функция при запуске программы вы­полняется первой.
Синтаксис определения функции:
тип_возвращаемого_значения имя_функции (список_параметров)
{
// тело функции
}
В качестве типа возвращаемого значения может использоваться клю­чевое слово void (пустота). Это означает, что функция не возвращает ника­кого значения. Функцию вызывают по ее имени с указанием в круглых скобках перечня передаваемых параметров (если их нет, то в круглых скобках ничего не указывается).
36
Пример: void function1(int n, char c) { …. } int functon2() { …. }
Параметры функции – это список идентификаторов, которые пред-
ставляют собой локальные переменные внутри функции. Вместо них под­ставляются соответствующие значения, указанные при вызове функции.
Значения передаются в функцию двумя способами – по ссылке и по
значению. При передаче данных по значению переданные данные факти­чески не изменяются, а просто копируются в параметры. Передача данных по ссылке осуществляется с помощью указателей, при этом переданные данные изменяются.
Функции могут вызываться из других функций. Операторы ветвления используются для выполнения того или иного
блока кода в зависимости от некоторого условия. К таким операторам на языке С относятся if-else и switch-case:
if (условное_выражение) блок_кода_1; else блок_кода_2;
Если условное выражение истинно, то выполняется блок кода 1, в про­тивном случае – блок кода 2. При этом в качестве блока кода 2 допускается использовать последовательность операторов else-if:
if (выражение1) блок_кода_1;
else if (выражение2) блок_кода_2;
else if (выражение3) блок_кода_3;
else блок_кода_N;
37
В данном случае каждое выражение будет вычисляться поочередно до тех пор, пока не будет найдено выражение, давшее истинный результат. Если же результаты вычислений всех выражений окажутся ложными, то будет выполнен блок кода N. Если выражение в первой строке будет ис­тинным, остальные операторы будут пропущены.
Язык С позволяет вместо оператора if-else использовать условные
выражения. Так, конструкцию вида
if(условие) блок_кода_1; elseблок_кода_2;
можно заменить следующим условным выражением:
условие ? блок_кода_1 : блок_кода 2;
Например:
{а == 1) ?b= а*3 : b= 0; //Если а=1, то b=а*3, иначе b =0
Оператор switch предназначен для организации выбора из множества различных вариантов, который заключается в проверке совпадения значе­ния данного выражения с одной из заданных констант и соответствующего ветвления.
Синтаксис:
switch (выражение)
{
[объявление]
[case константное-выражение1]: [группа операторов].]
[case константное-выражение2]: [группа операторов 2]
[default: [группа операторов п]]
Выражение, следующее за ключевым словом switch в круглых скоб­ках, может быть любым выражением, допустимым в языке С, значение ко­торого должно быть целым. Значение этого выражения является ключевым для выбора из нескольких вариантов. Тело оператора switch состоит из не­скольких операторов, помеченных ключевым словом case с последующим константным выражением.
38
Массив является составной структурой данных и используется для
представления последовательности однотипных значений:
int digits[10]; // массив из десяти элементов типа int char str[10]; // массив из десяти символов (строка)
Доступ к элементам массива реализуется с помощью индекса (поряд-
кового номера элемента, начиная с 0).
digits[0] = 0; digits[1] = 1; str[0] = 'A'; str[1] = 'B';
Строка в С – это массив типа char. char str[10] = “The line”;
Следует помнить, что реальная длина строки больше на 1, потому что
компилятор неявно завершает строковые литералы символом '\0'.

2.3. СТРУКТУРА ПРОГРАММЫ НА ЯЗЫКЕ С

Ниже приведена общая структура программы на языке С для микро-
контроллеров с комментариями:
– директивы препроцессора; – директива подключения необходимых внешних библиотек:
Внешние библиотеки: // библиотека имен и регистров ATmega8
#include <mega8.h> // библиотека функций ввода-вывода #include <stdio.h> // математическая библиотека #include <math.h>
39
#include <stdlib.h>
// библиотека работы с LCD дисплеем
#asm
.equ __lcd_port=0 x15 ;PO RTC
#endasm
#include < lc d.h>
// библиотека работы с задержками
#include <del ay.h>
Глобальные определения:
// базовое состояние мультиплексора АЦП
#define ADC_VREF_TYPE 0x00
// калибровочные коэффициенты
#define c_u 781/1024 // коэффициент напряжения
#define c_i 5.12/1024 // коэффициент тока
Глобальные переменные:
// структура результатов преобразования АЦП
struct ADCData {
signed long new, prev, filt, prevFilt; // здесь был int
} adcData[2];
// структура сумм мгновенных значений
struct SummData {
unsigned long U, I;
signed long P;
} summData, summCopy;
// структура результатов вычислений
struct ResultData {
float P, U, I, cosFi;
} resultData;
40
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]