Подробнее об I²C
Этот раздел продолжает тему, начатую в разделе Передача и приём данных.
I²C (и множество его вариаций) использует для передачи данных в обоих направлениях одну линию данных (называется «SDA»). Линии DO и DI канала SSI необходимо соединить вместе. На устройствах с однонаправленными линиями ввода-вывода свойство ssi.zmode должно быть равно 1 - PL_SSI_ZMODE_ENABLED_ON_ZERO (на устройствах с двунаправленными линиями ввода-вывода это не требуется). Линия DO при этом работает так:
- Чтобы установить на линии DO высокий уровень (HIGH), устройство отключает выходной буфер. Линия «всплывает» до HIGH (из-за «слабых подтяжек» к питанию в устройстве). В этом состоянии ведомое SSI-устройство может безопасно выдавать на SDA собственные данные.
- Чтобы установить на линии DO низкий уровень (LOW), устройство включает выходной буфер и устанавливает на выходе LOW.
Отсюда следует: если линии DO и DI соединены и вы хотите принимать данные от ведомого устройства, на собственном выходе нужно держать «все единицы», пока ведомое устройство должно передавать данные, например так:
...
ssi.str("\x40\x12\xFF",1) 'we anticipate that the slave device will reply after we output two bytes of our own data
...
Каждый обмен по I²C требует так называемых стартовой и стоповой последовательностей - объект ssi. их не формирует, поэтому реализовать их нужно в коде. Ниже приведён фрагмент из реального приложения. Обратите внимание: необходимые переходы на линии SDA выполняются установкой на линии DO уровня LOW с последующим включением и отключением её выходного буфера.
...
i2c_start()
ssi.str("\x40\x12\xFF",1) 'output data, with acknowledgements enabled
i2c_stop()
...
'------------------------------------------------------------
Sub i2c_start()
io.lineset(SSI_CLK,HIGH)
io.num=SSI_DO 'set SDA to HIGH first so we can have HIGH->LOW transition
io.state=LOW 'we are manipulating data line through the OE register
io.enabled=NO
io.enabled=YES 'this will set the data output to LOW
End Sub
'------------------------------------------------------------
Sub i2c_stop()
io.lineset(SSI_CLK,LOW) 'this will remove the ack bit
io.num=SSI_DO 'set SDA to LOW first so we can have LOW->HIGH transition
io.state=LOW 'we are manipulating data line through the OE register
io.enabled=YES
io.lineset(SSI_CLK,HIGH)
io.enabled=NO 'this will set the data output to HIGH
End Sub