Воскресенье, 22.07.2018
Интеллектуальные системы управления
Меню сайта
Категории раздела
Эксперименты [3]
Программирование микроконтроллеров PIC [7]
Программирование микроконтроллеров STM32 [0]
Программирование микроконтроллеров STM8 [0]
Программирование микроконтроллеров AVR [0]
Программирование микроконтроллеров MSP430 [0]
Программирование ПЛИС ALTERA [0]
Облако тегов
Главная » Статьи » Программирование микроконтроллеров » Программирование микроконтроллеров PIC

Пишем программу на Си для микроконтроллера PIC16F877A
Напишем простенькую программу для самого распространенного микроконтроллера фирмы Microchip PIC16F877A. Почему именно PIC16F877A, а не какой нибудь другой? Объясняю. По своему внутреннему устройству этот контроллер сочетает в себе все предыдущие модели, у него "на борту" есть все модули, которые встариваются в другие контроллеры 8-ми битного семейства начиная от PIC10 и заканчивая PIC16. Кроме этого, названия регистров у него такие же как и у других, и на него можно найти руссифицированное описание. Для начинающих это довольно хорошая помощь в освоении программирования микроконтроллеров. Плюс, мне он нравится большим количеством выводов, можно одключить много всяких компонентов и модулей.
Русскую версию даташита вы всегда можете скачать на русском сайте www.microhip.ru, английскую соответственно на анлийском - www.microhip.com. Скачали? Держите его всегда под рукой. Даташит - это описание работы и внутреннего устройства микроконтроллера и если его внимательно читать, то можно избежать ошибок, и неясностей в работе программы. Откроем созданный ранее проект и напечатаем следующий код:


Code
  #include <pic.h>                 // Подключение заголовочного файла
  __CONFIG(0x03F72);           // Установки контроллера 

  void main(void)                   // Главная функция
  {  
      while(1)                         // Главный цикл  
       {
       }   
  }

Вообще-то, я не очень люблю ставить комментарии, что конечно является дурным тоном в программировании, но это потому что при написании кода ты увлечен, весь в процессе, в голове куча мыслей и отвлекшись можно просто потерять основную нить. Для этой статьи я никуда не торопился, а потому все же сделал кое какие записи. Попробуем разобраться.

Code
  #include <pic.h>                 // Подключение заголовочного файла 

Те кто хорошо знаком с синтаксисом языка Си знают что #include это директива компилятора, говорящая ему о необходимости подключения библиотечного файла. Таким файлом у нас является pic.h, он расположен в директории куда был установлен Hi-tech в папке Include. Вообще там куча подобных файлов, но мы указываем главный из них, а дальше все делает программа. По указанному, при создании проекта, названию контроллера MPLAB определяет где и в каком дальше файле искать полное описания и названия его регистров.

Code
  __CONFIG(0x03F72);           // Установки контроллера  

Во второй строке записан так называемый макрос компилятора Hi-tech, в традиционном синтаксисе Си такой команды нет. С помощью нее мы настраиваем некоторые модули контроллера, сами настройки записываются в виде HEX-значения в круглых скобках. Что конкретно означает запись 0x03F72 и как ее получить можно посмотреть в строке "Configuration Bits..." меню "Configure".
 
Если у вас стоит галочка Configuration Bits set in code, то все необходимые настройки наш компилятор берет из макроса  __CONFIG. Если эту галочку снять то будет доступно редактирование полей. При изменении значения поля будет меняться и конечная сумма в столбце Value, ее то мы как раз и запишем в параметр нашего макроса. Что же все таки написано в этой таблице.

  • FOSC - Oscillator Selection bits - Устанавливает тип тактового генератора нашего микроконтоллера, значение HS означает что в нашем случае будет использоваться высокочастотный кварцевый генератор;
  • WDTE - Watchdog Timer Enable bit - Запускает сторожевой таймер служащий, например, для предотвращения зависания микроконтроллера. Пока лучше его отключить, ставим значение Disabled; 
  • PWRTE - Power-up Timer Enable bit - Активирует таймер удерживающий микроконтроллер в состоянии сброса, до тех пор пока напряжение питания не достигнет необходимого уровня. Для предотвращения ложных запусков ставим его в занчение Enabled;
  • BOREN - Brown-out Reset Enable bit - Активирует детектор пониженного напряжения. Если питающее напряжение снижается ниже определнного минимума то микроконтроллер перезагружается. Тоже полезная опция, так же ставим значение Enabled;
  • LVP - Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit - Активирует возможность низковольтного внутрисхемного программирования. Нам пока это не надо так что ставим Disabled;
  • CPD - Data EEPROM Memory Code Protection bit - Установка защиты от считывания кода записанного в память контроллера. Ставим Off, нам эта опция пока не нужна;
  • WRT - Flash Program Memory Write Enable bits - Установка защиты от записи программы во Flash память. Устанавливаем защиту в Off;
  • CP - Flash Program Memory Code Protection bit - Установка защиты от считывания кода записанного во Flash память. Это нам тоже ни к чему, снова Off.

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

Code
  void main(void)                   // Главная функция  

С настройкой покончено. В следующей строке у нас уже знакомая команда, это главная функция программы, так сказать тело программы. Запись void main(void) показывает что данная функция не имеет определенного типа и не возвращает никаких значений. Далее у нас идет открывающая скобка, после которой мы можем написать все что задумали. Я написал следующее:

Code
      while(1)                         // Главный цикл  

В программировании, с помощью такой записи создают бесконечный цикл, который в данном случае ничего не выполняет, заставляя контроллер как бы топтаться на одном месте. В принципе условие цикла можно записать вот так (1=1), но это будет тоже самое.
Итак... Текст программы мы написали, сохранили на всякий случай, теперь компилируем. На панели инструментов нажимаем кнопку "Build All"  и ждем результатов.
Если все прошло успешно то в окне "Output" должно появиться вот такое сообщение, заканчивающееся строкой BUILD SUCCEEDED, а в папке с проектом - несколько новых файлов. Из которых нас в первую очередь интересует файл с расширением "hex". Это и есть наш конечный результат, то ради чего все затевалось - прошивка, ее мы записываем в память микроконтроллера и получаем готовое hand made устройство.
Но программу, которая тупо крутится на одном месте ничего не делая врятли можно назвать громадным достижением, поэтому поехали дальше. Открываем даташит и ищем раздел "Порты ввода/вывода" (в русскоязычном варианте) или I/O Ports (в англоязычном). В первую очередь нас интересуют регистры PORTB и TRISB.
    PORTB - 8-ми битный двунаправленный порт ввода/вывода. Порт это, по сути, совокупность выводов (ног), который является основным средством связи микроконтроллера с внешним миром. Вся информация, которую микроконтроллер передает или принимает проходит через порт.
    TRISB - регистр управления портом, определяет направление каналов порта B. Если в биты регистра TRISB записать "1" то порт B будет настроен как вход. Запись в TRISB - "0" переведет порт B в режим выхода. В принципе все просто. Почему был взят PORTB, а не скажем PORTD или PORTA? От остальных PORTB, если вы внимательно читали даташит, отличается наличием встроенных защитных диодов и подтягивающих резисторов, тоесть сжечь его по неосторожности достаточно сложно, если не сказать - невозможно. Я вообще все мощные элементы (светодиоды, транзисторы и т.д.) стараюсь в первую очередь разместить на этом порту, после него уже идет очередь порта D, порт C использую для связи с другими контроллерами или компьютером, а порт A для каких либо измерений. Продолжим. Немного модифицируем нашу программу, добавим следующие строки перед while(1):

Code
   TRISB = 0b00000000;            // Перевод порта в режим выхода
   PORTB = 0b00000000;           // Присваивание начального значения

С помощью такой вот записи мы перевели все биты (ноги) порта B в режим вывода и принудительно обнулили, записав в PORTB значение по умолчанию. Если с первой операцией все понятно то зачем нужна вторая операция?! После сброса (перезагрузки) значение, которое принимает регистр PORTB может быть каким угодно, поэтому его необходимо обнулить во избежание ложных срабатываний или сразу вывести в начальное положение. Это не является прописной истиной, поэтому данную операцию можно пропустить, но я всегда так делаю и вам советую.
К тому что у нас получилось,  в тело нашего бесконечного цикла, сразу добавим еще одну строчку:

Code
       PORTB++;                       // Увеличение текущего значения порта 

Данная запись увеличивает значение записанное в PORTB на единицу и эквивалентна записи PORTB=PORTB+1. Снова нажимаем кнопку "Build All" и ждем успешного завершения.
Теперь хорошо было бы посмотреть как это все работает, поэтому запускаем PROTEUS (его мы устанавливали в прошлой статье).
И собираем схему как изображено на картинке.
1. Нажимаем кнопку библиотека элементов -  и в открывшемся окне, в списке Category ищем строку Microprocessor ICs, в списке Sub-Category - PIC16 Family, в таблице Results - PIC16F877A.
Нажимаем "OK", после чего возвращаемся в главное окно и кликаем левой клавишей мыши на свободном рабочем поле, элемент вставлен.
2. Тоже самое проделываем для следующих элементов:
  • Конденсатор. Category - Capacitors, Sub-category - Ceramic Disc, Results - CERAMIC22P;
  • Кварцевый генератор.  Category - Miscellaneous, Sub-category - All Sub-category, Results - CRISTAL;
  • Резистор.  Category - Resistors, Sub-category - 0.6W Metal Film, Results - MINRES100R;
  • Светодиод.  Category - Optoelectronics, Sub-category - LEDs, Results - LED-RED (GREEN, BLUE, любого понравившегося цвета);
  • Кнопка.  Category - Switches & Relay, Sub-category - All Sub-category, Results - BUTTON;

Попутно все компоненты добавляются в панель списка элементов "DEVICES", поэтому повторно открывать библиотеку для одинаковых деталей нет необходимости, достаточно выделить нужный в списке и кликнуть на свободном рабочем поле.

3. На боковой панели нажимаем кнопку терминальные метки - . В списке "TERMINALS" нам потребуются элементы POWER и GROUND, выбираем каждый и кликаем на свободном рабочем поле.

4. На той же панели нажимаем виртуальные приборы - . В списке INSTRUMENTS выделяем OSCILLOSCOPE и вставляем его в проект.

5. Включаем кнопку стрелка -  и расставляем все элементы как нам нужно, просто перетаскивая их мышью.

6. Редактируем параметры (номиналы) конденсаторов, резисторов и т.д. в соответствии со схемой. Щелкаем левой кнопкой мыши на нужном элементе несколько раз, в открывшемся окне редактирования ищем строки: Capacitance (для конденсаторов), Resistance (для резисторов), Frequency (для генераторов), String (для питания). Номиналы конденсаторов - 22p, резисторов - 100R и 10K, генераторов - 20MHz, питание - +5V.

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

8. Открываем свойства микроконтроллера PIC16F877A. В строке Processor Clock Frequency пишем 20MHz, а в строке Programm File - путь к HEX-файлу нашей программы. Он находится в директории куда мы сохраняли проект MPLABа. После всех операций нажимаем "OK". Сохраняем схему, можно в той же папке что и исходник программы.

9. Нажимаем запуск симуляции "Play". У меня получилось следующее:

Теперь можно сходить и попить чайку, в следующей статье продолжим.

Категория: Программирование микроконтроллеров PIC | Добавил: Anubis (09.01.2012)
Просмотров: 19561 | Рейтинг: 4.2/6
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа
Copyright MyCorp © 2018