Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование микроконтроллеров AVR. Учебное пособие.pdf
X
- •ПРЕДИСЛОВИЕ
- •1. АРХИТЕКТУРА МИКРОКОНТРОЛЛЕРОВ AVR СЕМЕЙСТВА MEGA
- •1.1. Регистры микроконтроллера
- •1.2. Порты ввода/вывода
- •1.3. Периферийные устройства
- •1.3.1. Таймеры/счетчики
- •1.3.2. Аналого-цифровой преобразователь
- •2. ОБЩИЕ СВЕДЕНИЯ О ЯЗЫКЕ С
- •2.1. Вводные понятия в языке С
- •2.2. Правила приведения типов компилятора Code Vision AVR
- •2.3. Структура программы на языке С
- •3. СОЗДАНИЕ ПРОЕКТА С ИСПОЛЬЗОВАНИЕМ МАСТЕРА-ПОСТРОИТЕЛЯ
- •3.1. Выбор общих параметров проекта
- •3.1.1. Настройка портов
- •3.1.2. Настройка таймеров
- •3.1.3. Настройка параметров АЦП
- •3.1.4. Настройка параметров ЖКИ
- •3.2. Генерации программы
- •4. ПРИМЕНЕНИЕ МИКРОКОНТРОЛЛЕРОВ AVR ПРИ РАЗРАБОТКЕ ИЗМЕРИТЕЛЬНЫХ СИСТЕМ
- •ЗАКЛЮЧЕНИЕ
- •БИБЛИОГРАФИЧЕСКИЙ СПИСОК

Байту данных в языке С соответствует тип 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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
