НЕХ-файл для загрузки в программатор
:10000000830100308A0004282030840038300D201D :100010008301392B04068001840A0406031D0A2883 :020020000034АА
:1004Е20083018С1Е712А1А0808008301В700831247 :1004F20003130C1E782A370899000800F401F5014D :100502000310F30CF20C031C8D2A7008F407710817 :100512000318710AF5070310F00DF10D7208730448 :1005220003190034812A8301850107309F00831655 :100532008501FE30860090308312980006308316C3 :100542009800683099008312061083169B011C14D0 :100552001A098312A200850008008301AD01AE01D1 :100562003008A0003108A100D030A007A1070A304E :10057200F200F3012008F000F1017F222108740744 :10058200AD0075080318750AAE00F1002D08F000E1 :1005920008000130F000831203132908F100F10A68 :1005A200D42A0310F00DF10BD22A7008A2042208FB :1005B200850083169B018312220983169A001C155B :1005C2008B1355309D00AA309D009C149C18E72A7D :1005D2008B171C11831208000130F00083120313E1 :1005E2002908F100F10AF72A0310F00DF10BF52AA0 :1005F2007009A2052208850083169B018312220935 :1006020083169A001C158B1355309D00AA309D004D :100612009C149C180A2B8B171C118312080083014F :100622003308A300D030F000FF30F1002308700738 :10063200A90071080318710AAA002E2B2908B50017 :100642002A08B600CA2A2908B5002A08B600ED2AE7 :100652002908B5002A08B6008C2B3408463A03193B :10066200242B083A03191F2B1D3A031D0800292BBE :100672009422AB01AC01462B2B082F3E840083133E :1006820020308000AB0A0319AC0A2C08803AF00033 :1006920080307002063003192B02031C3D2B5230AE :1006A200AF000608A500A6010430F000260DA60C36 :1006B200A50CF00B572B852BAB01AB0AAC012C0818 :1006C200803AF00080307002063003192B020318C2 :1006D200762B7122A4002B082F3E8400831324085A :1006E2008000AB0A0319AC0A602BAE227008A70087
:1006F2007108A8002606031D802B25082706031D66
:10070200852B2430B200102318167122A400523A0D
:1007120003195D2B852B52308301AF002008303E38
:10072200B0002108303EB1002330B2002308B300EC
:10O732002208F0002908F100F10AA12B0310F00CA5
:10074200F10B9F2B7008F000701CA92B4E30B400E7
:100752002208F0002908F100F10AB12B0310FOOC75
:10076200F10BAF2B7008F0007018B92B4630B400B3
:1007720018120614831698168312AB01AC012C08CA
:10078200803AF00080307002063003192B02031801
:10079200D42B2B082F3E8400831300087622AB0A49
:1007A2000319AC0AC02BAB01AC012C08803AF00053
:1007B20083307002E83003192B020318E42BAB0AD2
:1007C2000319AC0AD62BAB01AC012C08803AF0001D
:1007D20080307002063003192B020318FA2B2B0803
:1007E2002F3E8400831320308000AB0A0319AC0A29
:0E07F200E62B061083169812831218160800C4
:00000001FF
С теми, кому интересно провести эксперименты, не имея опыта работы с микроконтроллерами и программным обеспечением или желая более детально ознакомиться с модулем, мы продолжим разговор о том, как это все устроено.
Требования к модулю:
• модуль должен иметь реле, контакты которого позволят подключить нагрузку с параметрами: -220В, 10А (мощности нагрузки ~ 2 кВт);
• модуль должен иметь сетевой интерфейс RS485 (системная сеть);
• по отношению к системной сети модуль должен быть пассивным, то есть его основным режимом работы будет прослушивание сети и выполнение команд, полученных по сети, если они адресованы модулю;
• адрес модуля задается установкой переключателя в соответствующее положение.
Поскольку контроллер PIC16F628A имеет встроенный USART, мы используем его для работы с интерфейсом RS485.
Адресный селектор можно организовать на микроконтроллере различным образом. Для начала используем наиболее очевидный способ - выводы порта, включенные на ввод
информации, соединим с контактами переключателя, который устанавливает их в состояние - «1» или «О». В дальнейшем мы обсудим другие способы задания адреса. Четыре бита дают возможность адресоваться к 16 устройствам.
Для подачи сетевых команд используем СОМ-порт компьютера с передачей байта (рис. 1.35).
Пауза
СТт (линия свободна) (msb)
С с
Биты данных |
Мл. (lbs) |
Высокий Низкий |
: ; : g I о 5 j 6 j 7 : о j О
4 мкс
Фрейм данных - 44 мкс
Рис. 1.35. Биты данных RS232 из статьи на сайте Http://measure. chat. ru
Каждый бит имеет длительность 4 мкс (при данной скорости).
Для обращения к релейным модулям используем дополнительный адресный префикс «R».
Практически, мы определились со всем необходимым, чтобы приступить к построению релейного модуля.
Команды, которые будет принимать наш модуль:
• включить - Rxx $ xN;
• выключить - Rxx$xF.
Я добавлю команду передачи модулем состояния реле:
• передать статус - Rxx$xS.
При передаче статуса используем следующую символику:
• включено - Rxx#xN;
• выключено - Rxx#xF.
Здесь Rxx$xN означает: R - релейный модуль, хх - два символа адреса от 00 до 15, $ - символ команды (# - символ статуса), х - номер реле от 0 до 7, N - включить (F - выключить).
Уточним, как мы будем использовать ресурсы контроллера. Для ввода информации используем встроенный в контроллер USART.
Использование порта В:
• RB0 - управление передатчиком (микросхема МАХ1483).
• RB1 - прием (приемник USART).
• RB2 - передача (передатчик USART).
Для ввода заданного адреса используем четыре старших бита порта В (RB7-RB4).
Использование порта А:
• для подключения реле используем биты порта A (RA0- RA7), что предполагает использование восьми реле;
• при необходимости увеличить количество реле можно использовать свободные (если они есть) биты порта В.
Мы готовы приступить к написанию программы.
Основные блоки программы:
• инициализация (конфигурация контроллера);
• ожидание и прием команды (ожидание активности в сети, чтение команды, проверка адреса, и, если адрес совпадает с адресом устройства, выполнение команды, возвращение к ожиданию команды);
• выполнение команды.
Распишем это поподробнее.
Инициализация.
В этом блоке мы должны задать конфигурацию контроллера, переход в режим низкого энергопотребления (SLEEP) и условия выхода из этого режима. В блоке инициализации мы прочитаем адрес, задаваемый адресным переключателем.
Ожидание и прием команды.
Этот блок программы является основным, поскольку в сети модуль играет пассивную роль, то есть ожидает прихода и выполняет команду, адресованную ему. При активации сети команда прочитывается. Если префикс совпадает с префиксом модуля, а адрес - с адресом устройства, команда выполняется, в противном случае модуль переходит в режим ожидания следующей сетевой команды. Адрес в слове команды сравнивается с ранее прочитанным (при инициализации) заданным адресом модуля.
Выполнение команды запроса статуса.
Этот блок программы отличается от предыдущего, начиная с момента получения символа S вместо N или F. Программа должна определить состояние соответствующего вывода порта, переключить USART на передачу и передать статус в формате Rxx#xN, если соответствующий вывод порта - в состоянии «1», или Rxx#xF, если он в состоянии «О». После этого программа переходит к ожиданию следующей команды.
Блок инициализации контроллера.
В первую очередь, определим, нужен ли нам режим «SLEEP», который переводит контроллер в состояние с уменьшенным энергопотреблением. Режим очень удобен и важен в тех случаях, когда контроллер используется в условиях батарейного питания. Переход в режим «SLEEP» продлевает срок службы батарей или время работы без подзарядки аккумулятора. В нашем случае нет необходимости в поддержании этого режима, поскольку модуль получает питание от блока питания.
Часть конфигурирования необходимо выполнить при программировании контроллера. Это относится к слову конфигурации по адресу 2007h. Здесь h после цифр означает HEX, hexadecimal (шестнадцатеричное число). В слове конфигурации устанавливаются (или не устанавливаются) биты защиты, выбирается режим работы тактового генератора и некоторые параметры, относящиеся к режиму питания контроллера.
Вот первый вариант слова конфигурации для тактовой частоты 16-20 МГц:
• Бит 13 устанавливаем в «1» - выключаем защиту кода.
• Бит 8 устанавливаем в «1» - выключаем защиту EEPROM.
• Бит 7 устанавливаем в «0» - вывод RB4 работает как цифровой канал ввода-вывода.
• Бит 6 устанавливаем в «0» - запрещаем сброс по снижению напряжения питания.
• Бит 5 устанавливаем в «0» - вывод RB5 работает как цифровой канал ввода-вывода.
• Бит 4 устанавливаем в «О» - режим HS генератора, кварц к выводам RA6 и RA7.
• Бит 3 устанавливаем в «О» - выключаем режим включения по таймеру.
• Бит 2 устанавливаем в «О» - выключаем режим работы сторожевого таймера.
• Бит 1 устанавливаем в «1» - режим HS генератора, кварц к выводам RA6 и RA7.
• Бит 0 устанавливаем в «О» - режим HS генератора, кварц к выводам RA6 и RA7.
Слово конфигурации будет выглядеть так - 3F0Ah.
Для работы внутреннего тактового генератора следует использовать кварцевый резонатор с параллельным резонансом на 16-20 МГц (рис. 1.36).
Рис. 1.36. Типовая схема включения кварцевого резонатора для PIC16F628A |
Для частоты 16 МГц рекомендованные значения 10-22 пФ конденсаторов С1 и С2.
Давайте подумаем, а не использовать ли встроенный в контроллер генератор. Будем ли мы выполнять какие-либо операции, требующие стабильной тактовой частоты? На стабильность частоты внутреннего генератора, в первую очередь, влияет температура и напряжение питания. Будут ли они значительно меняться? Если мы не планируем использовать модуль в уличном исполнении, температура меняется мало. Если же после входного напряжения 12 В мы поставим стабилизатор на 5 В, питающее напряжение будет изменяться еще меньше. В данный момент я больше склонен отказаться от кварцевого резонатора и использовать внутренний тактовый генератор.
В этом случае есть два варианта на выбор. Для использования режима ER (3,6 МГц) к выводу RA7 микросхемы подключается резистор (не более 40 кОм). Вывод RA6 может использоваться для ввода-вывода.
Второй вариант слова конфигурации:
• Биты 13-10 устанавливаем в «1» - выключаем защиту кода.
• Бит 8 устанавливаем в «1» - выключаем защиту EEPROM.
• Бит 7 устанавливаем в «0» - вывод RB4 работает как цифровой канал ввода-вывода.
• Бит 6 устанавливаем в «0» - запрещаем сброс по снижению напряжения питания.
• Бит 5 устанавливаем в «0» - вывод RB5 работает как цифровой канал ввода-вывода.
• Бит 4 устанавливаем в «1» - режим ER, резистор 40 кОм подключается к RA7.
• Бит 3 устанавливаем в «0» - выключаем режим включения по таймеру.
• Бит 2 устанавливаем в «0» - выключаем режим работы сторожевого таймера.
• Бит 1 устанавливаем в «1» - режим ER генератора, резистор подключается к RA7.
• Бит 0 устанавливаем в «0» - режим ER генератора, резистор подключается к RA7.
Слово конфигурации будет выглядеть так - 3FlAh
Еще более удобный вариант - использование внутреннего генератора без внешних элементов INTRC (4 МГц). Слово конфигурации в этом случае - 3F18h.
Здесь я хотел бы сделать замечание, или признание - как вам угодно. Я впервые буду использовать контроллер PIC16F628A и пользоваться средой программирования контроллера MPLAB Может возникнуть закономерный вопрос - а чему я могу научить кого-то, если сам впервые это делаю? Если вас смущает данный аспект, можете обратиться к многочисленной литературе по программированию контроллеров, пропустив дальнейшее, что и решит проблему. Но мне кажется, что, имея большой опыт работы, основательно забываешь трудности, с которыми столкнулся в начале. А если сам только начинаешь работать, эти трудности налицо.
В блоке инициализации контроллера необходимо, в первую очередь, установить конфигурацию портов А и В.
Нам потребуется установить биты порта А 0-6 на вывод, бит 7 - на ввод (к выводу RA7 порта подключается резистор в режиме ER) или все выводы порта А - на вывод для режима генератора INTRC.
Для этого в регистр TRISA необходимо записать «1» для входных выводов и «0» для выходных. Ниже приведен пример инициализации для порта А, взятый из руководства:
CLRF PORTA ;Initialize PORTA by setting output data latches
; (инициализация установкой защелок данных) MOVLW 0x07 ;Turn comparators off and enable pins for I/O functions
MOVWF CMCON ; (выключение компараторов для I/O функции) BCF STATUS, RPl
BSF STATUS, RPO ;Select Bankl (выбор банка 1) MOVLW 0x80 ;Value used to initialize data direction MOVWF TRISA ;Set RA<4:0> as outputs TRISA<5> always read as '1'.
;TRISA<7:6> depend on oscillator mode ; (в данном случае все на вывод, 7 ввод)
Здесь 0x07 означает, что число 7 - шестнадцатеричное. Инициализация порта В связана, прежде всего, с необходимостью использования USART. Необходимо установить RB0 на
Вывод и записать в него «О» (при передаче записывается «1»). Затем:
• RB1 устанавливается на ввод, a RB2 - на вывод;
• RB3 установим на вывод (для управления микросхемой МАХ1483);
• RB4-RB7 устанавливаем на ввод для организации адресного селектора.
CLRF PORTB ;Initialize PORTB by setting output data latches
;(инициализация установкой защелок данных) MOVLW 0xF2 /Value used to initialize data direction MOVWF TRISB
Запишем необходимые данные в регистр управления приемника USART - RCSTA (адрес 18h):
• Бит 7 - «1» - модуль включен;
• Бит 6 - «О» - 8-битный прием;
• Бит 5 - не имеет значения;
• Бит 4 - «1» - прием разрешен;
• Бит 3 - не имеет значения;
• Бит 2 - только на чтение;
• Бит 1 - только на чтение;
• Бит 0 - только на чтение.
Операции записи побитовые:
BSF RCSTA, SPEN BCF RCSTA, RX9 BSF RCSTA, CREN
Аналогично запишем данные в регистр передатчика USART - TXSTA (адрес 98h):
• Бит 7 - не имеет значения;
• Бит 6 - «О» - 8-битная передача;
• Бит 5 - «1» - разрешение передачи;
• Бит 4 - «О» - асинхронный режим работы;
• Бит 3 - не используется;
• Бит 2 - «1» - высокоскоростной режим;
• Бит 1 - только чтение;
• Бит 0 - проверку четности мы не используем.
BCF TXSTA, ТХ9 BCF TXSTA, SYNC BSF TXSTA, BRGH
BSF TXSTA, TXEN (эта команда появится, когда мы начнем передачу статуса).
Кроме того, необходимо задать скорость работы в регистре SPBRG. Для первого варианта тактового генератора (SYNC = О, BRGH = 1,16 МГц):
MOVLW 0x67 MOVWF SPBRG
Для второго варианта тактового генератора (SYNC = О, BRGH = 1,3,6 МГц):
MOVLW 0x16 MOVWF SPBRG
В результате блок инициализации (для второго варианта) будет выглядеть следующим образом:
List p=16f628a #include pl6f628a. inc
; Инициализация модуля
BCF STATUS, RPl ; Выбор банка 0 BCF STATUS, RPO
Если посмотреть раздел организации памяти контроллера, видно, что часть регистров, которые мы используем, находится в банке «О», а часть в банке «1». Если забыть переключиться, команды могут не выполняться, а среда программирования MPLAB напомнит, выводя в окне Output на странице MPLAB SIM напоминания при трансляции программы. Это были первые грабли, на которые я часто наступал.
CLRF PORTA ; Настройка порта А.
MOVLW 0x07
MOVWF CMCON
BCF STATUS, RPl BSF STATUS, RPO
MOVLW 0x80 MOVWF TRISA
MOVLW 0xF6 MOVWF TRISB
Выбор банка 1. Настройка порта В. Выбор банка 0. |
BCF STATUS, RPl BCF STATUS, RPO CLRF PORTB
;Настройка приемопередатчика USART.
BSF RCSTA, SPEN ; Настройка приемника. BCF RCSTA, RX9 BSF RCSTA, CREN
Выбор банка 1.
Настройка передатчика.
Выбор банка 0.
Считывание собственного адреса.
Прочитаем порт В.
Нам не нужны младшие биты.
Сохраним адрес в регистре 2Oh.
BCF STATUS, RPl BSF STATUS, RPO BCF TXSTA, TX9 BCF TXSTA, SYNC BSF TXSTA, BRGH MOVLW 0x16 MOVWF SPBRG BCF STATUS, RPl BCF STATUS, RPO CLRW ADDWF PORTB, 0 ANDLW OxFO MOVWF 0x20 SWAPF 0x20, 1 CALL adrsim |
Нам не нужна работа с младшими битами.
Преобразуем его в символьный вид.
Чтобы сравнить адрес, задаваемый переключателем, с адресом в слове команды, нужно преобразовать их к единому
Виду. Здесь существует несколько возможностей. Я использую одну из них, вы можете поступить иначе.
; прочитаем из EEPROM в 30h - состояние реле.
Необязательно хранить текущее состояние реле в энергонезависимой памяти. Но это может быть полезно и, кроме того, дает возможность разобраться с механизмом записи в энергонезависимую память. Можно, например, изменить метод задания адреса. Использовать вместо переключателя в адресном селекторе программную установку адреса - запись адреса в энергонезависимую память контроллера. Так, в частности, устроены некоторые промышленные модули. В этом случае перед первым использованием модуля его переводят в режим установки адреса и программно устанавливают этот адрес. Механизм записи состояния реле и адреса одинаков.
BSF STATUS, RPO ; Выбор банка 1. BCF STATUS, RPl MOVLW 0x00
MOVWF EEADR ; Адрес считываемого регистра.
BSF EEC0N1, RD ; Чтение.
MOVF EEDATA, W ; w = EEDATA.
BCF STATUS, RPl ; Выбор банка 0.
BCF STATUS, RPO
MOVWF 0x30
COMF 0x30,1 ; Будем хранить в EEPROM в инверсном виде. CLRW
ADDWF 0x30,0 ; А в регистре 30h в прямом. MOVWF PORTA ; Перепишем 30h в порт.
Сохранение состояния реле в инверсном виде связано с тем, что в EEPROM по умолчанию записаны единицы. При инициализации прочтение состояния приведет к включению всех реле. Чтобы избежать этого, будем инвертировать прочитанное.
В строке «CALL adrsim» мы вызываем подпрограмму, которая переводит адреса в символы:
Это опять-таки не обязательно делать в данном программном блоке. Но оставлять в блоке инициализации длинный «хвост» мне не захотелось. Перевод адреса в символьное
Представление можно сделать различными способами, я выбрал самый очевидный.
Поскольку мы используем символьный обмен, я выпишу шестнадцатеричные коды некоторых символов ASCII:
«О» - 30h; «1» - 31h; «2» - 32h; «З» - 33h; «4» - 34h; «5» - 35h ит. д.
«R» - 52h; «$» - 24h; «#» - 23h; «N» - 4Eh; «F» - 46h; «S» - 53h
; Подпрограмма перевода адреса в символ (храним по адресам 21h, 22h).
Adrsim: CLRW ; Если адрес 1 запишем символы "О" "1" (30h и 31h).
ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x31 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x1 BTFSC STATUS, Z RETURN
CLRW ; Если адрес 2 запишем символы "0" "2й (30h и 32h). ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x32 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x2 BTFSC STATUS, Z RETURN
CLRW ; Если адрес 3 запишем символы "0" "3". ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x33
MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x3 BTFSC STATUS, Z RETURN
CLRW ; Если адрес 4 запишем символы "0" "4". ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x34 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x4 BTFSS STATUS, Z RETURN
CLRW ; Если адрес 5 запишем символы и0" "5й. ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x35 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x5 BTFSS STATUS, Z RETURN
CLRW ; Если адрес 6 запишем символы "0" "6". ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x36 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x6 BTFSS STATUS, Z RETURN
CLRW ; Если адрес 7 запишем символы "0й "7". ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x37 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x7 BTFSS STATUS, Z RETURN
CLRW ; Если адрес 8 запишем символы "0" "8". ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x38 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x8 BTFSS STATUS, Z RETURN
CLRW ; Если адрес 9 запишем символы "0" "9" ADDLW 0x30 MOVWF 0x21 CLRW
ADDLW 0x39 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW 0x9 BTFSS STATUS, Z RETURN
CLRW ; Если адрес 10 (Ah) запишем символы "1" "0й. ADDLW 0x31 MOVWF 0x21 CLRW
ADDLW 0x30 MOVWF 0x22 MOVF 0x20, 0
BCF STATUS, z XORLW ОхА BTFSS STATUS, Z RETURN
CLRW ; Если адрес 11 (Bh) запишем символы "1" "1". ADDLW 0x31 MOVWF 0x21 CLRW
ADDLW 0x31 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW OxB BTFSS STATUS, Z RETURN
CLRW ; Если адрес 12 (Ch) запишем символы "Iй "2". ADDLW 0x31 MOVWF 0x21 CLRW
ADDLW 0x32 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW OxC BTFSS STATUS, Z RETURN
CLRW ; Если адрес 13 (Dh) запишем символы "1" "3й. ADDLW 0x31 MOVWF 0x21 CLRW
ADDLW 0x33 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW OxD BTFSS STATUS, Z RETURN
CLRW ; Если адрес 14 (Eh) запишем символы "Iй "4". ADDLW 0x31
MOVWF 0x21 CLRW
ADDLW 0x34 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW OxE BTFSS STATUS, Z RETURN
CLRW ; Если адрес 15 (Fh) запишем символы "1" "5". ADDLW 0x31 MOVWF 0x21 CLRW
ADDLW 0x35 MOVWF 0x22 MOVF 0x20, 0 BCF STATUS, Z XORLW OxF BTFSS STATUS, Z RETURN