Что делать, если нужно управлять множеством выходов, а кол-во свободных портов МК ограничено?
Или управляемое устройство находится в некотором отдалении от управляющего блока (единицы-десятки метров). Не тянуть же к нему многожильный пучок проводов!
На помощь приходит 8-разрядный i2c-декодер. У него есть 8 двунаправленных выводов, которые могут работать как на выход, так и на вход (с некоторыми ограничениями, и здесь эта функция не использована).
Достаточно подключить на шину этот декодер, как мы получим 8 дополнительных TTL-выходов.
Путем изменения уровней на адресных выводах PCF8574 можно адресовать до 8 чипов, получив, таким образом, в общей сумме 64 (!) выхода, управляемых всего по 2 проводам.
Ниже приведена библиотечка для управления блоком из 8 реле, подключенных через буферный каскад к PCF8574.
' Этот модуль работает с 8-разрядным декодером PCF8574 на шине i2c,
' подключенным к блоку из 8 реле.
' Каждый разряд в байте состояния/управления отвечает за свое реле.
'
' ВНИМАНИЕ: биты в байте состояния реле ИНВЕРТИРОВАНЫ, так что
' НИЗКИЙ уровень (0) означает, что реле ВКЛЮЧЕНО,
' ВЫСОКИЙ уровень (1) - что реле ВЫКЛЮЧЕНО.
' Во избежание ошибок используйте константы RELAY_ON|OFF.
'
' ОБРАТИТЕ ВНИМАНИЕ: реле нумеруются от 0 до 7
$nocompile
const RELAY_ON = 0
const RELAY_OFF = 1
const RELAY_W = &H40 ' адрес записи в PCF8574 на шине i2c
const RELAY_R = &H41 ' адрес чтения из в PCF8574 на шине i2c
dim RELAY_bTMP as byte
dim RELAY_bStateStored as byte ' для запоминания/восстановления состояния всех реле
declare function RELAY_GetRelay(byval relay_num as byte) as byte ' прочитать состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
declare sub RELAY_SetRelay(byval relay_num as byte , byval state as byte) ' установить состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
declare sub RELAY_ToggleRelay(byval relay_num as byte) ' переключить реле #0...7
declare sub RELAY_RelaysOFF() ' выключить все реле
declare function RELAY_GetState() as byte ' прочитать состояние всех реле одним байтом
declare sub RELAY_SetState(byval relay_state as byte) ' установить состояние всех реле одним байтом
declare sub RELAY_Store() ' сохранить состояние всех реле
declare sub RELAY_Restotre() ' восстановить состояние всех реле
goto PCF8574_I2C_done ' требуется компилятору BASCOM при использовании оцпии "config submode = old"
macro RELAY_readI2C
i2cstart
i2cwbyte RELAY_R
i2crbyte RELAY_bTMP , nack
i2cstop
end macro
macro RELAY_writeI2C
i2cstart
i2cwbyte RELAY_W
i2cwbyte RELAY_bTMP
i2cstop
end macro
sub RELAY_RelaysOFF() ' выключить все реле
i2cstart
i2cwbyte RELAY_W
i2cwbyte 255
i2cstop
end sub
function RELAY_GetRelay(relay_num as byte) as byte ' прочитать состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
' прочитать текущее состояние всех реле
RELAY_readI2C
' смотря по состоянию заданного реле из байта состояния
if RELAY_bTMP.relay_num = RELAY_ON then
RELAY_GetRelay = RELAY_ON
else
RELAY_GetRelay = RELAY_OFF
end if
end function
sub RELAY_SetRelay(relay_num as byte , state as byte) ' установить состояние реле #0...7 (инвертировано! используйте RELAY_ON|OFF)
' прочитать текущее состояние всех реле
RELAY_readI2C
' сбросить бит заданного реле
RELAY_bTMP.relay_num = state.0
' записать обратно
RELAY_writeI2C
end sub
sub RELAY_ToggleRelay(relay_num as byte) ' переключить реле #0...7
' прочитать текущее состояние всех реле
RELAY_readI2C
' инвертировать бит заданного реле
RELAY_bTMP.relay_num = not RELAY_bTMP.relay_num
' записать обратно
RELAY_writeI2C
end sub
function RELAY_GetState() as byte ' прочитать состояние всех реле одним байтом
' прочитать текущее состояние всех реле
RELAY_readI2C
RELAY_GetState = RELAY_bTMP
end function
sub RELAY_SetState(relay_state as byte) ' установить состояние всех реле одним байтом
i2cstart
i2cwbyte RELAY_W
i2cwbyte relay_state
i2cstop
end sub
sub RELAY_Store() ' сохранить состояние всех реле
RELAY_bStateStored = RELAY_GetState()
end sub
sub RELAY_Restotre() ' восстановить состояние всех реле
RELAY_SetState RELAY_bStateStored
end sub
PCF8574_I2C_done: ' требуется компилятору BASCOM при использовании оцпии "config submode = old"






