Программирование микроконтроллеров на Си.
Программирование в среде 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.
|