Перейти к содержанию

Переключатель ATmega8 и две кнопки


Igor-13

Рекомендуемые сообщения

Пытаюсь сделать Переключатель на ATmega8. Вход -две кнопки независимы, выход - один порт 8 пинов. Каждая кнопка управляет своим сдвигом, а на выходе комбинация состояний.  Сочинил программу, а она работает не так как задумал. Сдвиги по отдельности работают хорошо, а вот комбинацию их состояний не могу получить правильно. Где ошибка?  Вот мой код   

#include <mega8.h>    // частота CP 4мгц. 
#include <delay.h>
unsigned char temp = 0x01; unsigned char n = 0;
unsigned char temp1 = 0x01; unsigned char n1 = 0;
unsigned char temp0 = 0x00; unsigned char m = 0;
void main(void) { DDRB = 0xFF; PORTB = 0x00; DDRD = 0xFF; PORTD = 0x00; // выходы PORTB и PORTD. 
DDRC = 0x00; PORTC=0x03; // входы PC0 и PC1. подключаем нагрузочные резисторы к PC0 и PC1
while(1) { delay_ms(100);  // главный цикл
//A:
while(PINC==0x03) {PORTD = temp0; }         // если ничего не нажато, то топчемся здесь.
if (PINC.0==0) { temp = temp << 1; n++;}      // если PINC.0 нажат, сдвигаем на 1 разряд temp вправо ( n=1, 00000010.)   
while(PINC.0==0) { }                                    // пока PINC.0 нажато, ждем когда отпустит
while (n==!0) { m=n+n1;  // бесконечный цикл.  если n не нуль, то выбираем 
if (m==0) PORTD=0b00000000;
if (n==1) {if (n1==8) PORTD=0b00000001;}  else PORTD=0b00000000;  
if (n==2) {if (n1==7) PORTD=0b00000010;}  else PORTD=0b00000000;  
if (n==3) {if (n1==6) PORTD=0b00000100;}  else PORTD=0b00000000; 
if (n==4) {if (n1==5) PORTD=0b00001000;}  else PORTD=0b00000000;  
if (n==5) {if (n1==4) PORTD=0b00010000;}  else PORTD=0b00000000;    
if (n==6) {if (n1==3) PORTD=0b00100000;}  else PORTD=0b00000000;  
if (n==7) {if (n1==2) PORTD=0b01000000;}  else PORTD=0b00000000;  
if (n==8) {if (n1==1) PORTD=0b10000000;}  else PORTD=0b00000000; }
if (n==8) {temp = 0x01; n=0;}  delay_ms(100); 
while(PINC==0x03) {PORTD = temp1; } 
if (PINC.1==0) { temp1 = temp1 << 1; n1++; }    // сдвигаем на 1 разряд temp вправо    
while(PINC.1==0) { }  
while (n==!0) { m=n+n1; // бесконечный цикл.
if (m==0) PORTD=0b00000000;
if (n==1) {if (n1==8) PORTD=0b00000001;}  else PORTD=0b00000000;  
if (n==2) {if (n1==7) PORTD=0b00000010;}  else PORTD=0b00000000;  
if (n==3) {if (n1==6) PORTD=0b00000100;}  else PORTD=0b00000000; 
if (n==4) {if (n1==5) PORTD=0b00001000;}  else PORTD=0b00000000;  
if (n==5) {if (n1==4) PORTD=0b00010000;}  else PORTD=0b00000000;    
if (n==6) {if (n1==3) PORTD=0b00100000;}  else PORTD=0b00000000;  
if (n==7) {if (n1==2) PORTD=0b01000000;}  else PORTD=0b00000000;  
if (n==8) {if (n1==1) PORTD=0b10000000;}  else PORTD=0b00000000; }
if (n1==8) {temp1 = 0x01; n1=0;} delay_ms(100);
}}                 //  фигня. PORTD.0 мигает по разному. 

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

  • Ответов 66
  • Создана
  • Последний ответ

Топ авторов темы

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

  • 2 недели спустя...

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Бегло ознакомлся, можт чего-то не допер... Вобще-то я на тете Асе пишу, и на Паскале... :D

Заведите себе две переменные типа byte (или как там этот тип в Сях-то называется? :)) - Left и Right. По одной кнопке двигаете Left влево, по другой Right - вправо. Затем делаете лог. ИЛИ этих двух переменных, результат пихаете в Temp, а уже Temp бросаете в порт - и будет у Вас в этом порту комбинация из двух "бегущих огоньков"... ;)

Изменено пользователем Prozac
Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Мне надо не бегущие огоньки.

Надо переключатель типа кодовый, от двух кнопок логическое И.  Если первый нажмет один раз, а второй нажмет восемь раз, то загорится первый на порту выхода. и так далее (2+7, 3+6, 4+5.......8+1). Вот переделал пока наполовину (до четырех нажатий), вроде бы работает, но иногда проскакивает мимо. Значит что-то не так.

#include <mega8.h>    // частота CP 8мгц. 
#include <delay.h>
unsigned char n = 0;
unsigned char m = 0;
unsigned char k = 0;
unsigned char s = 0;
unsigned char temp = 0;
void main(void) {              // начало программы 
DDRD = 0xFF; PORTD = 0x00; // выход -  PORTD. 
DDRC = 0x00; PORTC=0x03;   // входы - PC0 и PC1. подключаем нагрузочные резисторы к PC0 и PC1
PORTD = 0x0F; delay_ms(1000); PORTD = 0x00; // мигнуть для проверки лампочек
while(1) {  // главный цикл 
if(k!=5) { while(PINC==3) {PORTD=temp;} }  // если сумма не равна 5, если нет нажатий, то топчемся 
if (PINC.0==0) {n++; while(PINC.0==0)  {delay_ms(10);} if (n>4) n=0; }    // если есть нажатие n
if (PINC.1==0) {m++; while(PINC.1==0) {delay_ms(10);} if (m>4) m=0; }  // если есть нажатие m
k=n+m; delay_ms(1); if (k==5) {s=k-n;    // вычисляем сумму, если равна 5, то вычисляем s и делаем выбор на выход
switch (s) {
case 1: PORTD=1;  break;  
case 2: PORTD=2;  break; 
case 3: PORTD=4;  break;
case 4: PORTD=8;  break; }
delay_ms(1);  k=0;}
} }   

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

В любом случае, я считаю что Вам нужно завести две переменных - одну для первой, а вторую - для второй кнопки. И менять их значение (сдвигать) только по этим кнопкам. А результат всех операций над ними помещать в Temp, или еще куда-то. Но эти переменные - только по кнопкам! В них будет как бы неприкосновенно храниться состояние сдвга. :) А уж их можно AND'ить, OR'ить и вообще что угодно, но не трогая их значение - с помещением результата в новую переменную...

Ссылка на комментарий
Поделиться на другие сайты

все сделал, как Вы рекомендуете.   n++; - для первой, m++; - для второй, k=n+m; - их сумма, s=k-n; - условие для выхода. А проскакивает, видимо, из-за того, что бывают моменты когда обе кнопки нажаты одновременно. 

Ссылка на комментарий
Поделиться на другие сайты

На самом деле, не очень понятно о каких сдвигах идёт речь и какие состояния должны быть при нажатии кнопок.
Опишите поподробнее.

PS: Когда выкладываете код, обрамляйте его в специальный тег.
 

Ссылка на комментарий
Поделиться на другие сайты

изменил код, кажется стало лучше.

Скрытый текст

#include <mega8.h>    // частота CP 8мгц. 
#include <delay.h>
unsigned char n = 0;
unsigned char m = 0;
unsigned char k = 0;
unsigned char temp = 0;
void main(void) {              // начало программы 
DDRD = 0xFF; PORTD = 0x00; // выход -  PORTD. 
DDRC = 0x00; PORTC=0x03;   // входы - PC0 и PC1. подключаем нагрузочные резисторы к PC0 и PC1
PORTD = 0xFF; delay_ms(1000); PORTD = 0x00; // мигнуть для проверки лампочек
while(1) {  // главный цикл 
if(k!=9) { while(PINC==3) {PORTD=temp;} }  // если сумма не равна 5, если нет нажатий, то топчемся 
if (PINC.0==0) {n++; while(PINC.0==0)  {delay_ms(10);} if (n>8) n=0; }    // если есть нажатие n
if (PINC.1==0) {m++; while(PINC.1==0) {delay_ms(10);} if (m>8) m=0; }  // если есть нажатие m
k=n+m; delay_ms(1); if (k==9) {    // вычисляем сумму, если равна 5, то делаем выбор на выход
switch (n) {
case 1: PORTD=1;     if(PINC==3) { while(PINC==3) {PORTD=1;} }   else {n=0; m=0;} break;  
case 2: PORTD=2;     if(PINC==3) { while(PINC==3) {PORTD=2;} }   else {n=0; m=0;} break; 
case 3: PORTD=4;     if(PINC==3) { while(PINC==3) {PORTD=4;} }   else {n=0; m=0;} break;
case 4: PORTD=8;     if(PINC==3) { while(PINC==3) {PORTD=8;} }   else {n=0; m=0;}  break;  
case 5: PORTD=16;   if(PINC==3) { while(PINC==3) {PORTD=16;} }  else {n=0; m=0;} break; 
case 6: PORTD=32;   if(PINC==3) { while(PINC==3) {PORTD=32;} }  else {n=0; m=0;} break;
case 7: PORTD=64;   if(PINC==3) { while(PINC==3) {PORTD=64;} }  else {n=0; m=0;} break;
case 8: PORTD=128; if(PINC==3) { while(PINC==3) {PORTD=128;} } else {n=0; m=0;} break; }
delay_ms(1); temp = PORTD;}
} }   

 

А смысл такой. Первая кнопка управляет регистром сдвига Р1 (типа 561ие8), вторая тоже, но другим Р2. Далее надо сложить их состояния и вывести на выход при условии (1+8 =1, 2+7=2, 3+6=3, 4+5=4.......8+1=8).  Всё.

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

Всё равно ничего не понял, видимо у меня сегодня с кумекалкой что-то не то :D

44 минуты назад, Igor-13 сказал:

надо сложить их состояния и вывести на выход

Вывести состояния или их сумму ?
Судя по коду, Вы выводите 1,2,4,8,... Ни состояния, ни сумма никак не клеится к этим значениям :unsure:

44 минуты назад, Igor-13 сказал:

при условии (1+8 =1, 2+7=2, 3+6=3, 4+5=4.......8+1=8).

А если будет 1+5 ? Или, например, 5+3 ? Что тогда ?
Тут никак не могу догнать, что это за суммы и условия ...

Да и причём тут сдвиговые регистры, тоже не понятно, т.к. Вы просто считаете кол-во нажатий.

Ссылка на комментарий
Поделиться на другие сайты

да, я был слишком краток.

Каждое нажатие кнопки - это один шаг виртуального сдвигового регистра на 8 позиций (по кольцу).  

Состояния двух сдвиговых регистров Р1 и Р2 складываются. Если сумма = 8, то на выходе порта С горит только одна лампочка, в соответствии с состоянием первого регистра. Мой код опять не так работает. У меня логики в уме не хватает добить до конца, поэтому и мучаю тему. 

Р1 и Р2 должны крутиться сами по себе от кнопок С0 и С1. А у меня почему-то они друг от друга зависимы, Р1 не двигается, пока не сдвину Р2, 

и вот я не знаю как исправить это.

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

Ага, теперь понятно...
Ну первым, что бросается в глаза, это немного неверный опрос кнопок. Нужно по условию делать сразу задержку (прождать дребезг), а после неё уже ждать отпускания.

if (PINC.0==0) {    // если есть нажатие n
  delay_ms(10);
  while(PINC.0==0); // Ждём отпускания
  n++;              // Инкремент переменной
  if (n>8) n=0;     // Проверка на переполнение
}

Далее. Зачем так много всего ненужного в case'ах ? Какие-то чтения PINC, условия, вайлы, ... Там же, всего-лишь, нужно вывести значение, и всё. Причём значение, равное единице, сдвинутой на n-1.
Все кейсы можно выкинуть к чертям собачьим и сделать вот так :

PORTD=1<<(n-1);

 

У Вас задача то элементарная, а Вы программу понакрутили, что мозг можно сломать :)

Ссылка на комментарий
Поделиться на другие сайты

антидребезг я понял, сделаю. А PORTD=1<<(n-1); будет как работать? сам по себе? - не понял. наверное надо m тоже сделать как PORTD=1<<(m-1); или 

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

if (PINC.0==0) {    // если есть нажатие n
  delay_ms(10);
  while(PINC.0==0); // Ждём отпускания
  n++;              // Инкремент переменной
  if (n>8) n=8;     // Я бы сделал лучше так. Не обнулял, а просто не давал бы выйти за 8 и ждать нажатия другой кнопки, для суммы, равной 9-ти
}
if (PINC.1==0) {    // если есть нажатие m
  delay_ms(10);
  while(PINC.1==0); // Ждём отпускания
  m++;              // Инкремент переменной
  if (m>8) m=8;     // 
}
if((n+m)>=9){
  PORTD=1<<(n-1);
  n=m=0;
}

 

Вот вся Ваша программа :)

Ссылка на комментарий
Поделиться на другие сайты

7 минут назад, Alex сказал:

Вот вся Ваша программа

сейчас прошью, проверю.

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

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

8 минут назад, Alex сказал:

Покажите весь код, который собираетесь прошить.

#include <mega8.h>    // частота CP 8мгц. 
#include <delay.h>
unsigned char n = 0;
unsigned char m = 0;
unsigned char k = 0;
unsigned char temp = 0;
void main(void) {              // начало программы 
DDRD = 0xFF; PORTD = 0x00; // выход -  PORTD. 
DDRC = 0x00; PORTC=0x03;   // входы - PC0 и PC1. подключаем нагрузочные резисторы к PC0 и PC1
PORTD = 0xFF; delay_ms(1000); PORTD = 0x00; // мигнуть для проверки лампочек
while(1) {  // главный цикл 
if (PINC.0==0) {    // если есть нажатие n
  delay_ms(10);
  while(PINC.0==0); // Ждём отпускания
  n++;              // Инкремент переменной
  if (n>8) n=8;     // Я бы сделал лучше так. Не обнулял, а просто не давал бы выйти за 8 и ждать нажатия другой кнопки, для суммы, равной 9-ти
}
if (PINC.1==0) {    // если есть нажатие m
  delay_ms(10);
  while(PINC.1==0); // Ждём отпускания
  m++;              // Инкремент переменной
  if (m>8) m=8;     // 
}
if((n+m)>=9){
  PORTD=1<<(n-1);
  n=m=0;
}
} } 

обнулять n и m надо обязательно

Изменено пользователем Igor-13
Ссылка на комментарий
Поделиться на другие сайты

ну, вот. первое нажатие первой кнопки. потом нажимаю вторую кнопку. при восьми нажатиях должна загореться первая лампочка (в смысле светодиод). Далее. нажимаю вторую кнопку, а лампочка не тухнет (а должна, т.к. ((n+m) не равно 9)

Ссылка на комментарий
Поделиться на другие сайты

Ах вот оно что, Михалыч :)
Да, в этом варианте они не гаснут, а только меняются после очередного нажатия кнопок 8 раз.

3 минуты назад, Igor-13 сказал:

при восьми нажатиях должна загореться первая лампочка

А она загорается, кстати ? Алгоритм работает ?

Ссылка на комментарий
Поделиться на другие сайты

М.Б. так ?

#include <mega8.h>    // частота CP 8мгц. 
#include <delay.h>
unsigned char n = 0;
unsigned char m = 0;
unsigned char k = 0;
unsigned char temp = 0;
void main(void) {              // начало программы 
DDRD = 0xFF; PORTD = 0x00; // выход -  PORTD. 
DDRC = 0x00; PORTC=0x03;   // входы - PC0 и PC1. подключаем нагрузочные резисторы к PC0 и PC1
PORTD = 0xFF; delay_ms(1000); PORTD = 0x00; // мигнуть для проверки лампочек
while(1) {  // главный цикл
temp=0;
if (PINC.0==0) {    // если есть нажатие n
  delay_ms(10);
  while(PINC.0==0); // Ждём отпускания
  n++;              // Инкремент переменной
  if (n>8) n=8;     // Я бы сделал лучше так. Не обнулял, а просто не давал бы выйти за 8 и ждать нажатия другой кнопки, для суммы, равной 9-ти
  temp=1;
}
if (PINC.1==0) {    // если есть нажатие m
  delay_ms(10);
  while(PINC.1==0); // Ждём отпускания
  m++;              // Инкремент переменной
  if (m>8) m=8;     // 
  temp=1;
}
if(temp){
  if((n+m)>=9){
    PORTD=1<<(n-1);
    n=m=0;
  }
  else{
    PORTD=0;
  }
}
} 
} 
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...