Программирование на mikroC для AVR-микроконтроллеров процедур управления отдельными разрядами портов, опроса контактов переключателей
Способы управления отдельными разрядами портов
В программах для микроконтроллеров часто требуется управлять отдельными линиями портов МК, а также опрашивать их состояния.
Компилятор mikroC PRO for AVR позволяет иметь доступ к отдельными битами регистров специальных функций. Это можно выполнить следующими способами.
1. Указать имя регистра, а затем после знака точки как разделителя идентификатор номера бита в регистре в виде: B0, B1, B2, B3, B4, B5, B6, B7, где В0 – младший бит.
Например:
// для порта С, настроенного на вывод
PORTC.B0 = 1; // вывести лог. 1 на 0-ю линию порта С
PORTC.B7 = 0; // вывести лог. 0 на 7-ю линию порта С
SREG.B7 = 1; // Установить в 1 бит разрешения глобальных
// прерываний (7-й бит в регистре SREG)
2. Указать имя бита в регистре специальных функций, а затем идентификатор вида: _bit.
Например:
SREG_I_bit = 1; // установить в 1 бит с именем SREG_I в регистре SREG
// (это 7-й бит регистра – бит разрешения глобальных прерываний)
Биты регистров портов обозначаются следующим образом, например, для порта А:
· в регистре DDRA – DDA0_bit, DDA1_bit, …, DDA7_bit;
· в регистре PORTA – PORTA0_bit, PORTA1_bit, …, PORTA7_bit;
· в регистре PINA – PINA0_bit, PINA1_bit, …, PINA7_bit.
Для других портов (B, C, D, …) обозначения отдельных битов регистров аналогичное.
// для порта С, настроенного на вывод
PORTC0_bit = 1; // вывести лог. 1 на 0-ю линию порта С
PORTC7_bit = 0; // вывести лог. 0 на 7-ю линию порта С
В управляющих программах для микроконтроллеров часто возникает необходимость в формировании временных задержек. Компилятор mikroC имеет так называемые встроенные функции задержки, которые формируют временные задержки программным методом. Наибольшее применение находят три функции:
1) Delay_us(константа), где константа определяет величину задержки в микросекундах (константа – это целое число типа unsigned long в пределах от 1 до 4294967295);
2) Delay_ms(константа), где константа определяет величину задержки в миллисекундах ( константа – это целое число типа unsigned long в пределах от 1 до 4294967295);
3) Vdelay_ms(переменная), где значение переменной определяет величину задержки в миллисекундах (переменная должна быть типа unsigned int, а величина ее в пределах от 1 до 65535).
Примеры:
Delay_us(100); // задержка на время 100 мкс
Delay_ms(2000); // задержка на время 2000 мс = 2 с
unsigned int time = 500;
Vdelay_ms(time); // задержка на время 500 мс
Разработка программ управления светодиодом
Рассмотрим простейшее микроконтроллерное устройство (МКУ), в котором МК типа ATmega16 управляет светодиодом, присоединенным к 0-му разряду (линии) порта C. Принципиальная схема такого МКУ (при моделировании в среде Proteus) может иметь вид, приведенный на рисунке 1. При высоком уровне (логическая 1) на выводе порта PC0 светодиод горит, а при низком уровне (логический 0) на выводе порта PC0 светодиод не горит.
Рисунок 1 - Принципиальная схема МКУ для управления светодиодом
Рассмотрим программу, которая производит переключение светодиода через интервал 0,5 с, то есть с частотой 1 Гц.
С целью ознакомления с различными способами обеспечения доступа к отдельным битам регистров портов рассмотрим два варианта программы:
1) с использованием для доступа идентификатора номера бита в регистре – B0, B1, …, B7;
2) с использованием для доступа имени бита и идентификатора _bit.
/**********************************************************
led_1.c – программа управления светодиодом (1-й вариант)
***********************************************************/
void main( )
{
DDRC.B0 = 1; // настроить 0- линию порта С на вывод
PORTC.B0 = 0; // погасить светодиод D1
while(1) // бесконечный цикл вывода
{
PORTC.B0 = 1; // зажечь светодиод D1
Delay_ms(500); // задержка на 500 мс
PORTC.B0 = 0; // погасить светодиод D1
Delay_ms(500); // задержка на 500 мс
}
}
Второй вариант программы управления светодиодом.
/***********************************************************
led_2.c – программа управления светодиодом (2-й вариант)
***********************************************************/
void main( )
{
DDC0_bit = 1; // настроить 0-ю линию порта С на вывод
PORTC0_bit = 0; // погасить светодиод D1
while(1)
{
PORTC0_bit = 1; // зажечь D1
Delay_ms(500);
PORTC0_bit = 0; // погасить D1
Delay_ms(500);
}
}
Программирование процедуры опроса переключателя
Рассмотрим теперь, как на языке mikroC выполняется опрос состояния контактов переключателя (кнопки). На рисунке 2 приведена схема МКУ (при моделировании ее в Proteus), в которой управление светодиодом D1 производится от переключателя (кнопки) SB1 по следующему алгоритму. Когда контакт SB1 замкнут, светодиод D1 горит, когда контакт SB1 разомкнут, D1 не горит. Рассмотрим два варианта программы управления светодиодом D1 от кнопки SB1. Для упрощения текста программы будем считать, что у кнопки SB1 нет дребезга контактов.
Замечание. В схеме МКУ на рисунке 2 к выводу PB1 (1-я линия порта В) подключена кнопка SB1. Известно, что для считывания состояния контакта кнопки (замнут или разомкнут) к соответствующему выводу порта обязательно должен быть подключен подтягивающий резистор, который обеспечивает на этом выводе высокий уровень (логическую 1) при разомкнутом контакте.
В AVR-микроконтроллерах имеется возможность программного подключения внутренних подтягивающих резисторов к любым линиям портов, которые настроены на прием данных, т.е. сконфигурированы как входы. Для подключения резисторов нужно записать логические 1 в те разряды регистра данных PORTx порта, которые были предварительно настроены как входы.
Примеры подключения внутренних подтягивающих резисторов.
DDRC = 0; // настроить все линии порта С на ввод
PORTC = 0xFF; // подключить ко всем выводам порта С
// подтягивающие резисторы
………………….
DDRA.B2 = 0; // настроить 2-ю линию порта А (PA2) на ввод
PORTA.B2 = 1; // подключить к линии PA2 подтягивающий резистор
………………….
DDB1_bit = 0; // настроить 1-ю линию порта В (PB1) на ввод
PORTB1_bit = 1; // подключить к линии PB1 подтягивающий резистор
Сначала рассмотрим программу, в которой для опроса состояния контактов кнопки используются оператор выбора if …. else.
***********************************************************
led_but_1.c – первая программа управления светодиодом от кнопки
**********************************************************/
void main( )
{
DDRB.B1= 0; // настроить 1-ю линию порта B на ввод
PORTB.B1 = 1; // подключить подтягивающий резистор
// к линии PB1
DDRC.B1 = 1; // настроить 1-ю линию порта С на вывод
PORTC.B1 = 0; // погасить светодиод
while(1) // бесконечный цикл опроса
{
if(PINB.B1 ==0) // если контакт кнопки SB1 замкнут, то
PORTC.B1 = 1; // зажечь светодиод
else // иначе
PORTC.B1 = 0; // погасить светодиод
}
}
Рисунок 2 – Принципиальная схема МКУ с управлением
светодиодом от кнопки
Теперь рассмотрим программу, в которой для опроса состояния контактов кнопки SB1 используются операторы цикла while.
/**********************************************************
led_but_2.c - вторая программа управления светодиодом от кнопки
********************************************************* */
void main( )
{
DDB1_bit = 0; // настроить 1-ю линию порта В на ввод
PORTB1_bit = 1; // подключить подтягивающий резистор
// к выводу PB1
DDC1_bit = 1; // настроить 1-ю линию порта С на вывод
PORTC1_bit = 0; // погасить светодиод
while(1) // бесконечный цикл повторения
{
while(PINB1_bit == 1); // ожидание замыкания контакта SB1
PORTC1_bit = 1; // зажечь светодиод
while(PINB1_bit == 0); // ожидание размыкания контакта SB1
PORTC1_bit = 0; // погасить светодиод
}
}