KEEN SIDE успешно заменяет аналогичные продукты таких известных брендов, как Phoenix Contact, Weidmueller, Degson, Winstar, Hsuan Mao, KLS, G-NOR, Mean Well и др.

Устройство переключения на MEGA8

Новичок
 
Регистрация: 23.07.2014
Сообщений: 1
Репутация: 10
 
23.07.2014 13:26 #1
Здравствуйте, уважаемые посетители форума.

Я начинающий радиолюбитель, не так давно начал изучать микроконтроллеры AVR.
Хотелось бы, чтобы Вы помогли с написанием исходника на Си...

А вопрос, состоит в следующем - как написать программу устройства управления светодиодами (реле) при помощи одной кнопки, при нажатии на которую, светодиод (реле), подключённый к выходу
микроконтроллера, будет менять своё состояние на противоположное.
Конечно, эта задача легко решается при помощи обычного D —триггера, но всё же мне важно, как это сделать на микроконтроллере - программно…

P.S.
-Среда разработки - Atmel Studio 6.
-Микроконтроллер - ATMega8.
-Среда тестирования - Proteus ISIS 7. (схема в Протеусе - во вложении)
Вложения
Тип файла: rar RS_m8.rar (14.3 Кб, 0 просмотров)
Последний раз редактировалось Александр Трунов; 23.07.2014 в 18:28.
Оценка
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей.
Новичок
 
Регистрация: 30.09.2013
Сообщений: 2
Репутация: 10
 
24.07.2014 17:20 #2
простой опрос пинов и тригерная обработка. так конечно работать будет но это неправильно, желательно использовать прерывания, если задача требует мгновенной реакции. Для использования прерываний, читайте даташит. думаю вам пока что, надо тренироваться с ардуинкой.
Код:
//Изменение состояния светодиода в момент нажатия на кнопку:

/*
 * atmega8_keys.c
 *
 * Created: 24.07.2014 16:00:00
 *  Author: Grigoriev Alexander
 */

 #define F_CPU 1000000UL  // 1 MHz
 #define LED_1		PD1
 #define LED_2		PD0
 #define KN1		PB0
 #define KN2		PB1

    #define LED_ON(LED)    {sbi(DDRD, LED); sbi(PORTD, LED);}
    #define LED_OFF(LED)   {sbi(DDRD, LED); cbi(PORTD, LED);}
		
		

#include <avr/io.h>
#include <compat/deprecated.h>
#include <util/delay.h>

     
int  pkn1, pkn2;
	 
void init();


void delay_ms(int count) {
	while(count--) {
		_delay_ms(10);
	}
}
void init(){
         
		 // DDRD  |= (1<<LED_1)|(1<<LED_2);    //output
	  sbi(DDRD,LED_2);  //OUTPUT	  
	  sbi(DDRD,LED_2);  //OUTPUT

  	  cbi(PORTD,LED_1); // TO GND
	  cbi(PORTD,LED_2); // TO GND

	  cbi(DDRB,KN1); //input
	  cbi(DDRB,KN2); //INPUT

	  sbi(PORTB,KN1); //pullup TO vcc
	  sbi(PORTB,KN2); //pullup TO vcc
}
 
 
int main(void)
{
        init();
		
 	while(1){

if bit_is_clear(PINB,KN1) {
	_delay_ms(50);
	if bit_is_clear(PINB,KN1) pkn1=!pkn1;
}

if bit_is_clear(PINB,KN2) {
	_delay_ms(50);
	if bit_is_clear(PINB,KN2) pkn2=!pkn2;
}

if (pkn1)	LED_ON(LED_1) else LED_OFF(LED_1);
if (pkn2)	LED_ON(LED_2) else LED_OFF(LED_2);

}     
 
}
Вложения
Тип файла: rar atmega8-keys.rar (16.3 Кб, 0 просмотров)
Оценка
Специалист
 
Аватар для antonydublin
 
Регистрация: 22.09.2010
Адрес: г. Донецк
Сообщений: 868
Репутация: 380
371 0
3 0
 
24.07.2014 19:40 #3
Цитата:
Сообщение от alexanderik
Код:
...
void delay_ms(int count) {
	while(count--) {
		_delay_ms(10);
	}
}
...
while(1){

if bit_is_clear(PINB,KN1) {
	_delay_ms(50);
	if bit_is_clear(PINB,KN1) pkn1=!pkn1;
}

if bit_is_clear(PINB,KN2) {
	_delay_ms(50);
	if bit_is_clear(PINB,KN2) pkn2=!pkn2;
}

if (pkn1)	LED_ON(LED_1) else LED_OFF(LED_1);
if (pkn2)	LED_ON(LED_2) else LED_OFF(LED_2);

}
}
Alexanderik, Ваша программа не верна при таком подходе.
При нажатии и удержании кнопки событие будет отработано много раз с каким-то периодом. При удержании двух кнопок результат непредсказуем и/или реакция затянется. При удержании одной и нажатии второй аналогично. Неудачный пример. Такой код лучше использовать в упомянутом обработчике внешних прерываний, сторонясь _delay, когда есть возможность отследить фронт. С _delay правильно так:
Код:
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    uint8_t button0_event = 0x00;
    uint8_t button1_event = 0x00;

    PORTB |= _BV(PB0)|_BV(PB1);         // Подтяжка
    DDRB &= ~(_BV(PB0)|_BV(PB1));       // Входы

    PORTD |= _BV(PD0)|_BV(PD1);
    DDRD |= _BV(PD0)|_BV(PD1);          // Выходы		

    while(1)
    {
        if(button0_event == 0x00)       // Если предыдущее нажатие отработано и нажата кнопка 0
        if(!(PINB & _BV(PB0)))	
        {
            _delay_ms(20);              // Антидребезг
            if(!(PINB & _BV(PB0)))      // Если по-прежнему нажата
            {
                PORTD ^= _BV(PD0);      // Меняем состояние выхода
                button0_event = 0x01;   // Отметка о выполнении
            }
        }

        if(button1_event == 0x00)       // Аналогично
        if(!(PINB & _BV(PB1)))  
        {
            _delay_ms(20);
            if(!(PINB & _BV(PB1)))
            {
                PORTD ^= _BV(PD1);
                button1_event = 0x01;
            }
        }

        if(PINB & _BV(PB0))             // Если кнопка 0 или 1 не нажата - постоянно сбрасываем флаг
            button0_event = 0x00;       // Это исключает многократную отработку условий выше пока кнопка удерживается
        if(PINB & _BV(PB1))
            button1_event = 0x00;
    }
}
Вообще же, с логикой if(if(…)) легко запутаться. Программа становится сложной для понимания. Обычно используют внешние прерывания (а лучше обработчик таймера, если режим МК разрешает), что позволяет параллельно отслеживать много независимых событий (вплоть до «Короткого нажатия», «Длительного нажатия» и «Комбинаций клавиш») и отрабатывать нажатие кнопок в главном цикле не сразу, а как только появится «временное окно» при выполнении основной программы. ТС Александр, отправляйтесь к книге «Шпак. Программирование на С для AVR и PIC контроллеров» http://www.ozon.ru/context/detail/id/5615907/. Это поможет снять много первоначальных вопросов.
Последний раз редактировалось antonydublin; 24.07.2014 в 19:58.
Оценка
Новичок
 
Регистрация: 30.09.2013
Сообщений: 2
Репутация: 10
 
25.07.2014 05:15 #4
Цитата:
Сообщение от antonydublin
Alexanderik, Ваша программа не верна при таком подходе.
При нажатии и удержании кнопки событие будет отработано много раз с каким-то периодом. При удержании двух кнопок результат непредсказуем и/или реакция затянется. При удержании одной и нажатии второй аналогично. Неудачный пример. Такой код лучше использовать в упомянутом обработчике внешних прерываний, сторонясь _delay, когда есть возможность отследить фронт. С _delay правильно так:
Код:
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    uint8_t button0_event = 0x00;
    uint8_t button1_event = 0x00;

    PORTB |= _BV(PB0)|_BV(PB1);         // Подтяжка
    DDRB &= ~(_BV(PB0)|_BV(PB1));       // Входы

    PORTD |= _BV(PD0)|_BV(PD1);
    DDRD |= _BV(PD0)|_BV(PD1);          // Выходы		

    while(1)
    {
        if(button0_event == 0x00)       // Если предыдущее нажатие отработано и нажата кнопка 0
        if(!(PINB & _BV(PB0)))	
        {
            _delay_ms(20);              // Антидребезг
            if(!(PINB & _BV(PB0)))      // Если по-прежнему нажата
            {
                PORTD ^= _BV(PD0);      // Меняем состояние выхода
                button0_event = 0x01;   // Отметка о выполнении
            }
        }

        if(button1_event == 0x00)       // Аналогично
        if(!(PINB & _BV(PB1)))  
        {
            _delay_ms(20);
            if(!(PINB & _BV(PB1)))
            {
                PORTD ^= _BV(PD1);
                button1_event = 0x01;
            }
        }

        if(PINB & _BV(PB0))             // Если кнопка 0 или 1 не нажата - постоянно сбрасываем флаг
            button0_event = 0x00;       // Это исключает многократную отработку условий выше пока кнопка удерживается
        if(PINB & _BV(PB1))
            button1_event = 0x00;
    }
}
Вообще же, с логикой if(if(…)) легко запутаться. Программа становится сложной для понимания. Обычно используют внешние прерывания (а лучше обработчик таймера, если режим МК разрешает), что позволяет параллельно отслеживать много независимых событий (вплоть до «Короткого нажатия», «Длительного нажатия» и «Комбинаций клавиш») и отрабатывать нажатие кнопок в главном цикле не сразу, а как только появится «временное окно» при выполнении основной программы. ТС Александр, отправляйтесь к книге «Шпак. Программирование на С для AVR и PIC контроллеров» http://www.ozon.ru/context/detail/id/5615907/. Это поможет снять много первоначальных вопросов.
про тригер защелку совсем забыл.
ну по моему вопрошавшему все-равно.


дополняю... ШПАК.
magnet:?xt=urn:btih:JXO2YVF6MG5472Y4SZGL5PRQLU57DR YA
magnet:?xt=urn:btih:QD2CKCZABMKYIWTKCOHU5ZW2KZ5W47 KL
Оценка
Знаток
 
Аватар для iev91
 
Регистрация: 12.10.2009
Адрес: Тольятти
Сообщений: 231
Репутация: 86
74 10
1 0
 
25.07.2014 11:01 #5
Цитата:
Сообщение от Александр Трунов
эта задача легко решается при помощи обычного D —триггера
С помощью D-триггера легко делается генератор случайных чисел.
В принципе, программная и аппаратная обработка должны делать одно и то же, поэтому программирование, по большому счету, есть упаковка схемных узлов в виде программы.

Давайте посмотрим, как сделать аппаратно, чтобы кнопка меняла состояние триггера. Нужно сигнал от кнопки подать на интегратор (ФНЧ), который бы убрал все быстрые изменения состояний (дребезг контактов). Затем сигнал подается на триггер Шмитта с гистерезисом, на выходе которого получается сигнал с прямоугольными фронтами. И затем - счетчик-делитель на 2.

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

В итоге, от порта с кнопкой имеем ряд единиц и нулей, соответствующий состоянию контактов кнопки. Делаем программный интегратор. Он должен, наподобие RC-цепочки ФНЧ, медленно увеличиваться, когда на входе 1, и медленно уменьшаться, когда 0. Далее, он должен быть ограничен двумя значениями "снизу" и "сверху", потому что команда увеличения/уменьшения работает всегда и получается "перехлест" через 0. Аналог гистерезиса можно организовать путем прибавления и вычитания небольшого фиксированного числа по достижению границ. Ну, а деление на 2 выполняется простым инкрементом и использованием младшего разряда в качестве результата.

Я советую подходить к задаче именно так, системно. Это позволяет избежать путаницы с условными ветвлениями.

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход
Электронные компоненты. Бесплатная доставка по России
Часовой пояс GMT +3, время: 11:12.
Обратная связь РадиоЛоцман Вверх