Си для микроконтроллеров и чайников. Часть 4. Функции.. Раздел: Начинающим.

Eugene's MCU

Пятница, 04.10.2013, 13:36

Главная | | Мой профиль | Выход | RSS
Меню сайта
Категории каталога
Рекламный блок





Рекомендовать этот сайт:

Главная » Статьи » » Начинающим


Си для микроконтроллеров и чайников. Часть 4. Функции.
§ > Назначение функций.
       
     Ещё древние программисты обратили своё внимание на один занимательный факт – зачастую программа вынуждена несколько раз выполнять ровно одну и ту же последовательность действий. Именно тогда родилась идея при достаточно большом наборе таких действий и их повторов, с целью экономии программной памяти, оформлять их в виде отдельной группы, а затем при необходимости просто отправлять программу на её выполнение. Такой обособленный кусок кода в Си как раз и называется функцией. Само название термина "функция” исконно отражает другое свойство некоторых функций – способность (подобно функциям математическим) преобразовывать по заданному алгоритму некие входные данные. Но этом немного позже.
 
     Другое назначение функции, полностью отражющее её название – это выделение в отдельную группу действий связанных одной общей целью, например, функция инициализации портов или функция опроса клавиатуры. Это и есть одно из дополнительных предназначений функции.   
     Такие функции могут вызываться программой только один раз. Зачем же тогда они нужны? Для обоснования такого подхода в литературе часто приводится фраза неизвестного, но по всей видимости, очень авторитетного древнеримского программиста: " Разделяй и властвуй!”. И действительно, программа, оформленная в виде целевых функциональных блоков гораздо проще для понимания, отладки и последующей модификации, чем набор отдельных, разрозненных по назначению кусков кода. 
     Обобщая сказанное, можно сформулировать формальные предпосылки к созданию функций в программе, это:
   
     1. Наличие одинаковых, достаточно больших и многократно повторяющихся наборов действий.
     2. Желание структурировать программу в виде отдельных блоков с общим функциональным назначением.

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

§ > Структура и оформление функций.
  
     В любой функции структурно легко выделить две составные части: заголовок и тело функции.
     Заголовок это самая первая строчка любой функции вида:
       
  
     Тип выходной переменной Имя функции (Типы входных переменных и их имена через запятую)
  
     
     Временно опустим рассмотрение содержимого заголовка до и после имени и рассмотрим функции, которые не обрабатывают никаких данных. Они предназначены только для выполнения определённых действий. В заголовках таких функций нужно указать названия пустого типа – void (англ. вакуум, пустота):
       
  
     void имя функции (void)
  
    
     В качестве имени можно использовать любое слово, отражающее смысл выполняемых функцией действий, лишь бы оно не начиналось с цифры. Уже сейчас мы можем вызвать выполнение нашей функции из любого места программы. Для этого нужно записать имя функции, круглые скобки и символ точки с запятой. Например, функцию с заголовком:
     void initialization (void)
     можно вызвать так: 
      
  
     initialization ();
  
  
     Тело функции это набор команд расположенный между первой открывающейся фигурной скобкой после заголовка и соответствующей ей закрывающейся фигурной скобкой. Пояснение: наборы действий внутри фигурных скобок в Си принято называть блоками. Они логически связывают несколько одиночных действий в одно сложное, которое либо полностью выполняется, либо полностью игнорируется в зависимости от контекста программы. В данном случае тело функции представляет собой блок команд, которые функция обязана выполнить  от начала и до конца. Таким образом, программа, встретив переход на функцию, выполнит содержимое блока и по последней закрывающей скобке вернётся туда, откуда была вызвана. 
     Например, функция: 
         
  
     void initialization (void)
     {
          DDRA=0xFF; // PORTA на выход.
          DDRB|=(1<<0)| (1<<3)| (1<<4); // PB0, PB3, PB4 на выход.
          DDRC=0xF0; // Старшая тетрада  PORTC на выход.
     }
  
   
проинициализировав направление выводов портов A, B и С, вернётся в следующую после её вызова строчку.
     Для начала также важно знать, что тексте программы каждая функция должна быть расположена отдельно, то есть одна функция не может находиться внутри другой или частично накладываться на неё.
   
§ > Обработка параметров функцией.
  
     Всё функции могут обрабатывать и изменять значения специализированных регистров микроконтроллера и так называемых глобальных переменных, то есть тех, которые объявлены пользователем в самом начале программы вне каких либо функций. Помимо этого имеется возможность передавать данные в функцию для обработки непосредственно в момент её вызова. Это просто удобно и ничего больше. 
     Эти данные называются параметрами, передаваемыми функции. Они должны быть перечислены через запятую вместе с их типами в заголовке функции, внутри круглых скобок после её имени:      
  
  
     void initUart (char FrameLength, char StopBit)
  
   
     Такое оформление заголовка будет означать, что функция способна принимать в качестве параметров два числа типа char с именами FrameLength и StopBit. Теперь при вызове функции компилятор не позволит оставить круглые скобки пустыми и потребует передачи конкретных значений, через запятую, например:   
      
  
     initUart (8, 2);
  
     
     После этого внутри функции переменным с именами FrameLength и StopBit присвоятся конкретные значении 8 и 2, которые можно использовать, например, для настройки длинны посылки модуля UART и количества его стоп-битов:        
  
  
     void initUart (char FrameLength, char StopBit)
     {
           if (FrameLength==8) UCSR0C|=((1<<1)|(1<<2));
           if (StopBit==2) UCSR0C|=(1<<3);
     }
  
   
§ > Специализированные функции.
 
     Мы рассмотрели функции, задаваемые самим пользователем. Помимо них в любой программе присутствуют функции, которые выполняют специализированные задачи и должны быть оформлены по особым правилам. 
     Самая главная функция такого рода, как это видно и самого её названия это функция main. Она характеризуется тем, что выполнение передаётся на неё самим микроконтроллером при подаче питания или после перезагрузки, то есть, именно с неё и начинается работа любой программы. Еще одно свойство функции main состоит в том, что при её выполнении до конца программа автоматически перейдёт на её же начало, то есть она выполняется по циклу, если внутри её самим пользователем специально не был организован бесконечный цикл.
     Ещё один вариант системных функций – обработчики прерываний. Их так же невозможно вызвать программно. Микроконтроллер самостоятельно передаёт управление на них в случае возникновения особых аппаратных состояний – условий вызова прерываний. Подробнее об этом читайте в следующей главе.
  


При использовании материалов сайта ссылка на данный источник обязательна.

Категория: Начинающим | Добавил: eugenemcu (13.11.2010) | Автор:

Просмотров: 12435 | Рейтинг: 4.9/8 |
Всего комментариев: 0
Статистика

Наш магазин




Какую среду разработки Вы используете?

[ Результаты · Архив опросов ]
Всего ответов: 1328



Им нужна Ваша помощь: