![]() |
![]() |
+7-978-708-85-73 Дроссель Amadeus Productions. Быстрый заказ по телефону. (Viber, WhatsApp, Telegram) |
![]() |
![]()
Сообщение
#1
|
|
Технический Маньяк-Гуру ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Технический Маньяк Сообщений: 7049 Регистрация: 3.6.2009 Из: Армения Вне форума Авто: Lancer IX, AT Репутация: ![]() ![]() ![]() |
Ну что, начнем. Заранее заявляю, что я сам тоже новичок в этом деле, так, что если что не так с удовольствием приму и критику и замечания и дополнения.
Что такое микроконтроллер (МК)? Это микросхема которая сама по себе АБСОЛЮТНО ничего не умеет делать в отличии от даже самой примитивной логики. Для того, чтобы заставить МК выполнять какую-нибуть работу надо прошить (загрузить) в него программу. МК выпускаются многими фирмами - Mikrochip, Atmel, Motorolla, etc. Здесь будут рассматриваться только МК фирмы Mikrochip, так называемые pic-контроллеры. Их легко различить по маркировке от других, название начинается с префикса PIC или (в современных сигнальных процессорах) dsPIC, например, PIC18F2520, PIC16F877 и т.д. Наиболее употребимые в любительской практике - 8-разрядные контроллеры среднего и высшего семейств, PIC16 и PIC18. Буква "F" в маркировке МК означает, что он может многократно перезаписываться, т.е. если по каким-либо причинам надо поменять программу (прошивку), то это легко можно осуществить при помощи программатора (об этом попозже). Есть МК и с буквой "С" - это однократно программируемые. Питание МК - +5В, хотя многие из них могут работать и при пониженном напряжении, от +2,5В. Потребляемый ими ток насколько мал, что о нем и говорить неудобно (IMG:style_emoticons/default/dry.gif) Так что-же все таки представляет собй МК? Это микросхема с определенным количеством выводов (8, 14, 16, 18, 20, 28, 40 и т.д), как минимум двое из которых предназначены для подачи питания, а почти все остальные представляют собой линии ввода-вывода. Почти - потому-что есть МК, которые обязательно должны тактироваться внешним кварцем (еще 2 вывода) и/или имеют отдельный вывод сброса. А есть и такие, что могут работать как от внешнего так и от внутреннего генераторов, в этом случае освободившиеся выводы тоже можно использовать для дела. Конкретно количество выводов данных можно посмотреть в даташите на конкретный МК. Т.к. МК 8-и битные, то и выводы организованы в шины той-же разрядности, или, как их называют - порты. В зависимости от кол-ва ножек могут быть порты A, B, C, D, E, которые на изображении МК обозначаются след. образом: буква R, затем наименование порта, затем номер разряда порта, напр. RA0, RC2, RB7... В МК совсем необязательно наличие всех разрядов какого-либо порта, например, могут быть RC3...RC7, a RC0, RC1 и RC2 - отсутствовать. В принципе, это не имеет значения, т.к. любой порт можно запрограммировать на выполнение практически любой задачи (исключая некоторые специфические, такие, как обмен данными по USB или Ethernet), так, что без разницы - подключен, например, светодиод, сигнализирующий о превышении температуры к порту RB5 или RE0. Исключение составляют выводы порта А, которые можно сконфигурировать так, чтоб они работали в аналоговом режиме (все остальные только цифровые). Естественно, порт А также может работать в цифровом режиме, что он и делает по умолчанию. Аналоговый режим используется для задействования встроенных АЦП - аналого-цифровых преобразователей, с их помощью измеряются аналоговые сигналы, например, напряжение, показания термодатчиков и т.д. С распространением различных протоколов на определенные выводы могут также возлагаться дополнительные функции. Это не значит, что с другими выводами нельзя добиться результата, просто, если на вывод подключена какая-либо доп. функция, то результат достигается более легкими программными способами. Для примера приведу обозначения выводов МК PIC16F876 1 MCLR/VPP/RE3 2 RA0/AN0 3 RA1/AN1 4 RA2/AN2/VREF-/CVREF 5 RA3/AN3/VREF+ 6 RA4/T0CKI/C1OUT 7 RA5/AN5/SS/HLVDIN/C2OUT 8 VSS 9 OSC1/CLK1 10 OSC2/CLK0 11 RC0/T1OSO/T13CKI 12 RC1/T1OSI/CCP2 13 RC2/CCP1 14 RC3/SCK/SCL 15 RC4/SDI/SDA 16 RC5/SDO 17 RC6/TX/CK 18 RC7/RX/DT 19 VSS 20 VDD 21 RB0/INT 22 RB1 23 RB2 26 RB3/PGM 25 RB4 26 RB5 27 RB6/PGC 28 RB7/PGD Смотрим, что мы тут имеем. МК имеет 2 вывода для соединения с общим проводом (8 и 19 - Vss), вывод питания - 20 - Vdd, отдельные выводы для подачи тактовых импульсов или подключения кварца - 9 - OSC1/CLK1 и 10 - OSC2/CLK0. Вывод сброса по желанию можно переконфигурировать для обработки данных - 1 - MCLR/VPP/RE3, т.е. он превращается в RE3. Все остальные - данные. Дальше, некоторые выводы не имеют никаких специальных функций, например, RB1...RB7. Здесь PGM, PGC, PGD, а также Vpp на выводе 1 - сигналы с программатора, после прошивки МК они (имеются в виду сигналы а не выводы) не используются. Порты А, как видно, могут переконфигурироваться и работать как AN0...AN5 - аналоговые входы. Некоторые сигналы (вернее протоколы) могут нам никогда и не понадобиться, так, что не стоит сейчас акцентировать на них внимание, просто опять же для примера упомянем 17 - RC6/TX/CK 18 - RC7/RX/DT, т.е. если надо, чтоб МК взаимодействовал с компьютером по последовательному интерфейсу (СОМ порт), то для этой цели лучше выбрать выводы 17 и 18, т.к. на них посажены также режимы RX и TX. ----------------- Естественно, т.к. МК работают под управлением программы, то в них должна быть предусмотрена память для этих самых программ. В зависимости от МК объем памяти может колебаться от сотен байт до десятков килобайт. Память, как уже отмечалось, обычно многократно перезаписываемая. Помимо программной МК может также иметь RAM память (ОЗУ) - для временного хранения данных/переменных во время работы программы, а также EEPROM - постоянная память для хранения данных при выключенном питании контроллера. Скажем, если на контроллере построен борткомпьютер, то, например, пройденный путь или израсходованный бензин надо писать именно в EEPROM, иначе данные потеряются после выключения зажигания. Данные же о мгновенном расходе пишутся в RAM. Конкретно объем программной памяти и наличие/отсутствие и объем RAM и EEPROM надо опять же смотреть в соотв. даташитах. ----------------- Я честно говоря, не знаю, надо ли продолжать или нет, т.к. в сети есть куча информации по различным МК, так, что если есть желание, то изучить их работу в желаемом для себя объеме нетрудно. Если есть интерес к обсуждению этого вопроса именно здесь а не на спец. форумах, то в след. раз поговорим о самих программах и программаторах. |
![]() |
|
![]() |
![]()
Сообщение
#2
|
|
Технический Маньяк-Гуру ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Технический Маньяк Сообщений: 7049 Регистрация: 3.6.2009 Из: Армения Вне форума Авто: Lancer IX, AT Репутация: ![]() ![]() ![]() |
Как и было сказано ранее - попытаемся сделать что-то полезное а не просто "там нажал, тут светит" (IMG:style_emoticons/default/smile.gif)
Будем делать часы, с применением специализированной микросхемы DS1307. Для этого дополним схему голубой частью, а светодиод исключим из схемы, хотя, в принципе он нам и не мешает, пусть остается. Вместо резервной батареи питания часов можно просто закоротить вывод 3 DS1307 на общий провод, если его оставить пустым - микросхема не будет работать. DS1307 представляет собой 8-ножечную микросхему, взаимодействующую с внешним миром по протоколу I2C. Это стандартный протокол, применяется во многих устройствах, например в микросхемах памяти eeprom, так, что его изучение не помешает (естественно на том уровне, чтоб мы лишь бы смогли подцепить такое устройство к МК, большего и не надо). Во многих МК на аппаратном уровне заданы выводы для I2C устройств, хотя, как уже отмечалось, их можно посадить куда угодно, организуя этот протокол программно. I2C устройства взаимодействуют с внешним миром по 2-х проводной шине, SCL-синхронизация и SDA-данные. Т.е. вся информация передается по двум проводам, это особенно удобно если 2 устройства разнесены друг от друга или надо сэкономить выводы МК. На графическом обозначении pic16f876 видим, что SCL сидит на RC3, SDA - на RC4. Но здесь мы организуем программную реализацию протокола, для того, чтоб просто не занимать PORTC. Сначала слегка изучим саму DS1307 (RTC - Real Time Clock). Как? Конечно качаем datasheet. Опять же, все читать не надо, только суть, которая состоит в том, что Для того, чтобы читать из DS1307 надо подать команду 11010001 ($D1) Для записи в неё - 11010000 ($D0) Время и дата располагаются в области памяти, начиная с 0, 0 - секунды 1 - минуты 2 - часы и т.д. Время и дата считываются не в нашем родном десятичном формате, а в каком-то непонятном BCD (Binary Coded Decimal) - двоично-десятичном. Что это такое - черт его знает, ну да ладно, потом разберемся... Ну и естественно смотрим типовую схему включения, куда что паять. Все, больше нам ничего и не надо, все нарисованные графики, диаграммы и т.д. Только поймем, почему использован кварц на 32768 Гц, число какое-то ни к селу ни к городу. Оказывается, если это число последовательно делить на 2, то в итоге получим 1, т.е. интервал в 1 секунду, а деление на два самая простая операция в цифровой технике. Вооружившись этими сведениями примемся за программирование. Т.к. считанное время надо куда-то выводить - используем ЖКИ, работу с которым уже изучили. Далее, любые часы требуют коррекции, значит надо иметь кнопки для установки - как с ними работать - тоже знаем. Сразу же привожу текст программы, все, что на русском - здесь комментарии, все, что уже описывалось ранее - не комментируем. Почти во всех языках программирования, если перед числом стоит знак $, то подразумевается, что имеется в виду шестнацитиричное число, % - двоичное, ничего нет - десятичное. Для справки - компиллятор MikroBasic имеет в своем составе конвертор чисел, так, что, не надо объяснять как производится перевод из одной системы счисления в другую (IMG:style_emoticons/default/wink.gif) program DS1307 ' ' Lcd module connection dim LCD_RS as sbit at RB4_bit LCD_EN as sbit at RB5_bit LCD_D4 as sbit at RB0_bit LCD_D5 as sbit at RB1_bit LCD_D6 as sbit at RB2_bit LCD_D7 as sbit at RB3_bit LCD_RS_Direction as sbit at TRISB4_bit LCD_EN_Direction as sbit at TRISB5_bit LCD_D4_Direction as sbit at TRISB0_bit LCD_D5_Direction as sbit at TRISB1_bit LCD_D6_Direction as sbit at TRISB2_bit LCD_D7_Direction as sbit at TRISB3_bit ' End Lcd module connections ' По аналогии с описанием ЖКИ, здесь описано соединение выводов DS1307 с МК ' SCL - RB7 ' SDA - RB6 ' Software I2C connections dim Soft_I2C_Scl as sbit at RB7_bit Soft_I2C_Sda as sbit at RB6_bit Soft_I2C_Scl_Direction as sbit at TRISB7_bit Soft_I2C_Sda_Direction as sbit at TRISB6_bit ' End Software I2C connections ' Описания переменных, здесь присутствует новый тип - string, строка, состоящая из 8 символов ' Позиции символов нумеруются слева направо, начиная с нуля. dim hours, minutes, seconds as byte dim press as byte dim menuitem as short dim hrs, min, sec as char[3] dim text as char[2] dim systime as string[8] ' Считать показания DS1307 sub procedure GetTime() Soft_I2C_start ' Запустить программный протокол обмена по I2C Soft_I2C_write($D0) ' Подаем команду $D0 - запись в DS1307 Soft_I2C_write(0) ' записываем 0 - адрес с которого располагаются данные о времени. Soft_I2C_Start ' Перезапускаем протокол Soft_I2C_write($D1) ' Команда $D1 - читать из DS1307 seconds = Bcd2Dec(Soft_I2C_read(1)) ' т.к. адрес установлен на 0, считываем секунды и переходим (1) к minutes = Bcd2Dec(Soft_I2C_read(1)) ' считыванию минут, далее (1) hours = Bcd2Dec(Soft_I2C_read(0)) ' и часы и все, дальше не читаем (0) Soft_I2C_stop ' ну и останавливаем передачу данных по I2C end sub ' Здесь при считывании данных мы сразу же перевели их в десятичный формат - BCD2Dec (BCD to decimal) sub procedure ResetSec() 'Установка (сброс) секунд if Button(PORTA, 4, 1, 0) then Soft_I2C_start Soft_I2C_write($D0) ' Записать Soft_I2C_write($00) ' В ячейку с адресом 0 Soft_I2C_write($00) ' ноль Soft_I2C_stop end if Delay_ms(200) ' Здесь задержка в принципе и не нужна, ну да ладно, не помешает end sub sub procedure SetMinutes() ' Установка минут if Button(PORTA, 4, 1, 0) then Inc(minutes) ' При нажатии на кнопку увеличивать значения минут на единицу if minutes = 60 then minutes = 0 end if 'Больше 59-и минут не бывает minutes=Dec2Bcd(minutes) ' Переводим обратно формат в BCD, чтоб было понятно DS1307 Soft_I2C_start Soft_I2C_write($D0) ' Записать Soft_I2C_write($01) ' В ячейку с адресом 1 Soft_I2C_write(minutes) ' то число, которое мы получили чуть выше Soft_I2C_stop end if Delay_ms(200) ' Небольшая пауза, чтоб не слишком быстро менялись цифры end sub sub procedure SetHours() ' То же самое до часов if Button(PORTA, 4, 1, 0) then Inc(hours) if hours = 24 then hours = 0 end if ' Часы - до 24-х hours=Dec2Bcd(hours) Soft_I2C_start Soft_I2C_write($D0) Soft_I2C_write($02) 'Адрес ячейки часов - 2 Soft_I2C_write(hours) ' Soft_I2C_stop end if Delay_ms(200) end sub sub procedure DisplayTime() ByteToStr(seconds,sec) ' Переводим байты в символы text[0]=sec[1] ' Подробное описание - см. ниже text[1]=sec[2] ' text[2]=0 if text[0] = 32 then text[0] = "0" end if ' sec = text ' ByteToStr(minutes,min) text[0]=min[1] text[1]=min[2] text[2]=0 if text[0] = 32 then text[0] = "0" end if min = text ByteToStr(hours,hrs) text[0]=hrs[1] text[1]=hrs[2] text[2]=0 if text[0] = 32 then text[0] = "0" end if hrs = text systime = hrs + ":" + min + ":" + sec ' Имея все данные складываем их в строку, готовую к выводу на экран ' Это так называемая конкатенация строк, т.е. в результате получаем строковую переменную вот такого вида ' 12:06:34 end sub sub procedure SelectMode() ' Вторую кнопку (ту, что меняла состояние МК при однократном нажатии) ' используем для перебора пунктов меню установки времени и индикации соотв. режима if press = 0 then if Button(PORTA, 3, 1, 0) then menuitem = menuitem + 1 press = 1 end if end if if Button(PORTA, 3, 1, 1) then press = 0 end if select case menuitem ' В зависимости от значения переменной menuitem выбираем то или иное действие case 0 Lcd_out(1, 1, "Reset ") 'Если нажать на кнопку 1 - произойдет сброс секунд ResetSec() case 1 Lcd_out(1, 1, "Minutes") ' Установка минут SetMinutes() case 2 Lcd_out(1, 1, "Hours ") ' Часов SetHours() case 3 ' Обнуляем menuitem, т.е. после 3-х нажатий на кнопку пункты меню будут крутиться по новой. menuitem = 0 end select end sub '########################## Главная программа ######################## main: TRISA = %11111111 ADCON1 = %10000110 press = 0 menuitem = 0 Soft_I2C_Init() ' Аналогично ЖКИ надо проинициализировать и I2C Lcd_Init() Delay_ms(200) Lcd_Cmd(_LCD_CLEAR) Lcd_Cmd(_LCD_CURSOR_OFF) Lcd_Out(2, 1, "Time:") 'Т.к. это слово постоянно должно высвечиваться на экране, выводим его while true ' А этот цикл будет крутиться бесконечно GetTime() ' Считать время DisplayTime() ' Подготовить считанные данные к выводу на экран SelectMode() ' Проверить, не нажата ли вторая кнопка Lcd_Out(2, 9, systime) ' Вывести подготовленные данные (ЧЧ:ММ:СС) на экран ЖКИ wend ' возвратиться к while, и так все время, пока не выключим питание end. --------------------------- Про преобразование строки: Переводим байты в строку: ByteToStr(seconds,sec) Как происходит преобразование - мы уже видели, 000 - преобразуется в "0" 001 - "1" ... 010 - "10" 100 - "100" - но это нам не грозит, т.к. время - это мах. число 59 видно, что байт может состоять из 1-го, 2-х или трех символов (0...255), а показания часов - двухзначные, значит надо что-то предпринимать. Следующие операторы сдвигают символы в строке на одну позицию влево, и отсекают последний символ, т.е., например, если имеем 045, получаем 45 text[0]=sec[1] text[1]=sec[2] text[2]=0 ' Обратите внимание, это не символ "0", а просто пустота, иначе получилось бы не 45 а 450 если же имеем, например, 005, то после предыдующего преобразования получим просто 5, некрасиво будет смотреться на экране. Поэтому, если 0-й символ равен пробелу (ASCII код - 32), то вместо него записываем "0" (Т.к. ноль - в кавычках, то это не число а символ) if text[0] = 32 then text[0] = "0" end if sec = text Переменная text - промежуточная, сама она непосредственно нигде не высвечивается, присваиваем её значение переменной sec, чтоб в дальнейшем использовать text для преобразования минут и часов. ------------------------------ Здесь, да и раньше тоже, мы не останавливались на подробном описании команд, т.к. все это описано в HELP, и для того, чтобы полностью уяснить как работает та или иная команда надо читать её описание. Далее (если еще не надоел), добавим к нашему устройству вольтметр, а может еще и термометр (IMG:style_emoticons/default/wink.gif) |
![]() |
|
![]() ![]() ![]() |
![]() |
+7-978-708-85-73 Дроссель Amadeus Productions. Быстрый заказ по телефону. (Viber, WhatsApp, Telegram) |
Текстовая версия | © 2006-2025 Форум Технических Маньяков. |
|