|
Подскажите начинающему, Keil |
|
|
|
Oct 9 2010, 18:09
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Очень заинтересовался программированием микроконтроллеров. Сейчас изучаю Keil и язык C. Имеется железка на микроконтроллере ADuC842. Начал с малого. Решил написать программу, которая просто заставляет загореться два светодиода из четырёх. Написал. Получилось, работает. Сейчас решил написать программу, суть которой заключается в том, что надо нажать на кнопку и светодиод загорится, если ещё раз нажать на кнопку, то светодиод тухнет. Бился целый день, но не получается.
Согласно схеме: на светодиод надо подать 0, чтобы он загорелся, на кнопку надо тоже подать 0, чтобы она сработала и заставила загореться светодиод. Порты прописывал следующим образом: sbit P1_1=0x11 (например светодиод) и P2_1=0x22 (например кнопка). Адреса портов 0x00 условные, т.е. по спецификации я знаю правильный адрес, это для примера привел.
Подскажите, расскажите, объясните. Выслушаю всех, очень хочу научиться.
|
|
|
|
|
Oct 10 2010, 07:07
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(rezident @ Oct 10 2010, 02:02)  Не нужно подавать на пин, к которому подключена кнопка лог."0", а нужно опрашивать состояние этого пина и включать светодиод, если состояние кнопки изменилось. Соответственно на пине к которому подключена кнопка нужен pull-up резистор, либо используйте внутренний pull-up (если он есть в этом МК). а можете пример привести. На счёт резистора не знаю, сейчас буду смотреть спецификацию.
|
|
|
|
|
Oct 10 2010, 08:01
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Периферию вашего контроллера я не знаю, а изучать ее специально нет особого желания. Примерно вот так Код #define PIN_KEY (1<<2) //кнопка подключена к P3.2 и к DGND, к P3.2 подключен pull-up резистор #define PIN_LED (1<<1) //светодиод катодом подключен к P3.1, анодом через балластный резистор к +DVDD
#define MAXCOMP 15U #define MAXCNTR 1000U #define KEY_NULL 0x00 #define KEY_SET 0x01
unsigned int cntr, comp; unsigned char key;
void main (void) { /* тут секция для начальной инициализации периферии */ /* конец секции начальной инициализации периферии */ P3 &= PIN_LED^0xFF; key = KEY_NULL; for(;;) { if ((P3&PIN_KEY) == 0) //засекли нажатие кнопки? { comp = 0; cntr = 0; do //устраняем дребезг { if ((P3&PIN_KEY) == 0) comp++; else comp = 0; if (comp >= MAXCOMP) //состояние устойчивое? { key = KEY_SET; break; } cntr++; } while (cntr < MAXCNTR); if (cntr >= MAXCNTR) //дребезг устранить не удалось? key = KEY_NULL; } if (key == KEY_SET) //кнопка нажата? P3 &= PIN_LED^0xFF; //включим LED else P3 |= PIN_LED; //иначе выключим LED } } Времена устранения дребезга можно изменить значениями дефайнов. Если нужен триггерный эффект, то замените простую проверку кода кнопки на смену ее состояния. Добавим еще одну переменную Код unsigned char lastkey = KEY_NULL; Изменим способ проверки факта нажатия и переключение светодиода Код if ( (key == KEY_SET) && //кнопка нажата? И (lastkey == KEY_NULL) ) // до этого она была не нажата? P3 ^= PIN_LED; //переключим состояние LED lastkey = key; //обновим состояние кнопки
Сообщение отредактировал rezident - Oct 10 2010, 08:16
|
|
|
|
|
Oct 10 2010, 10:48
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
rezident спасибо, а что такое P3?
|
|
|
|
|
Oct 10 2010, 11:12
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(rezident @ Oct 10 2010, 18:05)  Порт P3, к которому якобы подключены кнопка и светодиод. Я еще раз повторяю, что не знаю ни вашего МК, ни его периферии, ни обозначений его портов в Keil. Кнопка и светодиод к разным портам подключены. sbit P3_6=0xB6; - диод sbit P1_2=0x92; - кнопка
Сообщение отредактировал Djumper - Oct 10 2010, 11:12
|
|
|
|
|
Oct 10 2010, 11:52
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Ну дык замените в дефайнах номера битов и далее по тексту чтение из порта P3 на чтение из порта P1. Код #define PIN_KEY (1<<2) //кнопка подключена к P1.2 и к DGND, к P1.2 подключен pull-up резистор #define PIN_LED (1<<6) //светодиод катодом подключен к P3.6, анодом через балластный резистор к +DVDD Код if ((P1&PIN_KEY) == 0)
|
|
|
|
|
Oct 12 2010, 15:00
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Дребезг и т.д. это слишком сложно для меня, на сколько я помню программа состоит из нескольких строк, жаль что я не записал её когда было время. По сути дела должно быть так??? sbit PIN_LED = 0xB6; sbit PIN_KEY = 0x92; #define KEY_NULL 0x00 #define KEY_SET 0x01 unsigned int key; void main (void) { for(;;) { if (key == KEY_SET) PIN_LED = 0x00; else PIN_LED = 0x01; } } Но не работает. Может где-то ошибку допустил. Помогите исправить и объяснить. Кнопка S2 (P1.2; 0x92), светодиод любой из четырёх (P3.4, Р3.5, Р3.6, Р3.7; 0xB4, 0xB5, 0xB6, 0xB7)
Сообщение отредактировал Djumper - Oct 12 2010, 15:05
Эскизы прикрепленных изображений
|
|
|
|
|
Oct 12 2010, 16:09
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Djumper @ Oct 12 2010, 21:00)  Но не работает. Может где-то ошибку допустил. Помогите исправить и объяснить. Для того чтобы понять причину, представьте себя на месте исполнителя вашей программы и попытайтесь по шагам мысленно исполнить ее  Для того, чтобы загорелся светодиод должны выполниться инструкция PIN_LED = 0x00; Но для того чтобы выполнилась эта инструкция условие if (key == KEY_SET) должно быть истинным, т.е. в переменной key должно быть значение KEY_SET. А откуда там возьмется это значение, если ни вы и никто другой его туда не записал? В сообщении #4 я привел практически готовую программу.
|
|
|
|
|
Oct 12 2010, 16:54
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(firstvald @ Oct 12 2010, 23:35)  Вы фактически реализуете счетный триггер, но при этом на входе у вас при каждом нажатии целая серия импульсов. Обычно у кнопки переходный процесс длиться до 20 миллисекунд, когда ее контакт то замкнут то разомкнут. Да и после переходного процесса могут быть "шуршавчики" в замкнутом состоянии. Поэтому упростите свою задачу до безобразия для начала - нажали кнопку - загорелся светодиод. Отпустили - погас. Потом будем дальше усложнять. Например так? sbit PIN_LED = 0xB6; sbit PIN_KEY = 0x92; unsigned int KEY_NULL1=0; unsigned int PIN_LED1=0; unsigned int PIN_LED2=1; void main (void) { for(;;) { if (PIN_KEY == KEY_NULL1) PIN_LED = PIN_LED1; else PIN_LED = PIN_LED2; } }
Сообщение отредактировал Djumper - Oct 12 2010, 16:55
|
|
|
|
|
Oct 12 2010, 17:40
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(firstvald @ Oct 13 2010, 00:18)  Давайте еще проще:
void main (void) { P1=0xff;//иначе может оказаться случайным P3=0xff;//
while(1){ if (P1&0x04 ==0 )//нажали {P3=P3&(~0x08);}//зажгли else {P3=P3|0x08;}//погасили } } P1_2=0x92; P3_6=0xB6; void main (void) { while(1){ if (P1_2&0x04 ==0 ) {P3_6=P3_6&(~0x08);} else {P3_6=P3_6|0x08;} } } Не хочет работать программа. Железка проверенная, должна работать.
|
|
|
|
|
Oct 12 2010, 18:34
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(firstvald @ Oct 13 2010, 00:51)  Нет. Я специально написал безо всяких битовых операций - именно работаем с портом как с байтом, целиком. Вы уже на глупость переправили.
Попробуем просто зажечь а потом просто погасить
sfr P1 = 0x90; //проверьте есть ли такие строчки в начале программы или в подключаемом заголовочном файле sfr P3 = 0xB0; // void main (void) { P1=0xff;//иначе может оказаться случайным P3=0xff;//
while(1){ P3=P3&(~0x08);//зажгли } } хорошо, завтра проверю, спасибо за объяснения
|
|
|
|
|
Nov 17 2010, 14:03
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
С кнопкой с горем пополам разобрался  Хочу собрать вот такое устройство http://avrlab.com/node/63Обычный микроконтроллер, три светодиода и т.д. Схема понятна, спаяю без проблем. Одно не понятно, как мне подключить это устройство к компьютеру? Какие контакты использовать и т.д.? Как я понимаю надо USB, но вот куда его подключать к микроконтроллеру, я не знаю. Как прошивать это устройство, какую программу для прошивки использовать? (имею ввиду, не ту программу которую надо в Keil написать, а софт которым прошивать) Объясните пожалуйста.
|
|
|
|
|
Nov 18 2010, 11:12
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата Одно не понятно, как мне подключить это устройство к компьютеру? Никак. Оно 'вещь в себе', к компу не подключается Цитата Как я понимаю надо USB, но вот куда его подключать к микроконтроллеру, я не знаю. К Tiny13 USB напрямую подключить нельзя. Понадобится переходник (на FT245 например). Или возьмите МК который поддерживает USB напрямую Цитата Как прошивать это устройство, Программатором. Железным. Их в сети море (и в магазине тоже). Цитата какую программу для прошивки использовать? Этого добра тоже навалом. avreal например. PonyProg. Да и сама AVRStudio умеет что то прошивать.
|
|
|
|
|
Nov 18 2010, 17:35
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(XVR @ Nov 18 2010, 18:12)  Программатором. Железным. Их в сети море (и в магазине тоже). Как я понял, я приобретаю программатор для микропроцессоров, допустим MCS-51, подключаю к компу, беру "голый" микроконтроллер, вставляю его в программатор, т.е. соответствующие "ножки" микроконтроллера в "дырочки" на программаторе. Качаю программу для прошивания микроконтроллера. Пишу программу в Keil. Прошиваю hex файлом микроконтроллер. Вытаскиваю микроконтроллер из программатора. Собираю схему. Включаю. Радуюсь. Так?
|
|
|
|
|
Nov 19 2010, 13:20
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Как подключить библиотеку delay.h в Keil 3? Пишет что нету её. Где взять? Или она по другому называется?
Хочу сделать задержку. Светодиод горит - через определённое количество секунд гаснет - через определённое количество секунд снова загорается.
|
|
|
|
|
Nov 21 2010, 14:48
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Возможно эта библиотека называется как-то по другому, не delay.h. Или есть другие возможности сделать задержку? Что-то вроде через 500 мс светодиод загорается, через 200 мс светодиод гаснет. Без delay я не знаю как ещё это можно сделать. Подскажите.
|
|
|
|
|
Nov 24 2010, 17:39
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Кое как со скрипам научился делать что-то вроде задержки, без всяких библиотек и delay-ев. С помощью таймеров! Использовал микроконтроллер ADuC842. Делал по книжке, так сказать, просто заменял цифры в готовой программе и делал разный период мигания светодиода. Цифры брал не от балды, а высчитывал сам по формуле и делал ту задержку которую мне надо. Осталось разобраться с программой. Помогите кто знает, укажите что так что не так, я сейчас напишу комментарии, а вы укажите что не так.
sfr TMOD=0x89; //тут всё стандартно, перечисляем порты микроконтроллера sfr TCON=0x88; sfr TH1=0x8D; //TH1 и TL1 старший и младший разряды таймера работающие в первом режиме? указываем их порты? sfr TL1=0x8B; sfr P0=0x80; sbit TF1=TCON^7; //вот эти две строчки не понял что означают. и цифры что означают 7 и 6? sbit TR1=TCON^6; sbit P0_0 = P0^0; //тут всё ясно, опять таки что означают цифры 0,1,2,3? исключающее ИЛИ для чего? sbit P0_1 = P0^1; sbit P0_2 = P0^2; sbit P0_3 = P0^3; main () { int i; TMOD=0x10; //сконфигурировали таймер как 8-битный тамер счётчик??? TCON=0xC0; //сконфигурировали регистр управления таймером ... как...??? for (i=1;i<100;i++) { TH1 = 13453 >> 8; //число высчитал по формуле, это не важно, тут вроде разобрался TL1 = 13453; TR1 = 1; while (!TF1); TF1 = 0; } P0_0 = 0; P0_1 = 0; P0_2 = 0; P0_3 = 0; for (i=1;i<100;i++) { TH1 = 13453 >> 8; //тут опять какое-то повторение, можно обойтись без него? а понял смысл, предыдущие идентичные команды - светодиод не горит "такое-то" время, а эти команды - светодиод горит "такое-то" время. TL1 = 13453; TR1 = 1; while (!TF1); TF1 = 0; } P0_0 = 0; P0_1 = 0; P0_2 = 1; //загорается "такой-то" светодиод P0_3 = 0; }
Сообщение отредактировал Djumper - Nov 24 2010, 17:42
|
|
|
|
|
Nov 25 2010, 06:29
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Djumper @ Nov 24 2010, 20:39)  sfr TH1=0x8D; //TH1 и TL1 старший и младший разряды таймера работающие в первом режиме? указываем их порты? Для SFR с адресом 8Dh определяется символическое имя - TH1. Это имя впоследствии используется в программе. Цитата(Djumper @ Nov 24 2010, 20:39)  sbit TF1=TCON^7; //вот эти две строчки не понял что означают. и цифры что означают 7 и 6? sbit TR1=TCON^6; sbit P0_0 = P0^0; //тут всё ясно, опять таки что означают цифры 0,1,2,3? исключающее ИЛИ для чего? sbit P0_1 = P0^1; sbit P0_2 = P0^2; sbit P0_3 = P0^3; Для отдельных битов SFR определяются символические имена. Например, запись P0^0 означает нулевой бит регистра специальных функций с именем P0. Такая запись битов "проходит" не во всех трансляторах. PS. Обычно с транслятором поставляется файл в котором уже определены все регистры и их биты в соответствии с DS на конкретный МК. Вместо определения их в программе (т.е. всех этих строк с sfr и sbit) записывают строчку препроцессора Код #include <ADuC842.h>
|
|
|
|
|
Nov 25 2010, 08:12
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Djumper @ Nov 24 2010, 20:39)  P0_2 = 1; //загорается "такой-то" светодиод Эдесь, скорее всего, "какой-то" светодиод - погаснет. Посмотрите внимательно в DS: как устроен выход паралельного порта - при выводе в порт нуля соответствующая ножка "замыкается" на "землю" ключем, а при выводе единицы - высокий уровень на ножке обеспечивается подтягивающим резистором. Чтобы загорелся светодиод - его включают между ножкой МК и плюсом питания через резистор, при этом светодиод горит при нуле на ножке МК. МК51 ("классика") может обеспечить достаточный для зажигания светодиода ток (и то не на всех портах) только при нуле на ножке МК (втекающий ток). Цитата(Djumper @ Nov 24 2010, 20:39)  TMOD=0x10; //сконфигурировали таймер как 8-битный тамер счётчик??? Устанавливается "режим 1" работы таймера. В этом режиме счет идёт до FFFFh (т.е. шестнадцатибитный счетчик), при переполнении (FFFF -> 0000) устанавливается бит TF1. Цитата(Djumper @ Nov 24 2010, 20:39)  TCON=0xC0; //сконфигурировали регистр управления таймером ... как...??? Устанавливаются биты TF1 и TR1. Imho, эта строка - лишняя: бит TR1 и так устанавливается несколько ниже, а бит TF1 - в данном случае устанавливать как раз и не надо: его появление при переполнении счетчика ожидается в цикле.
|
|
|
|
|
Nov 29 2010, 11:42
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(Палыч @ Nov 25 2010, 13:29)  Спасибо за подсказку! Цитата(Палыч @ Nov 25 2010, 15:12)  Эдесь, скорее всего, "какой-то" светодиод - погаснет. Посмотрите внимательно в DS: как устроен выход паралельного порта - при выводе в порт нуля соответствующая ножка "замыкается" на "землю" ключем, а при выводе единицы - высокий уровень на ножке обеспечивается подтягивающим резистором. Чтобы загорелся светодиод - его включают между ножкой МК и плюсом питания через резистор, при этом светодиод горит при нуле на ножке МК. МК51 ("классика") может обеспечить достаточный для зажигания светодиода ток (и то не на всех портах) только при нуле на ножке МК (втекающий ток). У меня (точнее на микроконтроллере на работе, он не мой  ) согласно схеме, светодиод подключен немного по другому: "минус" светодиода через резистор R1 подключен к коллектору транзистора, "плюс" светодиода подключен через резистор R2 к базе транзистора (сюда подаётся + напряжения питания, а этот резистор служит для усиления тока базы), эмиттер подключен к "земле" (-). И уже через базу транзистора мы подключаемся к выводу микроконтроллера. Как я понял благодаря этому резистору R2, вместо 0 для включения светодиода, мы имеем 1 для включения светодиода. Спасибо за подсказки! Кстати никто не поможет написать простую программу, что-то вроде ввода пароля на микроконтроллере: вводим с помощью клавиатуры матричного типа известные цифры (пароль), светодиод загорается, если пароль введён не верно, то ничего не происходит. С меня подробная принципиальная схема устройства для которого пишется программа. Документация. Само устройство есть в пользовании. И я готов за работу даже денюшку дать, минимум 10$. Короче мне нужен учитель для создания этой программы
Сообщение отредактировал Djumper - Nov 29 2010, 11:48
|
|
|
|
|
Dec 16 2010, 15:04
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Сам написал программу! Всё же приятно самому сделать что-то работающее. Получилась немного кривая программа. Писал программу пользуясь другими программами, т.е. пришлось перерыть много "литературы", чтобы найти то что нужно. Что получилось: хотел написать программу типа кодового замка, получилось, что-то вроде: жмём три кнопки 1,6,8 по очереди, загорается один, два и три светодиода (нажали нужные кнопки). Причём в обратном направлении кнопки 8,6,1 также жмутся и светодиоды загораются, реализовать код не получилось. Что хочу получить в новой версии программы, но не знаю как это реализовать:чтобы светодиоды загорались только при нажатии на кнопки 1,6,8. И чтобы когда загорелся третий светодиод, загорались все четыре светодиода и продолжали гореть, а при нажатии на любую кнопку они прекращали гореть. Выслушаю любые советы и подсказки. sfr P0=0x80; //ну тут стандартно, решил расписать каждую "ножку" отдельно, чтобы было легче писать программу и чтобы не запутаться sfr P1=0x90; sbit P0_0=0x80; //1 светодиод sbit P0_1=0x81; //2 светодиод sbit P0_2=0x82; //3 светодиод sbit P0_3=0x83; //4 светодиод sbit P0_4=0x84; //1 столбец клавиатуры матричного типа sbit P0_5=0x85; //2 столбец sbit P0_6=0x86; //3 столбец sbit P1_0=0x90; //1 строка sbit P1_1=0x91; //2 строка sbit P1_2=0x92; //3 строка sbit P1_3=0x93; //4 строка int k; char a[3]; //переменная "а" будет содержать 3 символа? или состоит из матрицы с 3 столбцами? main() { char b[3]={'1','6','8'}; //это вроде как значение кода, но он не работает или это что-то другое? переменная, то для чего? inception: P0=0; P1=0;//inception я придумал название, это же переменная? while(k!=3) //почему "k" не равно 3??? когда будет больше нажатий то обнулиться? { P0_4=0; P0_5=1; P0_6=1; //ну тут на 1 столбец 0 подаём, что означает что на этом столбце будет нажата какая-то клавиша if (P1_0==0) {k++; while(P1_0==0) a[k]='1'; //указали строку, нажата 1 клавиша, добавили к "k" единичку, далее пока клавиша нажата, то что? переменная "а" равна 1 кодовому символу? P0_3=1; P0_2=0; P0_1=0; P0_0=0;} //включаем светодиод подавая 1 (специфичная схема  ) P0_4=1; P0_5=1; P0_6=0; if (P1_1==0) {k++; while(P1_1==0) a[k]='6'; P0_3=0; P0_2=1; P0_1=0; P0_0=0;} P0_4=1; P0_5=0; P0_6=1; if (P1_2==0) {k++; while(P1_1==0) a[k]='8'; P0_3=0; P0_2=0; P0_1=1; P0_0=0;} } //тут охота чтобы после третьей нажатой клавиши загорались все 4 светодиода и продолжали гореть пока не нажму на любую другую клавишу goto inception; //идём к "началу" и повторяем цикл? } PS: не важно в каком порядке буду код вводить, подскажите как включить все 4 светодиода и выключить их при нажатии на любую клавишу. Спасибо!
Сообщение отредактировал Djumper - Dec 16 2010, 15:06
|
|
|
|
|
Dec 17 2010, 13:46
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Djumper @ Dec 16 2010, 21:04)  Выслушаю любые советы и подсказки. Попробую подсказать Бесконечный цикл реализуется проще так: вместо Код inception: P0=0; P1=0;//inception я придумал название, это же переменная? ....... goto inception; записываем Код for(;;) { P0=0; P1=0; ....... } Далее - матричная клавиатура... Работает считывание нажатых кнопок так: на один из столбцов выдаем низкий уровень (0), на остальные - высокий (1). Считываем значение строк и, там где будет низкий - там нажата кнопка на "пересечении" строки и столбца. Чтобы было Вам понятнее, рекомендую оформить отдельные функциональные части Вашей программы как функции. Например, функция возвращающая нажатые в данный момент кнопки может выглядеть как-то так (подстоюсь под Ваш стиль, чтобы было Вам понятнее): Код unsigned int GetButton(void) { unsigned int x; P0_4= 1; P0_5= 1; P0_6= 0; // Третий столбец x= ((~P1) & 0x0F); // Считали четыре кнопки третьего столбца (P1_0 ... P1_3) P0_4= 1; P0_5= 0; P0_6= 1; // Второй столбец x= (x << 4) | ((~P1) & 0x0F); // Добавили четыре кнопки второго столбца (P1_0 ... P1_3) P0_4= 0; P0_5= 1; P0_6= 1; // Первый столбец x= (x << 4) | ((~P1) & 0x0F); // Добавили четыре кнопки первого столбца (P1_0 ... P1_3) return x; } Эта функция возвращает шестнадцатибитовое значение, 12 младших разрядов которого означают состояние кнопок: 4 младших - на первом столбце, следующие четыре - на втором, и ещё четыре - на третьем. Причем, 1 - кнопка нажата (обратите внимание на инверсию разрядов - (~P1) ). Можно написать и функцию зажигания/тушения светодиодов: Код void LED(unsigned char L) { P0= (P0 & 0xF0) | (L & 0x0F); } Параметр этой функции: младшие четыре бита - состояния светодиодов (младший - первый, и т.д.) Тогда Ваша программа будет выглядеть как-то так: Код void main(void) { unsigned char P; // Три младших бита этой переменной - признаки нажатия трёх "секретных" кнопок (оно же состояние трёх светодиодов) const unsigned int B[3]= { 0x0001, 0x0020, 0x0080 }; // Коды "секретных" кнопок: первая(первый столбец-первая строка), шестая(2-2) и восьмая(2-4) P= 0; // Кнопки нажаты не были LED(0); // Светодиоды погашены for(;;) { unsigned int x; // Текущее состояние кнопок x= GetButton(); if((x & B[0]) != 0) { // Среди нажатых кнопок есть первая секретная P= P | (1 << 0); // Зафиксировали этот факт x= x & (~B[0]); // Удалим её из переменной с нажатыми кнопками } if((x & B[1]) != 0) { // Среди нажатых кнопок есть вторая секретная P= P | (1 << 1); x= x & (~B[1]); } if((x & B[2]) != 0) { // Среди нажатых кнопок есть третья секретная P= P | (1 << 2); x= x & (~B[2]); } // Обратите внимание, что выше напрашивается цикл, но сделал без цикла, чтобы было Вам понятнее - переделаете сами... if(x != 0) // Нажата ещё какая-то кнопка, которая не входит в список секретных? P= 0; // Да, нажата ещё какая-то кнопка: Все - как бы сначала (т.е. сбросить признаки нажатия кнопок, потушить светодиоды) if(P == 0x07) // Все ли секретные кнопки были нажаты? LED(P | 0x08); // или LED(0x0F); Да! Все три кнопки были нажаты - зажечь 4 светодиода else LED(P); // Зажечь те светодиоды, что соответствуют нажатым секретным кнопкам } } Ну - вот... Как-то так... P.S. Может-быть я не понял Вашу задачу? Например, нужно ли соблюдать порядок нажатия на "секретные" кнопки? В приведенной выше программке - порядок нажатия безразличен. Это - не трудно исправить... Три светодиода я "привязал" к трем "секретным" кнопкам - т.е. нажали вторую "секретную" кнопку - второй светодиод и загорелся, первую кнопку - первый светодиод... А как Вы хотели? Научитесь четко формулировать задачу: хорошая формулировка - считай - половина работы сделана!
|
|
|
|
|
Dec 18 2010, 08:21
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Цитата(Палыч @ Dec 17 2010, 22:46)  P.S. Может-быть я не понял Вашу задачу? Например, нужно ли соблюдать порядок нажатия на "секретные" кнопки? В приведенной выше программке - порядок нажатия безразличен. Это - не трудно исправить... Три светодиода я "привязал" к трем "секретным" кнопкам - т.е. нажали вторую "секретную" кнопку - второй светодиод и загорелся, первую кнопку - первый светодиод... А как Вы хотели? Научитесь четко формулировать задачу: хорошая формулировка - считай - половина работы сделана! Спасибо за подсказки, к сожалению нет возможности проверить ваш вариант программы, т.к. микроконтроллер будет доступен только на следующей неделе, но мне бы хотелось просто доработать свой вариант программы. В принципе, пусть "секретные" кнопки нажимаются как угодно, не обязательно по порядку (хотя какой это замок с КОДОМ?  ), мне главное суть уловить и из вашей программы я уловил суть как сделать что-то вроде кода! Спасибо! Сейчас я бы хотел просто сделать так, что после третьей кнопки (в моей программе) загорались все 4 светодиода и продолжали гореть пока я не нажму на любую другую кнопку. Подскажите и я вам буду очень благодарен  PS: кстати, прочтите мои комментарии к моей программе, правильно ли я понимаю как работает программа?
|
|
|
|
|
Dec 18 2010, 09:08
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Djumper @ Dec 18 2010, 14:21)  Подскажите и я вам буду очень благодарен  PS: кстати, прочтите мои комментарии к моей программе, правильно ли я понимаю как работает программа? Поскольку из Ваших коментариев трудно понять, что же вы хотели сделать, то написанное ниже - мои фантазии на эту тему... Код char a[3]; //переменная "а" будет содержать 3 символа? или состоит из матрицы с 3 столбцами? Массив с именем а состоит из трёх элементов, каждый из которых - символ. Imho, сюда Вы ходели поместить некие символы, соответствующие нажатым клавишам. Код char b[3]={'1','6','8'}; //это вроде как значение кода, но он не работает или это что-то другое? переменная, то для чего? Наверное, этот массив, с которым нужно бы сравнить массив а после нажатия трёх клавиш. Код inception: P0=0; P1=0;//inception я придумал название, это же переменная? Это - не переменная, это - метка. Как лучше оформлять бесконецный цикл - см. мой предыдущий пост: тогда сразу видно, что этот цикл - бесконечный. Код while(k!=3) //почему "k" не равно 3??? когда будет больше нажатий то обнулиться? Imho, не равно 3, потому, что Вы ожидаете нажатие трёх кнопок. Значение переменной k изменяется в цикле (операторы k++), обнулять эту переменную нужно самому (автоматически это не делается). Код if (P1_0==0) {k++; while(P1_0==0) a[k]='1'; //указали строку, нажата 1 клавиша, добавили к "k" единичку, далее пока клавиша нажата, то что? переменная "а" равна 1 кодовому символу? Вы, вероятно путаете символ '1' со значением 1... Поскольку в начале переменная k равнялась нулю (и то, потому, что эта переменная - глобальная; хорошо бы явно присваивать ей начальное значение), то увеличивать её значение нужно было бы после a[k]='1' (индексы массивом начинаются с нуля, т.е. первый элемент массива а[0]). Оператор while спользуется, по-видимому, для ожидания отпускания кнопки. Всё это следовало бы записать, наверное так: Код if (P1_0==0) { a[k]='1'; k++; // или так: a[k++]='1'; P0_3=1; P0_2=0; P0_1=0; P0_0=0; while(P1_0==0); } Код //тут охота чтобы после третьей нажатой клавиши загорались все 4 светодиода и продолжали гореть пока не нажму на любую другую клавишу Здесь, наверное, нужно сравнить Ваши массивы a и b, и, если они совпадают, то зажечь четвертый светодиод. Здесь же, наверное, нужно ещё и обнулить переменную k, раз Вы переходите на начало Вашего бесконечного цикла... P.S. Кнопки имеют нехорошее свойство, которое называют "дребезг контактов". Ваша программа от него не защищена! И, возможно (даже - вероятнее всего), будет улавливать нажатие одной кнопки как множественное нажатие на одну и ту же кнопку.
|
|
|
|
|
Dec 18 2010, 15:16
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Код sfr P0=0x80; sfr P1=0x90; sbit P0_0=0x80; //1 светодиод sbit P0_1=0x81; //2 светодиод sbit P0_2=0x82; //3 светодиод sbit P0_3=0x83; //4 светодиод sbit P0_4=0x84; //1 столбец клавиатуры матричного типа sbit P0_5=0x85; //2 столбец sbit P0_6=0x86; //3 столбец sbit P1_0=0x90; //1 строка sbit P1_1=0x91; //2 строка sbit P1_2=0x92; //3 строка sbit P1_3=0x93; //4 строка
int k, c; char a[3]; main() { char b[3]={'1','6','8'}; inception: P0=0; P1=0; while(k!=3) { P0_4=0; P0_5=1; P0_6=1; if (P1_0==0) {k++; while(P1_0==0) a[k]='1'; P0_3=1; P0_2=0; P0_1=0; P0_0=0;}
P0_4=1; P0_5=1; P0_6=0; if (P1_1==0) {k++; while(P1_1==0) a[k]='6'; P0_3=0; P0_2=1; P0_1=0; P0_0=0;}
P0_4=1; P0_5=0; P0_6=1; if (P1_2==0) {k++; while(P1_1==0) a[k]='8'; P0_3=0; P0_2=0; P0_1=1; P0_0=0;} } for (c=0; c<4; c++) //ввёл переменную "c": сначала "с" равно "0", пока "с" меньше 4-х то выполняется программа, правильно? if (b[c]!=a[c]) //тут сравниваем: если "b" не равно "а" то гоу в начало, правильно?
Код goto inception; } Всё равно не могу сообразить как четыре светодиода включить и сбросить.
Сообщение отредактировал Djumper - Dec 18 2010, 15:26
|
|
|
|
|
Dec 19 2010, 04:22
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Djumper @ Dec 18 2010, 21:16)  for (c=0; c<4; c++) //ввёл переменную "c": сначала "с" равно "0", пока "с" меньше 4-х то выполняется программа, правильно? Нет, неправильно. Массивы а и b состоят из трёх элементов; индексы этих элементов 0, 1, 2 (в языке Си самый первый элемент массива имеет индекс ноль); поэтому - "пока переменная с меньше трёх". Цитата(Djumper @ Dec 18 2010, 21:16)  if (b[c]!=a[c]) //тут сравниваем: если "b" не равно "а" то гоу в начало, правильно? Да, правильно. Но, скорее всего, Ваши массивы никогда не совпадут (см. PS к моему предыдущему посту). Цитата(Djumper @ Dec 18 2010, 21:16)  Всё равно не могу сообразить как четыре светодиода включить и сбросить. Вот, после выполнения цикла for(c=0; c<3; c++) т.е. после того, как проверили, что массивы совпадают и надо включить четыре светодиода. Что делать дальше? Далее нужно сканировать клавиатуру и обнаруживать нажатия на клавишу; как только нажатие клавиши будет обнаружено, то потушить диоды и - в начало.
|
|
|
|
|
Dec 19 2010, 12:35
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 9-10-10
Пользователь №: 60 027

|
Учту дребезг в будущем. На данный момент сделаю так, чтобы загорались все 4 светодиода. Правильно? Код for (c=0; c<3; c++) P0_3=1; P0_2=1; P0_1=1; P0_0=1; if (b[c]!=a[c]) Или из-за дребезга можно вообще убрать сравнение, т.к. оно врятли будет работать в нынешней моей версии программы? Т.е. просто сделать так: Код for (c=0; c<3; c++) P0_3=1; P0_2=1; P0_1=1; P0_0=1; Ой, причём тут переменная "c", нужна "k"? Код for (k=0; k<3; k++) P0_3=1; P0_2=1; P0_1=1; P0_0=1; Кстати, а можно int k, c; и char a[3]; поместить в main {}? Т.е. сделать так: Код main() { int k, c; char a[3]; char b[3]={'1','6','8'}; } Надо брать микроконтроллер с программатором на вечное пользование и учиться, а то людей отвлекаю своими вопросами
Сообщение отредактировал Djumper - Dec 19 2010, 13:18
|
|
|
|
|
Dec 20 2010, 07:00
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Djumper @ Dec 19 2010, 18:35)  На данный момент сделаю так, чтобы загорались все 4 светодиода. Правильно? Код for (c=0; c<3; c++) P0_3=1; P0_2=1; P0_1=1; P0_0=1; if (b[c]!=a[c]) Нет, неправильно. В некоторых операторах (например, циклов, ветвления...) можно разместить один оператор, а если нужно - несколько операторов, то они заключаются в операторные (фигурные) скобки. Так, как Вы написали: будет трижды (при с=0, 1, 2) выполнен один и тот же оператор (P0_3=1;). Цикл же здесь, чтобы сравнить три элемента массивов a и b. Т.е. должно быть что-то такое: Код for (c=0; c<3; c++) if (b[c]!=a[c]) // элементы совпадают ? { // нет, не совпадают // здесь помещаем все действия, что нужно выполнить при неправильном наборе goto inception; } // Сюда программа попадёт, если все три элемента массивов a и b совпадут между собой P0_3=1; P0_2=1; P0_1=1; P0_0=1; // зажечь все четыре светодиода Цитата(Djumper @ Dec 19 2010, 18:35)  можно int k, c; и char a[3]; поместить в main {}? Можно Цитата(Djumper @ Dec 19 2010, 18:35)  Надо брать микроконтроллер с программатором на вечное пользование и учиться, а то людей отвлекаю своими вопросами Ну, или, если микроконтроллер с программатором труднодоступен, то - "потренироваться на кошечках" - воспользоваться симулятором.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|