I2C GPIO Interrupt PCF8574

Экономим порты (подключение кнопок по i2c)

Как известно, портов много не бывает. По этому жалко их тратить на подключение банальных кнопок. Особенно когда кнопок много.

Все уже придумали до нас. I2c шина позволяет подключить до 120 устройств потратив на это всего 2 пина на RPi.

Тем более, что есть отличная вешь: PCF8574(PCF8575). Дистанционный 8-битный расширитель ввода – вывода I2C-шины на 8(16) портов соответственно. Вот к нему то мы и будем цеплять кнопки.

Буква А в маркировке определяет базовый адрес чипа.

Буква P - тип корпуса (DIP1)Описание микросхемы для любознательных

Выводы A0-A2 позволяют изменить адрес чипа на шине путем подачи на них высокого или низкого уровня.

Hint: Обязательно подайте на них или 3.3В или массу. Не подключенные выводы источник презабавнейших глюков.VDD питание +3.3ВVSS земля.SDA/SCL соответственно I2C шина.P0-P7 8 доп портов.INT - крайне полезная вещь - выход прерывания. Т.е. нам не придется постоянно опрашивать микросхему, чтобы определить, изменилось ли состояние портов. Достаточно это сделать после прихода этого самого прерывания :)Я навесил на нее 2 кнопки на порты P4 и P5. Кнопки замыкают эти порты на землю. С железом на этом закончили. Далее все понятно из кода и коментариев к нему:

#!/usr/bin/python# -*- coding: utf-8 -*-# Адрес микросхемы PCF8574i2c_addr = 0x20#

импортируем необходимые библиотеки

import smbus as smbus
import RPIOfrom time 
import *from subprocess 
import Popen, PIPE

#configure I2C bus for functionsi2c = smbus.SMBus(1)# Настраиваем 25 порт GPIO и подтягиваем его на земл.
RPIO.setup(25, RPIO.IN, pull_up_down=RPIO.PUD_DOWN)# Здесь то, что мы делаем по приходу прерыванияdef gpio_callback(gpio_id, val):     

 try :     

 # Читаем из PCF8574          

temp = i2c.read_byte( i2c_addr )           
print 'PCF8574 at address 0x{0:2x} READ 0x{1:2x}'.format( i2c_addr, temp )     
except IOError :  print 'PCF8574 Device not found at I2C address 0x{1:2x}'.format( i2c_addr )            
error = 1      

# Нажата кнопка на порту P4     

 if (hex(temp)== hex(0xdf)):       
 # Тут я дергаю экранчик, подключение которого я в прошлой записи описывал.       
 #p = Popen('/home/pi/mj/LCD-Char/LCD-Test-mj-v4.py Key=1 1 VAL=Press 2', stdout=PIPE, shell=True)       
 print("gpio %s: %s" % (gpio_id, val))      

# Нажата кнопка на порту P5      

 if (hex(temp)== hex(0xef)):        

#p = Popen('/home/pi/mj/LCD-Char/LCD-Test-mj-v4.py Key=2 1 VAL=Press 2', stdout=PIPE, shell=True)       

 print("gpio %s: %s" % (gpio_id, val))       

# Одновременно нажаты обе кнопки       
if (hex(temp)== hex(0xcf)):        
#p = Popen('/home/pi/mj/LCD-Char/LCD-Test-mj-v4.py Key=1+2 1 VAL=Press 2', stdout=PIPE, shell=True)        
print("gpio %s: %s" % (gpio_id, val))       
fleg=1

# Настраиваем порт на ожидание прерываний и выполнение выщенаписанной функции
RPIO.add_interrupt_callback(25, gpio_callback, pull_up_down=RPIO.PUD_UP, debounce_timeout_ms=50)

# Ждем прихода прерывания.
RPIO.wait_for_interrupts()

Вот, собственно и все.

Тэги:

 

Автор:

Комментариев: 10

  • В.П. Столярчук10
    02.03.2014 в 12:53 ответ

    Это конечно прекрасно, но ты мне вот скажи, как мне зацепить на i2c несколько одинаковых температурных датчиков??? То что разные датчики можно подключать паралельно я занаю, а вот одинаковые датчики имеют одинаковые адреса. Мне нужно подключать их очень много.

    • m
      02.03.2014 в 15:41 ответ

      Использовать датчики, где адрес можно устанавливать самостоятельно

      • В.П. Столярчук10
        02.03.2014 в 23:33 ответ

        Дык какой например, да и сколько он будет стоить? Если брать например производителя DALLAS, то он будет стоить от 100р., но насколько мне известно, там адрес поменять нельзя.

        • m
          03.03.2014 в 04:55 ответ

          Например LM75AD

          • В.П. Столярчук10
            03.03.2014 в 17:13 ответ

            ОК, даташит скачал, вроде недорого, чота я не вкуриваю как работать с клемами A0-A2 ?! Мне в реале надо подсоединить не менее 64-х датчиков. Если есть возможность то можно пример исходника на С с сохранением данных в файл, буду благодарен.

            • mj1
              07.03.2014 в 09:50 ответ

              Клеммы А0-А2 это корректировщик адреса. Если на всех лог.0 то адрес равен адресу указанному в документации на ИС. а так, покавая на какую нибудь ногу (ноги) лог. 1 мы получаем обычное 3хбитное двоичное число, которое суммируется с базовым адресом из документации и получается новый адрес этой микрухи. Опять же, микрухи с различными буквенными индексами имеют разные базовые адреса (см. даташит).

      • В.П. Столярчук10
        02.03.2014 в 23:40 ответ

        Может быть есть какой нибудь контроллер, чтобы используя дополнительный пин для управления - циклом считывать данные по одному адресу по очереди с каждого датчика.

        • mj1
          07.03.2014 в 09:54 ответ

          не понял вопроса. Есть у тебя int (прерывание). Получил его, вызвал функцию и в цикле считал поочередно со своих датчиков что нужно. В коде у меня как раз это используется (правда код криво отображается, но разобраться можно. Если это то, что тебе нужно, но код непонятен, скажи, я простейший пример тут же в каментах покажу.

  • Ermito9
    13.12.2014 в 02:32 ответ

    Можете разьяснить для новичков. Дополнительное сопротивление между кнопкой и входом нужно вешать?

    • Ermito9
      15.12.2014 в 01:14 ответ

      Сам себе отвечу. не работало, потому что нужно предварительно питание на пины выставить # make certain the pins are set high so they can be used as inputs b.write_byte(PCF8574, 0xff)

Ваш комментарий

Авторизуйтесь для отправки комментария

© Сообщество пользователей RaspberryPi 2021