Урок 5. Первая программа на PIC12F675

Мы уже получили минимальные представления о микроконтроллерах,  установили необходимые программы: среду разработки MPLAB и C-компилятор для микроконтроллеров фирмы Microchip Hi-Tech PICC. На этом уроке, как я уже давно обещал, мы научимся создавать проект в среде MPLAB, напишем первую программу для PIC12F675 и проверим ее работоспособность в среде моделирования Proteus. Программа будет очень простая: с помощью нашего микроконтроллера мы заставим мигать два светодиода. То есть на данном этапе нам нужно понять: как работать с портами ввода/вывода.

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

Итак, надеюсь, что MPLAB, Proteus и PICC вы скачали и установили.

Скачайте также даташит на PIC12F675.

Кто испытывает трудности с чтение на английском языке, рекомендую скачать даташит на PIC12F675 на русском языке.

Для начала создадим в Proteus схему нашей мигалки.

Схема мигалки на PIC12F675 в Proteus

Вывод MCLR используется для сброса микроконтроллера, поэтому для нормальной работы его нужно подтягивать к питанию через резистор. Если подать на этот вход сигнал низкого уровня (логический «0»), то произойдет сброс микроконтроллера. В качестве цифровых выходов, которые будут управлять светодиодами, выбираем выходы GP4 и GP5. Двойным кликом левой кнопки мыши на микроконтроллере U1 открываем его свойства. Здесь необходимо установить такие настройки:

Настройки PIC12F675 в Proteus

Пока просто установите все как на рисунке, подробности будут потом.

Для тех, кто не умеет работать в протеусе, я снял видео о том, как создать схему в Proteus.

Теперь, когда схема в протеусе готова, создадим проект в среде MPLAB.

Запускаем MPLAB, переходим в меню Project->ProjectWizard…

Должно появиться окно:

Создание проекта в MPLAB

Нажимаем Далее и в поле Device выбираем нужный микроконтроллер PIC12F675.

Создание проекта в MPLAB. Выбор микроконтроллера

Нажимаем Далее. В следующем окне предлагается выбрать компилятор.

Создание проекта в MPLAB. Выбор компилятора

Здесь, как вы уже догадались, мы выбираем установленный ранее компилятор PICC.

Если возле PICC Compiler, Assembler или Linker появится красный крестик, то нужно указать полный путь к файлу picc.exe.  Обычно это что-то вроде c:\Program Files\HI-TECH Software\PICC\9.50\bin\picc.exe

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

Создание проекта в MPLAB. Рабочая директория проекта

Выбираем нужную директорию, в поле Имя файла задаем имя нашего проекта и нажимаем Сохранить.

Создание проекта в MPLAB. Имя проекта

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

Создание проекта в MPLAB. Добавление файлов в проект

Просто жмем Далее. В следующем окне появится сообщение о том, что проект создан. Нажимаем  Готово.

Создание проекта в MPLAB. Завершение

Далее предлагается сохранить файл рабочей директории Workspace Files.

Создание проекта в MPLAB. Сохранение mcw

Здесь обычно я пишу такое же имя, как и у самого проекта. Хотя можно писать и другое.

Дальше у вас должно открыться дерево проекта “Project” и окно “Output”.

Дерево проекта в MPLAB

Открыть/закрыть  их можно через меню View. View->Project, View->Output

Пришло время создать файл программы. Заходим в меню File->New. Появится текстовый редактор.

Текстовый редактор MPLAB

Дальше вставляем в редактор код программы:

#include <pic.h>
__CONFIG(0x31F4);

void main(void){
	//Вспомогательная переменная
	//для организации временной задержки
	unsigned long counter;
	
	//Настройка портов ввода/вывода PIC12F675
	//Выключение подтягивающих резисторов
	WPU = 0x00;
	//Запретить использование подтягивающих резисторов
	GPPU = 1;
	
	//Настрока выходов GP4, GP5 на выход
	TRISIO = 0;
	
	//Установка на выходах GP4, GP5 лог. 0
	GPIO = 0;
	
	//Бесконечный цикл. 
	while(1){
		//Установка GP4 в лог. 1, GP1 в лог. 0
		GPIO = 0x10;
		//Задержка на 5000 циклов
		for(counter = 0; counter < 5000; counter++);
		//Установка GP5 в лог. 0, GP1 в лог. 1
		GPIO = 0x20;
		//Задержка на 5000 циклов
		for(counter = 0; counter < 5000; counter++);
	}
	
}

Позже я объясню как работает программа.

Сохраняем файл программы File->Save.

Сохраняем исходный код программы main.c

В появившемся диалоговом окне выбираем директорию, в которой создавался проект, и даем имя файлу main.c. Нажимаем Сохранить.

Теперь нужно добавить файл программы в дерево проекта. Для этого нажимаем правой кнопкой мыши на Source Files и выбираем пункт Add Files…

Добавление файла программы в дерево проекта

Находим наш main.c и нажимаем Открыть. После этого main.c появится в дереве проекта.

Сохраняем нашWorkspace: File->Save Workspace.

Теперь, чтобы создался файл прошивки *.hex, нужно откомпилировать проект.

Заходим в меню Project и нажимаем Bild All.

Компиляция проекта MPLAB

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

Результат компиляции проекта в MPLAB

Program space – постоянная flash память, в которой хранится программа.

Data space – временная память, в которой хранятся переменные

EEPROM – энергонезависимая постоянная память, в ней могут храниться какие-то настройки устройства.

Configuration bits – область памяти, в которой хранятся биты конфигурации.

Если в программе имеются ошибки, то в окне Output появится предупреждение о них.

После компиляции в папке с проектом должен появиться файл leds_blink.hex

Название может быть и другим - смотря как назван проект.

Загружаем данный файл в модель микроконтроллера PIC12F675 в протеусе. Для этого заходим в параметры микроконтроллера (рисунок в начале  урока) и в поле Program File выбираем файл прошивки leds_blink.hex.

В левом нижнем углу среды Proteus нажмите кнопку Play. Запускается симуляция работы микроконтроллера и светодиоды должны замигать. Поздравляю, вы создали первую программу!

 

Теперь подробнее расскажу - что же мы написали в коде нашей программы.

Прежде всего напоминаю, что для работы микроконтроллера необходимо его тактировать. В микроконтроллере PIC12F675 предусмотрена возможноcть тактирования как от внешнего источника, которым может служить кварцевый резонатор или RC-цепочка, так и от внутреннего RC-генератора. Максимальная частота тактирования для данного микроконтроллера составляет 20 МГц. Частота внутреннего RC-генератора фиксирована и составляет 4 МГц. От какого типа генератора будет тактировать микроконтроллер, определяется битами конфигурации. В коде программы биты конфигурации настраиваются через макрос __CONFIG(0x31F4);

Число, записанное в скобках, не взято «с потолка». Это число записывается в регистр CONFIG, и определяет такие параметры как: режим тактирования/источник тактирования, разрешает/запрещает работу сторожевого таймера, таймера включения питания, разрешение сброса контроллера при понижении питания и другие настройки. Подробно о регистре написано в разделе 9.1 Configuration Bits даташита. В среде MPLAB есть графический инструмент для настройки битов конфигурации, из которого можно получить число, записываемое в регистр CONFIG. Запускается данный инструмент через меню Configure->Configuration Bits…

Биты конфигурации в MPLAB

 

Снимите галочку Configuration Bits set in code.

1. Выбираем генератор FOSC: INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN.

Мы выбрали тактирование от внутреннего RC-генератора (не хотим тратиться на покупку кварцевого резонатора). Нужно заметить, что тактирование от RC-генератора не гарантирует высокую точность периода сигнала, поэтому данный вариант нельзя применять, когда в программе отсчитываются очень точные интервалы времени. В этом случае лучше применить более стабильный генератор на кварцевом резонаторе.

В микроконтроллере PIC12F675 одни и те же выводы могут использоваться для выполнения различных функций: работать как цифровые входы/выходы, как аналоговые входы, входы компаратора, выходы компаратора и т.д. Еще одна из возможностей – это получение сигнала тактирования на выводе микроконтроллера (если например от этого же сигнала нужно тактировать что-то еще). В данном случае мы настроили данный выходы для работы в цифровом режиме, т.к. ног у микроконтроллера и так не много, а внешний сигнал тактирования нам не нужен.

 

2. Настройка сторожевого таймера (Watchdog Timer) WDTE: WDT Disabled.

Сторожевой таймер – это такой таймер, который «сторожит» микроконтроллер от зависания. Данный таймер отсчитывает определенные интервалы времени, и если за это время не сбросить таймер, то он сбрасывает микроконтроллер (перезапускает программу). Т.е. в программе нужно с определенной периодичностью сбрасывать данный таймер. Период таймера настраивается в регистре OPTION_REG. Для обнуления сторожевого таймера вызывается ассемблерная команда CLRWDT. На си можно записать ее так asm(“CLRWDT”);

Наше устройства выполняет простые функции и если оно зависнет, то это не приведет к тяжелым последствиям, поэтому просто выключает сторожевой таймер, иначе он выключит нас J.

 

3. Таймер включения питания PWRTE: PWRT Disable.

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

 

4.Настройка пина MCLR: GP3/MCLR pin function is MCLR.

Я уже писал ранее, что этот пин используется для внешнего сброса микроконтроллера. Но его можно настроить так, чтобы он выполнял функцию цифрового вывода порта (в данном случае MCLR подтягивается к питанию внутренним резистором). Я вам советую оставить функцию внешнего сброса по данному пину, иначе, в зависимости от программатора, могут возникнуть проблемы при дальнейшем перепрограммировании МК.

 

5.Сброс по снижению питания BODEN: BOD enable. Здесь все понятно: снижается питание Vdd до определенного порога Vbor в течение времени Tbor – происходит сброс микроконтроллера. Vbor как правило  - это напряжение 2.0…2.1 В. Включаем функцию сброса по снижению питания.

 

6.Бит защиты памяти программ CB:  disable. Может называться CP (Code protect). Установка этого бита защищает память микроконтроллера от чтения программатором.  Предположим, что вы проделали большую интеллектуальную работу – написали сложную программу для устройства, которое поступит в серийное производство, и вам не хотелось бы, чтобы данное устройство мог кто-то с легкостью скопировать, поэтому в данном случае вы включаете защиту памяти микроконтроллера от считывания.  Когда этот бит установлен, программу нельзя считать. В нашем случае мы защиту отключаем.

 

7. Бит защиты памяти EEPROM CPD: disable. Здесь все аналогично CB, только устанавливается защита на энергонезависимую память EEPROM. Тоже отключаем.

 

После того, как каждый бит конфигурации установлен, в поле Value можно увидеть шестнадцатеричное число, которое записывается в регистр CONFIG. У меня получилось число 0x31F4.

 

Для того, чтобы с регистрами можно было работать, используя их имена, а не адреса в памяти, подключается заголовочный файл pic.c помощью директивы компилятора #include.

 

Как известно, основная функция в Си, с которой начинается выполнения программы – это функция main. Программа наша не большая и весь код будет находиться в функции main. Еще одной важной особенностью написания программ для микроконтроллера является наличие бесконечно цикла (в нашем случае это while(1)). Если это не сделать, то счетчик команд дойдет до последнего адреса в памяти программ (flash-памяти) и перейдет на нулевой адрес, что приведет, если не к сбросу микроконтроллера, так, по крайней мере, к повторному запуску программы и повторной инициализации всех регистров. В общем, ерунда получится.

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

Заглянем в даташит на мк и увидим, что за работу цифровых портов ввода/вывода отвечают следующие регистры: GPIO, TRISIO, WPU и еще другие, но о них позже.

Регистр GPIO:

Регистр GPIO

Данный регистр отвечает за то, какой логический уровень сигнала будет на выходе: 1 – высокий (5 В), 0 – низкий (0В). Нужно заметить, что установить уровень выходного сигнала можно в том случает, если цифровой вывод используется в качестве выхода.

За направление работы порта на вход или выход отвечает регистр TRISIO.

Регистр TRISIO

Если бит TRISIOn установлен в 1, то соответствующий n-й вывод порта будет работать на вход. Если 0 – то на выход.

Когда выводы порта используются как входы, то часто необходимо их подтягивать к питанию через резистор. Вход в «висящем» состоянии оставлять нежелательно, так как из-за наводок на нем хаотически могут возникать сигналы высокого или низкого уровня. Когда же вход подтянут к питанию (или к земле), то можно с уверенностью сказать, что на нем присутствует сигнал высокого (низкого) уровня. В микроконтроллере PIC12F675 имеются встроенные подтягивающие резисторы, что избавляет разработчика от применения внешних резисторов и уменьшает конструкцию устройства. За настройку подтягивающих резисторов отвечает регистр WPU.

Регистр WPU

Установка бита WPUn в 1 разрешает внутреннюю подтяжку к питанию вывода n. Сброс бита в 0 соответственно запрещает использование подтягивающего резистора.

Однако разрешить использование подтягивающих резисторов в регистре WPU не достаточно. Есть еще такой замечательный регистр OPTION. Он в основном отвечает за настройку режима работы таймера Timer0, о котором будет сказано на других уроках, но помимо этого данный регистр содержит бит GPPU, который запрещает или разрешает использование всех подтягивающих регистров.

Регистр OPTION

Над описание бита GPPU стоит черта инверсии. Это значит, что установка бита в 1 запрещает подтягивающие резисторы, а сброс бита в 0 наоборот разрешает.

Итак, минимальные знания для написания первой программы мы получили.

Теперь алгоритм работы программы по порядку.

1) Запрещаем использование подтягивающих резисторов, так как порт работает на выход.

//Выключение подтягивающих резисторов
WPU = 0x00;
//Запретить использование подтягивающих резисторов
GPPU = 1;

Необходимо заметить, что в файле pic.h описаны не только регистры целиком, но и каждый бит по отдельности, поэтому мы записали единицу в бит GPPU вместо того, чтобы записать ее в регистр OPTION. Запись OPTION |= 0x80 будет равнозначной записи GPPU = 1. Т.е. тут дело вкуса/универсальности программы. Если число 0x80 перевести в двоичный код, то получим 0b10000000, т.е. в бит под номером 7 (отсчет идет от 0-го бита) мы запишем единицу.

2)Настраиваем все выводы порта на выход.

//Настрока выводов на выход
TRISIO = 0;

3)Устанавливаем все выходы микроконтроллера в 0.

//Установка на выходах лог. 0
GPIO = 0;

4) Устанавливаем на выходе GP4 единицу, а на выходе GP5 – ноль (см. схему в протеусе).

//Установка GP4 в лог. 1, GP1 в лог. 0
GPIO = 0x10;

5)Организовываем задержку во времени на переключение светодиодов. Каждая команда PIC-контроллера выполняется за 4 машинных цикла. Мы настраивали тактирование микроконтроллера от внутреннего RC-генератора частотой 4МГц. Т.е получается , что каждая команда выполняется с частотой 1МГц, т.е. за 1 мкс. Если переключать светодиоды с такой частотой, то мы просто не увидим этого. Нам будет казаться, что они постоянно горят. Для этого создаем программный цикл на n-е количество «бесполезных» операций, которые задержат переключение светодиодов.

//Задержка примерно на 5000 циклов
for(counter = 0; counter < 5000; counter++);

6)Как только истекло время задержки, переключаем светодиоды. На выходе GP4 устанавливается ноль, на выходе GP5 – единица.

//Установка GP5 в лог. 0, GP1 в лог. 1
GPIO = 0x20;

7)Снова организовываем задержку.

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

После компиляции программы получаем hex-файл, который загружается в модель микроконтроллера в протеусе, о чем говорилось выше. Как это сделать показано на видео.

На этом наш урок по работе с портами ввода/вывода заканчивается. В следующем уроке научимся работать в режиме отладки программы.

Скачать проект мигалки в MPLAB

Скачать модель в Proteus

Комментарии

Загрузил все программы, но при компиляции мне выдает такую ошибку-
Clean: Deleting intermediary and output files.
Clean: Deleted file "D:\PIC controler\led_blik.mcs".
Clean: Done.
Executing: "C:\Program Files\HI-TECH Software\PICC\9.83\bin\picc.exe" -C -E"maine.cce" "maine.c" -O"maine.obj" -Zg9 -O -ASMLIST -Q -MPLAB -12F675
(924) missing argument to "-O" option
Halting build on first failure as requested.
BUILD FAILED: Tue Mar 17 14:59:02 2015

.
В чем может быть причина.

Сделал как написано в 5 уроке.
//Запретить использование подтягивающих резисторов
GPPU = 1;

Error [192] C:\projekt\start\workspace\trttwerq\main.c; 15.1 undefined identifier "GPPU"
(Ошибка [192] C:\projekt\start\workspace\trttwerq\main.c; 15.1 неопределенных идентификатора "GPPU")
Что не так?

Какая версия компилятора?
Нужно смотреть заголовочный файл с регистрами микроконтроллера, возможно там данный бит описан по-другому или не описан вовсе, тогда нужно с помощью операции побитового ИЛИ установить бит GPPU в регистре OPTION.