Rambler's Top100
Sources.RU Magazine
Декабрь 2004

· От редактора

· Создание сайта

· Программирование на IAR

· Обзор UPS

· mIRC + Delphi = WinAmp Plugin

· Многоязыковое приложение

· Передача файлов через сокеты

· H.323: Обзор архитектуры

· Введение в KDevelop

· Linux Live CD - Основы

· Microsoft Speech API — Синтез речи

 
· On-line версия выпуска

Программирование микроконтроллеров на Си. Программирование в среде IAR Embedded Workbench for Microchip PICmicro 16/17.

Автор: bizar

Немного о IAR

Как и во всех статьях по программированию начинают с самого лёгкого, например простой программой "Hello world" так и в моей первой статьи я начну с простого, работа со светодиодами. Но для начала я вас дорогие читатели посвищу в среду IAR. IAR - это компилятор для микропроцессора с Гарвардской архитектурой (два адресных пространства - для кода и данных) и для более эффективной работы в ограниченных условиях микроконтроллеров. Также следует отметить возможность описывать внешние события и управлять средой и симулятором с помощью специального скриптового языка. Также очень хорошо реализована отладка Си-приложений - то есть удобно просматривать структуры данных, как глобальные, так и локальные, и управлять симулятором на основе структуры Си-кода. Скачать IAR можнос сайта производителя www.iar.com

Установка и настройка IAR для Pic

Скачиваем пакет IAR Embedded Workbench for Microchip PICmicro 16/17 и устанавливаем его. Открываем IAR Embedded Workbench смотрите ниже внешний вид программы.

Нажимаем меню File->New..., выбираем source/text, вставляем исходник, нажимаем File->SaveAs..., вводим имя в виде имя_файла.c , нажимаем Сохранить. Если в проекте в разделе Common Sources этот файл не появился, то нажимаем меню Project->Files..., выбираем этот файл, нажимаем Add, затем Done. Файл в проекте. Дальше - компиляция. В Project->Options в General нужно указать путь к "Процессор сетап файл" pic16f84. (ну или тот микроконтроллер с которым вы работаете.) IAR должно выдать что-то типа:


Rebuilding target Debug...

tit.c

Linking...

Первые программы

Для начало составим схему с 10 светодиодами:

А вот сам исходник программы:
#include 

/* подпрограмма временной задержки */

void tick(void)

                     {

                     unsigned int p;

                     for ( p = 0xffff; p!=0; p--);

                     for ( p = 0xffff; p!=0; p--);

                     for ( p = 0xffff; p!=0; p--);

                     for ( p = 0xffff; p!=0; p--);

                    } 



void TransmitBitDelay(void)

                                              {

                                              for (int i= 10; i!=0; i--)

                                              for (int j= 10; j!=0; j--);

                                              }



void TransmitByte(char Symbol)

                                                    {

                                                    PORTA &= 0xfe; //передаем стартовый бит

                                                    count = 8;// счетчик передаваемых бит данных

                                                    do

                                                       {

                                                        TransmitBitDelay(); // задержка перед передачей следующего бита

                                                        PORTA ^= (~Symbol) & 1; // выдаем очередной бит в COM

                                                        Symbol >>= 1; //следующий бит

                                                        count--;

                                                       }

                                                     while (count >0);

                                                     TransmitBitDelay(); // задержка перед передачей следующего бита

                                                     PORTA |= 1; //передаем стоповый бит 

                                                    } 



main ()

          {

            TRISB = 4|8;  /* RB2 - RB3 настраиваем на вход */

            PORTB = 0xfc; /* RB0 - RB1 настраиваем на вывод*/

            while(1) 

                        {

                         do 

                             {

 /* НЕБОЛЬШОЙ ПРОМЕЖУТОК ВРЕМЕНИ, "не будем опрашивать кнопки слишком часто" */

                               tick();

                              Keys = (~PORTB) & (4|8); /* состояние кнопок на RB2-RB3. Ждёт нажатия */

                            } 

                         Keys >>= 1;

                         while(PORTB & Bit(0)); /* если установлен бит 0, значит нажата кнопка на RB2 */

                         while(1)

                       {

            void TransmitByte(34) /* посылаем 34 */

          }

 

while(PORTB & Bit(1)); /* если установлен бит 1, значит нажата кнопка на RB3 */

 while(1)

              {

               void TransmitByte(35) /* посылаем 35 */

              }

         }

 }

Далее для разнообразия подкину исходник Бегущего огня, то есть светодиоды будут загораться по очереди. Все вопросы которые у вас возникнут задавать на форуме сайта где размещена статья или почитайте в ссылке которая указана ниже, там сто пудов найдёте ответ на свой вопрос.

Бегущий огонь:

#include 

/* подпрограмма временной задержки */

void tick(void) {

   unsigned int i;

   for ( i = 0xffff; i!=0; i--);

   for ( i = 0xffff; i!=0; i--);

   for ( i = 0xffff; i!=0; i--);

   for ( i = 0xffff; i!=0; i--);

}

/* Эта подпрограмма зажигает нулем светодиод на определенном выводе */

void FlashPin(unsigned char pin_code){

   switch(pin_code) {

      case 0:

      case 1:

      case 2:

      case 3:

      case 4:

      case 5:

      case 6:

      case 7:

         /* 0-7 - выводы порта B */

         PORTB &= 0xfe<>= 2; // нормализуем(сдвигаем). Теперь:

                  //  бит 0 - RA2,

                  //  бит 1 - RA3,

                  //  бит 2 - RA4.

      counter = Keys;

      direction = -1;   /* направление "движения" */

      for( i=1000 ; i != 0 ; i-- ) {

         if( counter == Keys ) {

            // прошли круг - начанаем двигаться в другую сторону

            direction = -direction;

         }

         TurnOffPins();        /* гасим все светодиоды */

         FlashPin(counter);    /* зажигаем определенный */

         counter += direction; /* в следующий раз будем зажигать другой */

         if( counter == 0xff ) {

            /* закольцовываем "снизу" */

            counter = 9;

         }

         if( counter == 10 ) {

            /* закольцовываем "сверху" */

            counter = 0;

         }

         tick();  /* пауза - чтобы светодиод погорел немного */

      }

   } 

}

А вот и сама ссылка где родилась эта идея: http://forum.sources.ru/index.php?showtopic=42431&st=0. Теперь я вам растолкую как указывать на вход или выход (выбирать нужную ногу) чтобы было понятней вот строчка исходника:

PORTA &= 0xfe

Что за 0xfe? Это и есть адрес нужной ноги микроконтроллера. Объясню вам на примере микроконтроллера pic16f84

RB, RA это и есть обозначение портов для настройки ввода/вывода. В исходнике они обозначаются PORTA (это обозначение всех портов RA), PORTB (это обозначение портов RB). Далее идёт номер порта 0xfe это номер порта RB0. Переводим у 0xfe, fe из шестнадцатеричной в двоичную систему исчисления это будет 11111110 считаем число всех цифр это будет восьмизначное число и у нашего микроконтроллера восемь портов ввода/вывода RB0-RB7 значит это число (fe) относиться к порту RB так как у RA всего пять портов RA0-RA4. Теперь смотрим нолик у числа 11111110 находиться в начале числа вот это и говорит что это первый порт на RB, не трудно догадаться что это RB0. Если бы нолик стоял вторым числом 11111101 то это был бы порт RB1 и т. д. Также у портов RA.

Для портов RA:

PORTA = 0x1f;//записываем во все разряды PORTB единицы (11111)

PORTA = 0x1е;// записываем в RB0 0, в остальные разряды 1 (11110)

PORTA = 0x1d;// записываем в RB1 0, в остальные разряды 1 (11101)

PORTA = 0xb;// записываем в RB2 0, в остальные разряды 1 (11011)

PORTA = 0x17;// записываем в RB3 0, в остальные разряды 1 (10111)

PORTA = 0xf;// записываем в RB4 0, в остальные разряды 1 (01111)

Для портов RB:

PORTB = 0xff;//записываем во все разряды PORTB единицы (11111111)

PORTB = 0xfе;// записываем в RB0 0, в остальные разряды 1 (11111110)

PORTB = 0xfd;// записываем в RB1 0, в остальные разряды 1 (11111101)

PORTB = 0xfb;// записываем в RB2 0, в остальные разряды 1 (11111011)

PORTB = 0xf7;// записываем в RB3 0, в остальные разряды 1 (11110111)

PORTB = 0xef;// записываем в RB4 0, в остальные разряды 1 (11101111)

PORTB = 0xdf;// записываем в RB5 0, в остальные разряды 1 (11011111)

PORTB = 0xbf;// записываем в RB6 0, в остальные разряды 1 (10111111)

PORTB = 0x7f;// записываем в RB7 0, в остальные разряды 1 (01111111)

В написании статьи огромное участие принимал: trainer и potor.