Представленная ниже программа предназначена для микроконтроллера PIC12F629, управляющего работой портативного устройства копирования микросхем памяти серии 24Cxx.
При написании программы использовались стандартные процедуры, позволяющие программно реализовать мастер-абонента шины I2C в режиме single-master. Единственное изменение, которое было сделано при их включении в нашу программу, — это клонирование всех процедур, работающих с линией DATA, для возможности работы с двумя независимыми линиями DATA. Таким образом, у нас получились процедуры, работающие с линией DATA микросхемы-источника (процедуры с индексом T: Data_T_One, Data_T_null и т.д.) и процедуры, работающие с линией DATA микросхемы приёмника (процедуры с индексом R: Data_R_One, Data_R_null и т.д.). Далее вся логика работы собрана из этих стандартных процедур, как из конструктора.
Поскольку алгоритмы стандартных процедур подробно разобраны в отдельной статье, то здесь мы их описывать не будем.
Алгоритм работы управляющей программы:
list p = 12f629 __config 01FC4h ;*** Переменные ****************************************** CBLOCK 0x20 ; Начальный адрес блока пользовательской памяти I2C_flags ; 20h Bit_counter ; 21h BTS ; byte to send 22h RDB ; recieved byte 23h Buf_counter ; кол-во байт в буфере 24h Page_counter_low ; кол-во обработ-х страниц 25h младший байт Page_counter_high ; кол-во обработ-х страниц 26h старший байт Banks ; адрес банка 27h Counter1 ; 28h Counter2 ; 29h ; дальше, по адресам с 2Ah по 31h, будем хранить буфер страницы из 8 байт ENDC ;**** Константы / Адреса регистров ************************ Status equ 03h ; выбор банка Cmcon equ 19h ; Регистр Cmcon - компаратора (банк 0) OSCCAL equ 10h ; Регистр хранения калибровочной константы (банк 1) INDF equ 0h ; Регистр косвенной адресации FSR equ 04h ; Регистр адреса при косвенной адресации ;--------------------------- Port_reg equ 05h ; GPIO - управления защелками порта Tris_reg equ 05h ; TrisIO - выбор направления работы выводов порта Clock_line equ 04h ; GP4 Data_T_line equ 01h ; GP1 Data_R_line equ 05h ; GP5 ;********************************************************** ; GP0 - светодиод, GP1 - Data трансмиттера, GP2 - вход JP1, ; GP3 - кнопка, GP4 - Clock, GP5 - Data приемника ; в каждом банке 24Сxx может быть максимум 32 (20h) ; страницы по 8 байт при однобайтном счётчике ; или 8192 (2000h) страницы по 8 байт при двухбайтном счётчике ;********************************************************** org 0 ;********************************************************* ;*** КОНФИГУРИРОВАНИЕ КОНТРОЛЛЕРА ************************ ;*** Калибровка Генератора ******************************* start bsf Status,5 Call 3FFh ; Загрузить калибровочную константу в w movwf OSCCAL ;*** Установка направления работы ног ******************** main bcf Status,5 ; перейти в банк 0 clrf Port_reg ; инициализация защелок (все выходы равны нулю) movlw .7 ; биты 0..2 поднять movwf Cmcon ; компаратор выключен, GP0, GP1, GP2 - цифровые вх/вых bsf Status,5 ; Перейти в 1-й банк movlw b'00111110' ; настройка выходов, ; GP3 - вход, Clock и обе Datы сначала ставим на вход) movwf Tris_reg bcf Status,5 ; перейти в банк 0 ;*** РАБОЧАЯ ЧАСТЬ *************************************** clrf I2C_flags ;--- Читаем джампер ------------------- btfsc Port_reg,2 ; если JP1 замкнут - на входе 0 (однобайтный адрес) bsf I2C_flags,1 ; флаг 1 будет хранить выбранный тип адресации ;--- Инициализируем банки ------------- movlw 0A0h ; сначала пишем в первый банк movwf Banks ;----------------------------------- work btfsc Port_reg,3 ; если вх.кнопки=0 -> значит она нажата goto work ;------------------------------------ ;--- Инициализация адреса первой микрухи ------ no_ack1 call Start_T_uslovie ; старт movlw 0A0h movwf BTS call Send_T_Byte ; посылаем А0 - передача btfsc I2C_flags,0 goto no_ack1 movlw .0 movwf BTS call Send_T_Byte ; посылаем начальный адрес movlw .0 movwf BTS btfsc I2C_flags,1 call Send_T_Byte ; если флаг адресации=1, - шлём второй байт адреса call Stop_T_uslovie ;------------------------------------ next_bank clrf Page_counter_low clrf Page_counter_high ;--- Чтение из микрухи 1 ------------ next_page call Start_T_uslovie ; старт movlw 0A1h movwf BTS call Send_T_Byte ; посылаем А1 - приём ;----------------------- movlw .7 movwf Buf_counter movlw 2Ah movwf FSR ;----------------------- next_byte_rt call Recieve_T_Byte ; принимаем байт movf RDB,0 movwf INDF ; и сохраяем его по адресу FSR incf FSR,1 decfsz Buf_counter,1 goto next_byte_rt bsf I2C_flags,0 call Recieve_T_Byte ; дочитываем последний байт страницы movf RDB,0 movwf INDF ; и сохраяем его по адресу FSR Call Stop_T_uslovie ; стоп ;------------------------------------ ;------------------------------------ ;--- Запись в микруху 2 ------------- call Start_R_uslovie ; старт movf Banks,0 movwf BTS call Send_R_Byte ; посылаем заявку на передачу в нужный банк btfsc I2C_flags,0 goto no_bank ; если нет ответа - значит этот банк отсутствует movf Page_counter_high,0 movwf BTS call Send_R_Byte ; посылаем начальный адрес movf Page_counter_low,0 movwf BTS btfsc I2C_flags,1 call Send_R_Byte ; если флаг адресации=1, - шлём второй байт адреса ;----------------------- movlw .7 movwf Buf_counter movlw 2Ah movwf FSR ;----------------------- next_byte_tr movf INDF,0 ; читаем байт из буфера movwf BTS call Send_R_Byte ; шлём байт incf FSR,1 decfsz Buf_counter,1 goto next_byte_tr movf INDF,0 ; читаем байт из буфера movwf BTS call Send_R_Byte ; шлём последний байт страницы Call Stop_R_uslovie ; стоп ;--- Ждём окончания записи ------------- no_ack2 call Start_R_uslovie ; старт movlw 0A0h movwf BTS call Send_R_Byte ; посылаем A0 - запись btfsc I2C_flags,0 goto no_ack2 call Stop_R_uslovie ;------------------------------------ btfsc I2C_flags,1 ; если 1 байт адреса - пропустить следующ.команду goto extended_address movlw .8 addwf Page_counter_high,1 btfss Status,2 ; если счетчик=0, - мы скопировали банк целиком goto next_page goto no_bank ;------------------------------------ ;--- для двухбайтного счётчика ------ extended_address movlw .8 addwf Page_counter_low,1 btfsc Status,2 ; если счётчик не=0 - следующ. команда пропуск. incf Page_counter_high,1 ; увеличить старший байт адреса movf Page_counter_low,0 iorwf Page_counter_high,0 btfss Status,2 ; если оба счётчика=0, - скопирован весь банк goto next_page ;--- Проверяем, во все ли банки мы скопировали --- no_bank movlw .2 addwf Banks,1 movlw 0B0h xorwf Banks,0 btfss Status,2 ; если скопировали все банки - идём дальше goto next_bank ;------------------------------------ ;************************************ lamp_signal bsf Port_reg,0 call short_pause bcf Port_reg,0 call long_pause goto lamp_signal ;************************************ ;------------------------------------ Clock_null bcf Port_reg, Clock_line bsf Status,5 bcf Tris_reg, Clock_line bcf Status,5 return Clock_one bsf Status,5 bsf Tris_reg, Clock_line bcf Status,5 return Data_T_null bcf Port_reg, Data_T_line bsf Status,5 bcf Tris_reg, Data_T_line bcf Status,5 return Data_T_one bsf Status,5 bsf Tris_reg, Data_T_line bcf Status,5 return Data_R_null bcf Port_reg, Data_R_line bsf Status,5 bcf Tris_reg, Data_R_line bcf Status,5 return Data_R_one bsf Status,5 bsf Tris_reg, Data_R_line bcf Status,5 return ;------------------------------------ Start_T_uslovie call Clock_one call Data_T_null call Clock_null return Stop_T_uslovie call Data_T_null call Clock_one wait_clock_p btfss Port_reg, Clock_line goto wait_clock_p call Data_T_one return ;------------------------------------ Start_R_uslovie call Clock_one call Data_R_null call Clock_null return Stop_R_uslovie call Data_R_null call Clock_one wait_clock_p1 btfss Port_reg, Clock_line goto wait_clock_p1 call Data_R_one return ;------------------------------------ Send_T_Byte bcf I2C_flags,0 ; посылка байта микрухе источнику movlw .8 movwf Bit_counter next_bit_st btfsc BTS,7 Call Data_T_one btfss BTS,7 call Data_T_null call Clock_one wait_clock_st1 btfss Port_reg, Clock_line goto wait_clock_st1 call Clock_null rlf BTS,1 decfsz Bit_counter,1 goto next_bit_st call Data_T_one call Clock_one wait_clock_st2 btfss Port_reg, Clock_line goto wait_clock_st2 btfsc Port_reg, Data_T_line bsf I2C_flags,0 call Clock_null return ;------------------------------------ Recieve_T_Byte clrf RDB movlw .8 movwf Bit_counter next_bit_rt bcf Status,0 rlf RDB,1 call Data_T_one call Clock_one wait_clock_rt1 btfss Port_reg, Clock_line goto wait_clock_rt1 btfsc Port_reg, Data_T_line bsf RDB,0 call Clock_null decfsz Bit_counter,1 goto next_bit_rt btfss I2C_flags,0 call Data_T_null btfsc I2C_flags,0 call Data_T_one call Clock_one wait_clock_rt2 btfss Port_reg, Clock_line goto wait_clock_rt2 call Clock_null return ;--------------------------------- Send_R_Byte bcf I2C_flags,0 ; посылка байта микрухе приёмнику movlw .8 movwf Bit_counter next_bit_sr btfsc BTS,7 Call Data_R_one btfss BTS,7 call Data_R_null call Clock_one wait_clock_sr1 btfss Port_reg, Clock_line goto wait_clock_sr1 call Clock_null rlf BTS,1 decfsz Bit_counter,1 goto next_bit_sr call Data_R_one call Clock_one wait_clock_sr2 btfss Port_reg, Clock_line goto wait_clock_sr2 btfsc Port_reg, Data_R_line bsf I2C_flags,0 call Clock_null return ;--------------------------------- Recieve_R_Byte clrf RDB movlw .8 movwf Bit_counter next_bit_rr bcf Status,0 rlf RDB,1 call Data_R_one call Clock_one wait_clock_rr1 btfss Port_reg, Clock_line goto wait_clock_rr1 btfsc Port_reg, Data_R_line bsf RDB,0 call Clock_null decfsz Bit_counter,1 goto next_bit_rr btfss I2C_flags,0 call Data_R_null btfsc I2C_flags,0 call Data_R_one call Clock_one wait_clock_rr2 btfss Port_reg, Clock_line goto wait_clock_rr2 call Clock_null return ;************************************ short_pause movlw .100 movwf Counter1 cikl1 movlw .255 movwf Counter2 cikl2 nop nop decfsz Counter2,1 goto cikl2 decfsz Counter1,1 goto cikl1 return ;------------------------- long_pause movlw .250 movwf Counter1 cikl3 movlw .255 movwf Counter2 cikl4 nop nop decfsz Counter2,1 goto cikl4 decfsz Counter1,1 goto cikl3 return end ;--------------------------------- |