Хелпикс

Главная

Контакты

Случайная статья





PORTD = 0xff;. PORTD = 0x00;. PORTD |= 1<<3;. PORTD &= ~(1<<4);



PORTD = 0xff;

А установить " 0" на всех выводах порта D можно так.

PORTD = 0x00;

К каждому биту регистров PORTx можно обращаться и по отдельности так же, как в случае с регистрами DDRx.

Например, команда

PORTD |= 1< < 3;

установит " 1" (сигнал высокого уровня) на выводе PD3.

Команда

PORTD & = ~(1< < 4);

установит " 0" (сигнал низкого уровня) на выводе PD4.

В AVR GCC сдвиг можно осуществлять и с помощью функции _BV(), которая выполняет поразрядный сдвиг и вставляет результат в компилируемый код.

В случае использования функции _BV() две предыдущие команды будут выглядеть следующим образом.

PORTD |= _BV(PD3); // установить " 1" на линии 3 порта D

PORTD & = ~_BV(PD4); // установить " 0" на линии 4 порта D

 

В микроконтроллерах AVR каждому параллельному порту ввода/вывода поставлен в соответствие также регистр PINx. PINx является регистром выводов порта и в отличие от регистров DDRx и PORTx доступен только для чтения. PINx позволяет считывать входные данные порта на внутреннюю шину микроконтроллера. Об этом регистре мы поговорим чуть позже.

 

 

 

Теперь попробуем написать несколько простых программ для лучшего понимания принципа работы с портами микроконтроллера.

Первые наши программы будут состоять всего из нескольких строк, и в их задачу будет входить зажигание светодиода, подключенного к микроконтроллеру.

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

Рисунок 1 Рисунок 2

 

В зависимости от способа подключения светодиод будет загораться либо от сигнала высокого уровня, подаваемого на вывод PD1 микроконтроллера, как в первом случае, либо от сигнала низкого уровня в случае подключения, изображенного на втором рисунке.

 

 

/*************************************************************************

ПРИМЕР ВКЛЮЧЕНИЯ СВЕТОДИОДА СИГНАЛОМ ВЫСОКОГО УРОВНЯ

Пример подключения на рисунке 1

**************************************************************************/

 

#include < avr/io. h>   

int main( void ) { // начало основной программы

DDRD = 0xff;    // все выводы порта D сконфигурировать как выходы

PORTD |= _BV(PD1); // установить " 1" (высокий уровень) на выводе PD1

}              // закрывающая скобка основной программы

 

 

 

 


 

/***********************************************************************

ПРИМЕР ВКЛЮЧЕНИЯ СВЕТОДИОДА СИГНАЛОМ НИЗКОГО УРОВНЯ

Пример подключения на рисунке 2

************************************************************************/

 

#include < avr/io. h>

  

int main( void ) { // начало основной программы

DDRD = 0xff;    // все выводы порта D сконфигурировать как выходы

PORTD & = ~_BV(PD1); // установить " 0" (низкий уровень) на выводе PD1

}              // закрывающая скобка основной программы

 

 

 

 

Теперь попробуем мигнуть светодиодом, подключенным так, как это изображено на левом рисунке. Для этого используем функцию задержки _delay_ms().

Функция _delay_ms() формирует задержку в зависимости от передаваемого ей аргумента, выраженного в миллисекундах (в одной секунде 1000 миллисекунд). Максимальная задержка может достигать 262. 14 миллисекунд. Если пользователь передаст функции значение более 262. 14, то произойдет автоматическое уменьшение разрешения до 1/10 миллисекунды, что обеспечивает задержки до 6. 5535 секунд. (О формировании более длительных задержек можно прочитать в статье " Циклы в языке Си. Формирование задержки". )

Функция _delay_ms() содержится в файле delay. h, поэтому нам будет необходимо подключить этот файл к программе. Кроме того, для нормальной работы этой функции необходимо указать частоту, на которой работает микроконтроллер, в герцах.

 

 

/*************************************

ПРИМЕР МИГАНИЯ СВЕТОДИОДОМ

Пример подключения на рисунке 1

**************************************/

 

#define F_CPU 1000000UL // указываем частоту в герцах

 

#include < avr/io. h>

#include < util/delay. h>

 

int main( void ) { // начало основной программы

  

DDRD = 0xff;    // все выводы порта D сконфигурировать как выходы

 

PORTD |= _BV(PD1); // установить " 1" (высокий уровень) на выводе PD1,

                  //зажечь светодиод

 

_delay_ms(500); // ждем 0. 5 сек.

 

PORTD & = ~_BV(PD1); // установить " 0" (низкий уровень) на выводе PD1,

                  //погасить светодиод

 

_delay_ms(500); // ждем 0. 5 сек.

 

PORTD |= _BV(PD1); // установить " 1" (высокий уровень) на выводе PD1,

                  //зажечь светодиод

 

_delay_ms(500); // ждем 0. 5 сек.

 

PORTD & = ~_BV(PD1); // установить " 0" (низкий уровень) на выводе PD1,

                  //погасить светодиод

 

}              // закрывающая скобка основной программы

 

 

 

Серия миганий светодиодом будет очень короткой. Для того чтобы сделать мигание непрерывным, можно организовать бесконечный цикл с помощью оператора безусловного перехода " goto". Оператор goto осуществляет переход к месту программы, обозначенному меткой. Имя метки не должно содержать пробелов. После имени метки ставится знак двоеточия. Между именем метки и двоеточием не должно быть пробелов.

 

 

/*******************************************************

ПРИМЕР БЕСКОНЕЧНОГО МИГАНИЯ СВЕТОДИОДОМ

Пример подключения на рисунке 1

********************************************************/

 

#define F_CPU 1000000UL // указываем частоту в герцах

 

#include < avr/io. h>

#include < util/delay. h>

 

int main( void ) { // начало основной программы

  

DDRD = 0xff;    // все выводы порта D сконфигурировать как выходы

 

start:             // метка для команды goto start

 

PORTD |= _BV(PD1); // установить " 1" (высокий уровень) на выводе PD1,

                  //зажечь светодиод

 

_delay_ms(250); // ждем 0. 25 сек.

 

PORTD & = ~_BV(PD1); // установить " 0" (низкий уровень) на выводе PD1,

                  //погасить светодиод

 

_delay_ms(250); // ждем 0. 25 сек.

 

goto start;        // перейти к метке start

 

}              // закрывающая скобка основной программы

 

Циклы в языке программирования Си. Цикл " для". Цикл " пока". Принудительное прерывание цикла. Бесконечные циклы. Вложенные циклы. Формирование временной задержки. Для того чтобы много раз повторить какую-либо последовательность действий, применяют алгоритмические конструкции, которые называются циклами. Саму последовательность действий при этом называют телом цикла. Различают следующие разновидности циклов: цикл " для" (цикл со счетчиком) и цикл " пока" (цикл с условием).
Цикл " для"



Цикл " для " используют, когда заранее известно количество повторений.

У такого цикла есть " счетчик повторений ", или " переменная цикла ", которая должна быть предварительно объявлена.


   int i;

 

   for (i = a; i < b; i = i + c)

   {

   // тело_цикла

   }


Тело цикла повторяется столько раз, сколько значений приобретает переменная цикла i от своего начального значения, задаваемого конструкцией присваивания i = a, до конечного, задаваемого условием i < b. Изменение переменной i задается конструкцией присваивания вида i = i + c (также могут быть использованы инкремент i++ или декремент i-- ). При i = b цикл заканчивается и выполняется оператор, следующий за закрывающей скобкой цикла.

Пример:


   int i;

 

   for (i = 1; i < = 5; i++)

   {

   // тело_цикла

   }


На первом шаге цикла переменная i будет равна 1, перед вторым шагом она увеличится на 1 в результате декремента ( i++ ) и станет равной 2. На третьем шаге цикла i примет значение 3. И так до тех пор, пока на пятом шаге цикла она не станет равной 5. В результате следующей операции i++ переменная цикла примет значение 6, но условие i < = 5 уже не будет истинным, и цикл завершится. Таким образом, тело цикла будет выполнено 5 раз.

Существует возможность объявлять переменную цикла непосредственно в его оглавлении:


   for ( int i = 0; i < 100; i++)

   {

   // тело_цикла

   }


Но на первом этапе изучения языка Си лучше объявлять переменные отдельно.

Рассмотрим пример мигания светодиодом 10 раз с помощью цикла " для".

Рисунок 1




 

/******************************************

ПРИМЕР МИГАНИЯ СВЕТОДИОДОМ 10 РАЗ

Пример подключения светодиода на рисунке 1

*******************************************/

 

#define F_CPU 1000000UL // указываем частоту в герцах

 

#include < avr/io. h>

#include < util/delay. h>

 

int main( void ) { // начало основной программы

  

int i;          // объявляем переменную i

 

DDRD = 0xff;    // все выводы порта D сконфигурировать как выходы

 

 

    for (i = 1; i < = 10; i++) // цикл " для", повторяющийся 10 раз

    {

 

        PORTD |= _BV(PD1); // установить " 1" (высокий уровень) на выводе PD1,

                        //зажечь светодиод

 

        _delay_ms(250); // ждем 0. 25 сек.

 

        PORTD & = ~_BV(PD1); // установить " 0" (низкий уровень) на выводе PD1,

                        //погасить светодиод

 

        _delay_ms(250); // ждем 0. 25 сек.

 

    } // закрывающая скобка цикла

 

 

} // закрывающая скобка основной программы



Цикл " пока"



Цикл " пока ", по-другому называемый циклом с условием, повторяется, пока истинно условие цикла.


   while (условие)

   {

   // тело_цикла

   }


Циклы с условием чаще всего используются, когда заранее не известно количество повторений и цикл должен работать до тех пор, пока выполняется условие.

Чтобы цикл завершился, в теле цикла должна меняться какая-либо переменная, от которой зависит истинность условия повторений.

Пример:


   int x;

 

   x = 50;

 

   while (x > 0)

   {

   x = x - 1;

   }


В даном примере тело цикла будет повторяться 50 раз, до тех пор пока переменная x будет больше нуля. На каждом шаге цикла x будет уменьшаться на 1. Когда x станет равным нулю, цикл прекратится.

Оператор break



Оператор break позволяет прервать выполнение тела цикла (при дополнительных условиях).

Для того чтобы воспользоваться этим оператором, необходимо просто вставить строчку


   break;


в том месте цикла, где необходимо организовать его прерывание.

Бесконечные циклы



Организовать бесконечный цикл можно как с помощью цикла " для ", так и с помощью цикла " пока "


   for (;; )

   {

   // тело_цикла

   }


или


   while (1)

   {

   // тело_цикла

   }


Единственный способ выйти из таких циклов - это сделать break (при каком-либо условии) в теле цикла.

Вложенные циклы



Один цикл повторения может находиться внутри другого цикла. При использовании вложенных циклов следует соблюдать простое правило: один цикл внутри другого должен находиться так же, как одна матрешка внутри другой матрешки.

Рассмотрим пример двух вложенных друг в друга циклов " для". Тело вложенного цикла в общей сложности будет повторено 200 раз.


unsigned short i, j; // объявляем переменные

 

 

         for (i = 0; i < 20; i++) // основной цикл

         {

                for (j = 0; j < 10; j++) // вложенный цикл

                {

                         // тело вложенного цикла

                }

         }

 

Формирование задержки



С помощью циклов можно формировать временн ы е задержки большой длительности. Рассмотрим пример многократного повторения функции _delay_ms().


unsigned short i; // объявляем переменную для цикла

 

         for (i = 0; i < 600; i++) // цикл " для", повторяющийся 600 раз

         {

               _delay_ms(1000); // ждем 1 сек.

         }


Данный пример реализует задержку длительностью 10 минут.

Такую конструкцию можно применять в тех случаях, когда в ходе работы программы необходимы длительные временные задержки (до 1092. 25 минут). Для реализации еще более длительных задержек тип переменной i может быть объявлен как unsigned long.




 



  

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