В общем в программировании микроконтроллеров я ноль... нет конечно почитал кучу "литературы", даташит и прочее, написал самую простейщую программу. Вроде бы даже прошил мк с помощью пик кит 2.
НЕ РАБОТАЕТ.
И так по порядку:
Написал в mplabX (компилятор xc8) вот такую простую программу:
Код:
// PIC16F628A Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
void podgot (void); void main (void) { podgot(); while (1) if (RA1 = 1) RB1 = 1; else RB1 = 0;
Всё просто смотрим что в порте RA1 если ноль то на RB1 ноль если на RA1 единица то и на RB1 единица и всё это крутится в бесконечном цикле. То есть простая мигалка светодиодом. Кнопку нажал диод загорелся.
2. Нарисовал схемку в протеусе и запустил симуляцию. В протеусе всё работает!
3. Подключил контроллер к програматору пиккит 2 прошил мк
На сколько я могу судить прошивка прошла успешно.
4. Подключил всё согласно схеме. Проверил питание - везде всё есть.
НЕ РАБОТАЕТ! ((((( Пожалуйста ткните носом что и где я не правильно делаю. Я уже и с битом конфигурации поигрался а толку ноль. Буду благодарен за любую помощь задолбался уже (( Заранее спасибо всем откликнувшимся!
Курил вот тут http://www.microchip.ru/lit/?mid=1x0 Видимо не той стороной ) Пожалуйста ткните пальцем какой раздел покурить ещё раз. И что подразумеваться под периферией ? Для меня это всё что прицеплено к МК но судя по всему я не прав. Поправьте меня пожалуйста.
...И что подразумеваться под периферией ? Для меня это всё что прицеплено к МК...
Возможно, я не совсем корректно сказал. Периферия - я имел ввиду то, что почти у всех контроллеров, выводы "внутри него" могут быть подключены к разным функциональным блокам. По вашему контроллеру, надо вначале смотреть TABLE 3-2 в документации по той ссылке, которую я дал. Так вот, до старта основной программы, нужно назначить выводы контроллера именно на то, что вам требуется. У всех назначений есть приоритет выбора. К примеру, если вы выбираете назначение вывода контроллера как "вход ADC" - это отменяет работу вывода как Digital In/Out. Никогда не смотрите на состояние регистров контроллера "по умолчанию". Всё нужно прописать в INIT-е (если не хотите потом получить "глюки"). И ещё: читайте документацию только от производителя. Очень часто в "переводной" документации бывают ошибки!
Открыта удобная площадка с выгодными ценами, поставляющая весь ассортимент продукции, производимой компанией MEAN WELL – от завоевавших популярность и известных на рынке изделий до новинок. MEAN WELL.Market предоставляет гарантийную и сервисную поддержку, удобный подбор продукции, оперативную доставку по России.
На сайте интернет-магазина посетители смогут найти обзоры, интересные статьи о применении, максимальный объем технических сведений.
Продукция MOSO предназначена в основном для индустриальных приложений, использует инновационные решения на основе более 200 собственных патентов для силовой электроники и соответствует международным стандартам. LED-драйверы MOSO применяются в системах наружного освещения разных отраслей, включая промышленность, сельское хозяйство, транспорт и железную дорогу. В ряде серий реализована возможность дистанционного контроля и программирования работы по заданному сценарию. Разберем решения MOSO
подробнее>>
Oleg99
Заголовок сообщения: Re: Помогите! Мигалка светодиодом не работает (
...И что подразумеваться под периферией ? Для меня это всё что прицеплено к МК...
Возможно, я не совсем корректно сказал. Периферия - я имел ввиду то, что почти у всех контроллеров, выводы "внутри него" могут быть подключены к разным функциональным блокам. По вашему контроллеру, надо вначале смотреть TABLE 3-2 в документации по той ссылке, которую я дал. Так вот, до старта основной программы, нужно назначить выводы контроллера именно на то, что вам требуется. У всех назначений есть приоритет выбора. К примеру, если вы выбираете назначение вывода контроллера как "вход ADC" - это отменяет работу вывода как Digital In/Out. Никогда не смотрите на состояние регистров контроллера "по умолчанию". Всё нужно прописать в INIT-е (если не хотите потом получить "глюки"). И ещё: читайте документацию только от производителя. Очень часто в "переводной" документации бывают ошибки!
Прежде спасибо за то что вы мне помогаете! Так... Попробую разобраться! Исходя из таблицы на которую вы ссылаете вывод RA1 может работать как на вход так и на выход. Так же к нему подключен компаратор. В моём случае я его использую как вход. (ST) Тогда нужно как-то сказать мк что именно как вход и отключит компаратор. Для этого я использовал сроку TRISA = 0b11111111; то есть весь порт А как вход. Но не сказал что компаратор выключить. Не знаю как это сделать.
RB1 имеет возможность работать как двунаправленый порт ввода-вывода. В режиме вывода он может быть только CMOS (в таблице) Строчкой TRISB = 0b00000000 я ему сказал что весь порт В это выходы. Но не сказал какую функцию исполнять RA1 или \ INT Не знаю как это сделать.
Ползу дальше.... "...до старта основной программы..." до метки main? И тогда получается что я не правильно написал сначала main потом podgot и т.д. ? Должно быть как-то так?
Код:
TRISA = 0b11111111; PORTA = 0; TRISB = 0b00000000; PORTB = 0; void main (void) { podgot(); while (1) if (RA1 = 1) RB1 = 1; else RB1 = 0;
}
Теперь о INIT... к сожалению вте самоучителе что я читал об этом не как не упоминали. Куда, как, и где он должен быть?
Спасибо ) Я конечно понимаю что краткость сестра таланта и всё таки откуда это выросло и в какое место кода это вставить?
Если я не ошибаюсь это ассемблер.
mov копировать/записать значение в регистр "lw" какое-то значение "b'00000111"
mov копировать/записать значение в регистр "wf" тут тёмный лес... если в предыдущем всё относительно понятно (есть регистр настройки чего-то и в него нужно поместить какое-то значение. Где это в даташите написано? Что это за регистр и как вы подобрали значение?) то как поместить в регистр "wf" значение "CMCON" я не понимаю. Разжуйте этот момент пожалуйста!
Ну и третья строка "Comporators is OFF" как бы понятно что выключает компараторы но откуда взята эта команда? Даташит? Если да то в каком месте написано что вот так выключаются компараторы?
Спасибо ) Я конечно понимаю что краткость сестра таланта и всё таки откуда это выросло и в какое место кода это вставить?
Если я не ошибаюсь это ассемблер.
Ну и третья строка "Comporators is OFF" как бы понятно что выключает компараторы но откуда взята эта команда? Даташит? Если да то в каком месте написано что вот так выключаются компараторы?
CMCON = 0b00000111; аналог двух ассемблерных строк на Си.
В даташите, раздел "Регистр CMCON". По умолчанию компаратор включен (ф628, 629 и ещё у кучки) и его надо отключить, что-бы не мешел работе пина на вход-выход.
_________________ Ох уж эти сказки... Ох уж эти сказочники...
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
void main (void) { TRISA = 0b11111111; PORTA = 0; TRISB = 0b00000000; PORTB = 0; CMCON = 0b00000111; while (1) if (RA1 = 1) RB1 = 1; else RB1 = 0; }
Вот в таком варианте мигалка заработала. Пожалуйста проверьте на возможные ошибки и ткните носом в них! Может с точки зрения "мк этики" я что-то ну совсем не верно написал
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disable) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF #define _XTAL_FREQ 4000000
void podgot (void); void cikl (void); void main (void) { podgot(); while(1) { if (RA0 == 1) {
Для начала - а что должно работать? Потом, зачем в цикле выводить стопицот раз на выход единицу? Обычно, достаточно одного раза. Микроконтроллер послушный и повторять ему второй раз не требуется. И если надеетесь на помощь - структурируйте текст. както влом выяснять, кто под кем вложен. А еще - пишите, не ленитесь, подробный комментарий - что, для чего и что вы хотите этим достичь. У меня самого много раз было так, что пока описывал подробно свою проблему на форуме - самостоятельно находил ошибку и удалял тему не начав. Просто нужно было мозги привести в порядок.
_________________ А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Само устройство. И для чего это нужно. Это своеобразный доводчик двери. То есть электро двигатель установлен на двери и он должен её дотягивать до щелчка когда это по каким либо причинам не произошло при закрытии. Например хлопнули слабо и дверь прикрыта но замок не закрыт. В атомобилях такое часто бывает. Дверь закрыта только на половину и чтобы её дозакрыть нужно снова открыть дверь и хлопнуть по сильнее чтобы двери закрылись доконца. Сам исполнительный механиз я слизал с одного готового устройства. Если очень грубо то когда дверь не закрылась датчик это видит, включает двигатель тот в свою очередь "крючком" подцепляет дверь и тянет её до полного закрытия. Когда происходит полное закрытие нужно убрать "крючок" для этого дигатель вращается в обратную сторону.
Теперь как связана моя схема и то что я описал. К выводу RA0 ( настроен на вход) подключен тот самый датчик который фиксирует неполное закрытие двери (геркон) Он фиксирует именно положение двери когда она закрыта не до конца. Когда дверь полностью открыта или закрыта до конца он разомкнут . Когда на нём появляется + (единица) МК должен перейти в цикл закрывания двери. Сам цикл закрывания двери в моём представлении выглядит следующим образом: -Повторно проверить состояние датчика положения двери если единица от начать закрывать дверь, если ноль то ничего не делать и вернутся в основную программу ожидания срабатывания датчика. Перед повторной проверкой состояния датчика должна идти пауза. Это нужно чтобы когда дверь просто открывают из закрытого положения она неизбежно будет проходить через датчик положения двери и будет вызывать его срабатывание. То есть если без паузы будет происходит следующее: дверь начинают открывать, срабатывает датчик неплотно закрытой двери и МК даёт команду двигателю закрыть её. И вот я начинаю бороться собственным устройством что-бы открыть дверь ) Что-бы этого не было перед повторной проверкой состояния датчика положения двери должна быть пауза. То есть в моём понимании это должно работать так: начинаешь открывать дверь срабатывает датчик не плотно закрытой двери, МК ждёт секунду и повторно спрашивает датчик. Если он говорит что дверь неплотно закрыта то закрыть её. Если датчик не сработал (это случается в двух случаях -дверь открыта совсем и дверь закрыта полностью) то ни чего не делать. Если датчик сработал - дверь закрыта не полностью - закрыть её.
Немного о механизме и двигателе: Пусть двигатель это обычный соленоид который стоит в автомобильной двери и закрывает её когда вы ставите свой автомобиль на сигнализацию. Добавим на него крючок который зацепляет дверь для того чтобы её закрыть полностью. И ещё добавим на него два концевых выключателя. С помощью этих выключателей мы будем контролировать положение крючка. Это нужно для того чтобы он гарантированно доходил до нужных положений. И совершенно случайно не завис где нибудь по середине. Если это случится то дверь попросту будет невозможно открыть.
Теперь по схеме: К выводу RA0 подключен датчик положения двери (геркон). К выводам RA1 и RA2 подключены концевые выключатель двигателя К выводам RB0 и RB1 подключены реле. Сейчас на схем их место занимают два светодиода. Так проще контролировать в каком состоянии находится программа МК.
#pragma config FOSC = INTOSCCLK // включаем внутренний генеротар #pragma config WDTE = OFF // выключаем собачий (сторожевой) таймер, пока что он не нужен #pragma config PWRTE = ON // включаем задержку при включении мк, нужна для его стабилизации #pragma config MCLRE = OFF // выключаем сигнал сброса МК #pragma config BOREN = OFF // выключаем функцию сброса при пониженном напряжении #pragma config LVP = OFF // запрещаем низковольтное программирование #pragma config CPD = OFF // выключаем защиту программы #pragma config CP = OFF // выключаем защиту EEPROM тут могу напутать. #define _XTAL_FREQ 4000000 // говорим кварцевому генератору на какой частоте работать - эту строчку я просто скопировал из примера где-то и предполагаю что она работает так как я её описал
void podgot (void);// объявляем функции void cikl (void); // объявляем функции void main (void) // старт основной программы { podgot(); // переход к настройке МК - в какомто примере это сделано отдельном блоке и я по аналогии сделал также while(1) // организация бесконечного цикла так как условие в скобочках рядом с while ни когда не выполнится { if (RA0 == 1) // проверка датчика положения двери: -замкнут (единица на вводе RA) отработать блок под название "cikl" -разомкнут ни чего не делать дальше крутится в цикле и ожидать срабатывания датчика { cikl(); // переход в блок под название "cikl" } } }
void podgot (void)//podgotovka MK // блок подготовки МК { TRISA = 0b11111111; // весь порт RA на вход PORTA = 0; // очистка порта RA TRISB = 0b00000000; // весь порт RB на выход PORTB = 0; // очистка порта RB CMCON = 0b00000111; // отключение компараторов }
void cikl (void) // цикл отработки сигнала от датчика положения двери { __delay_ms(250); // пауза перед повторным опросом датчика положения двери if (RA0 == 1) // если на вводе RA0 единица (датчик сработал) начать закрывать дверь, если ноль ничего не делать вернутся в основную программу { while (RA1 == 0) // пока на вводе RA1 ноль (концевой датчик не сработал) тянуть дверь на себя { RB0 = 1; // первое реле. Тянуть на себя, включит двигатель } RB0 = 0; // выключить двигатель __delay_ms(50); //так как двигатель подключен через реле на всякий случай дать реле время для отключения чтобы небыло сквозных токов и замыкания while (RA2 == 0) // пока на вводе RA2 ноль (концевой датчик не сработал) отпускать дверь { RB1 = 1; // реверс, двигатель через второе реле - отпуска } RB1 = 0; // выключит двигатель } // конец цикла отрывания/закрывания возврат в основную программу и ожидание срабатывания датчика положения двери }
А что именно в железе не работает? Концевики подключены правильно? А то геркон замыкает на "+", а концевики на "-". А сравниваете с "0". И потом. Логичнее было бы писать
Код:
void cikl (void){// цикл отработки сигнала от датчика положения двери __delay_ms(250);// пауза перед повторным опросом датчика положения двери if (RA0 == 1){// если на вводе RA0 единица (датчик сработал) начать закрывать дверь, если ноль ничего не делать вернутся в основную программу RB0 = 1; while (RA1 == 1 или 0){// пока на вводе RA1 ноль (концевой датчик не сработал) тянуть дверь на себя // первое реле. Тянуть на себя, включит двигатель } RB0 = 0;// выключить двигатель __delay_ms(50);//так как двигатель подключен через реле на всякий случай дать реле время для отключения чтобы небыло сквозных токов и замыкания RB1 = 1; while (RA2 == 1 или 0){// пока на вводе RA2 ноль (концевой датчик не сработал) отпускать дверь // реверс, двигатель через второе реле - отпуска } RB1 = 0;// выключит двигатель }// конец цикла отрывания/закрывания возврат в основную программу и ожидание срабатывания датчика положения двери }
Ну и внутри циклов неплохо бы вставить "таймеры", а то может концевик никогда не сработает, а мы заклиненный двигатель пожгём...
_________________ А люди посмотрят и скажут: "Собаки летят. Вот и осень."
А что именно в железе не работает? Концевики подключены правильно? А то геркон замыкает на "+", а концевики на "-". А сравниваете с "0". И потом. Логичнее было бы писать... ...Ну и внутри циклов неплохо бы вставить "таймеры", а то может концевик никогда не сработает, а мы заклиненный двигатель пожгём...
Да Вы верно заметили на RA1 и RA2 должно быть пока единица то есть "+" ведь он подтянут резистором к "+" . Изменил код. Проверил подключение всего. Всё равно не работает. А в протеусе работает... а в железе нет...
Код:
void cikl (void){// цикл отработки сигнала от датчика положения двери __delay_ms(250);// пауза перед повторным опросом датчика положения двери if (RA0 == 1){// если на вводе RA0 единица (датчик сработал) начать закрывать дверь, если ноль ничего не делать вернутся в основную программу RB0 = 1; while (RA1 == 1){// пока на вводе RA1 еденица "+" (концевой датчик не сработал) тянуть дверь на себя // первое реле. Тянуть на себя, включит двигатель } RB0 = 0;// выключить двигатель __delay_ms(50);//так как двигатель подключен через реле на всякий случай дать реле время для отключения чтобы небыло сквозных токов и замыкания RB1 = 1; while (RA2 == 1 ){// пока на вводе RA2 еденица "+" (концевой датчик не сработал) отпускать дверь // реверс, двигатель через второе реле - отпуска } RB1 = 0;// выключит двигатель }// конец цикла отрывания/закрывания возврат в основную программу и ожидание срабатывания датчика положения двери }
А почему стало; ... RB1=0; __delay_ms(50); while (RA2 ==1) { RB1=0; } ... Почему строка RB1=0; подпрыгнула над while.
Я правильно понимаю что while работает следующим образом: while (условие, у нас это RA2==1) {тело цикла, у нас это включит двигатель то есть RB1=1} когда условие становиться истиной выполнение программы выходит из тела цикла заключённое в квадратные скобки и переходит к следующему оператору. У нас это выключить двигатель RB1 = 0?
И да Вы совершенно правы нужно добавить "таймер" причём несколько: 1. Это на закрытие 2. Это на открытие 3. Это сторожевой таймер. Действительно вдруг двигатель заклинил и мы всё это дело сожжём. И пришла мысль что по мимо таймеров нужно ещё сделать "инициальзацию" при включении. т.к. когда он первый раз включается (не важно после какого события, сброс от сторожевого, пропало питание во время выполнения цикла или ещё какая беда) он не знает в каком положении находится "крючок" Но это всё потом. Сейчас в простом варианте (без защит) запустить бы...
В общем заработало!!! Удалил из MPlab лишние проекты и заработало! Всем огромное спасибо за помощь!
Сейчас буду колдовать с защитами
Добавил инициализацию первого включения. А вот с таймерами пока что не понимаю как луче сделать. С одной стороны есть встроенные три таймера с другой стороны можно программный написать... Программный будет занимать процессор мк и тот в свою очередь не сможет заниматься другими "делами"... с другой стороны его проще встроить в цикл открывания закрывания....
Таймер нам нужен для отслеживания аварийной ситуации. Например двигатель заклинил и конечник не сработал.
Что-то я пока что не представляю как это реализовать ...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения