Ключевое ?лово

vk

Рассмотрим 3 основных варианта добавления портов на микроконтроллерах или одноплатных компьютерах:

Микросхема MCP23017

MCP23o17Микросхема MCP23017 добавляет 16 портов,которые можно настроить как на вход,так и на выход.

Микросхема использует популярную двухпроводную шину I2C. Имеет очень гибкие настройк.

Микросхемы MCP23017 можно нарасщивать до 8 штук на одной шине I2C ,например используя 3 провода (+питание) можно их разводить по квартире для уменьшения количества проводов к датчикам и исполнительным механизмам.Каждой микросхеме задается адрес через выводы А0,А1,А2 в двоичном виде , подключив их к минусу или плюсу.Цена одной микросхемы MCP23017 - 1.5$. 

Существует так же вариант микросхемы MCP23S17 ,которая использует шину SPI .

Работа MCP23017 в Arduino

 У плат Arduino имются отдельные выводы SCL и SDA ,но например плат,основанных на ATMEGA328P устройства подключаются к аналоговым входам А5 (SCL) и А4(SDA) .Шины SCL и SDA должны быть "подтянуты" через резисторы 4.7KoM к плюсу.
.Назначение выводов  определяется скетчем.

Библиотека для работы MCP23017 с Arduino: MCP23x17.zip 

Для некоторых случаев может быть выгоднее использовать MCP23017 без использования библиотек,смотрите пример ниже:

 
// Arduino code ,используется банк А на вход,а банк В - на вывод.

// pins 15,16 и 17 к GND для I2C шины адреса 0x20

#include "Wire.h"     // подключаем библиотеку I2C
byte a=0;
boolean registers[8]; // храним состояние регистров банка В


void setup()
{
  
Serial.begin(9600);
    
  
Wire.begin();                // wake up I2C bus
// настраиваем банк B на вывод
Wire.beginTransmission(0x20);// подключение к чипу
Wire.write((byte)0x01);      // выбираем банк B
Wire.write((byte)0x00);      // установка банка B на вывод,точнее устанавливаем на всех выводах значение 0
Wire.endTransmission();      // отключаемся.
//

}

void loop()
{
// чтение банки A
Wire.beginTransmission(0x20); // подключение к чипу
Wire.write(0x12);             // выбираем для работы банку A
Wire.endTransmission();       // отключаемся.
Wire.requestFrom(0x20, 1);    // отправляем один байт
a=Wire.read();                // чтение состояния портов банка А в переменную 'a'

// выводим состояние портов банка А,если на них подан минус.
if (!((a>>0)&1))  Serial.print(0);
if (!((a>>0)&2))  Serial.print(1);
if (!((a>>0)&4))  Serial.print(2);
if (!((a>>0)&8))  Serial.print(3);
if (!((a>>0)&16))  Serial.print(4);
if (!((a>>0)&32))  Serial.print(5);
if (!((a>>0)&64))  Serial.print(6);
if (!((a>>0)&128))  Serial.print(7);

//  Serial.print(a);

Serial.println("--");
 
// тест мигалка на выводе банки В порта номер 3
mcWrite(3,0); 
delay(500);

mcWrite(3,1);
delay(500);
}




// подпрограмма записи в банк B
void mcWrite(int whichPin, int whichState) {
 byte d=0;
 byte l=1;
  registers[whichPin] = whichState;

for(int i = 0; i <=  7; i++){
d=registers[i]*l+d;
l=l*2;
}
//запись в банк B
Wire.beginTransmission(0x20);  // подключение к чипу
Wire.write(0x13);              // выбираем для работы банку B
Wire.write(d);                 // запись байта
Wire.endTransmission();        // отключаемся

}

 

Работа MCP23017 с Raspberry PI

 

Пример кода для работы в Linux находится в статье GPIO на любом компьютере.

 
Не забывайте ,что для работы с шиной I2C необходим загруженный модуль i2c-dev и для проверки работы и управления из консоли нужна утилита i2c-tools -подробнее в статьях про Rasperry PI.

Кроме Raspberry PI микросхему MCP23O17 можно подключить к любому компютеру через переходник I2C-USB ,например через этот.Подробнее про это тут.

 Микросхема регистр 74HC595

74HC595Регистр 74HC595  дает возможность добавить 8 портов на выход,но при этом занимает 3 цифровых выхода.

Микросхемы 74HC595 так же можно наращивать для увеличения выводов и при этом дополнительные выводы микропроцессора не занимаются.Цена одной микросхемы 74HC595 - 0.20$.

 

 

 

 

 
int SER_Pin = 9;   //pin 14 (DS) на 75HC595
int RCLK_Pin = 8;  //pin 12 (ST_CP) на 75HC595
int SRCLK_Pin = 7; //pin 11 (SH_CP) на 75HC595

//количество регистров
#define number_of_74hc595s 2 

//не трогать !
#define numOfRegisterPins number_of_74hc595s * 8
boolean registers[numOfRegisterPins];
//

void setup(){
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);

}

void registerWrite(int whichPin, int whichState) {
registers[whichPin] = whichState;

  digitalWrite(RCLK_Pin, LOW);

  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(SRCLK_Pin, LOW);

    int val = registers[i];

    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);

  }
  digitalWrite(RCLK_Pin, HIGH);

}


Пример подпрограммы для использования 2 регистров,изменение статуса вызывается через registerWrite(номер_порта, LOW);

 
 
// 
#include <SPI.h>

#define SS_HC595 45 // ST_CP(12)

// SH_CP (11) на SCK (13 uno,52 mega)
// DS(14) на MOSI (11 uno,51 mega)
//SER (10) на минус или при каскаде-с предыдущего регистра

//количество регистров 1 или 2
#define number_of_74hc595s 1 

//не трогать !
#define numOfRegisterPins number_of_74hc595s * 8
boolean registers[numOfRegisterPins];

void setup()
{

//  Serial.begin(9600);
  
 SPI.begin();

  pinMode(SS_HC595, OUTPUT);
// pinMode(13, OUTPUT);   
}
void loop()
{
//  digitalWrite(13, HIGH);  
registerWrite(4,1); 
delay(1000);
// digitalWrite(13, LOW);
registerWrite(4,0);
delay(1000);
}

void registerWrite(byte whichPin, byte whichState) {
  
 // int d=0; //для 2 регистров
 byte d=0;
 
 byte l=1;
  registers[whichPin] = whichState;

for(byte i = 0; i <=  7; i++){
d=registers[i]*l+d;
l=l*2;
}
digitalWrite(SS_HC595, HIGH);

SPI.transfer(d);

//для 2 регистров:
//  SPI.transfer(highByte(d));
//  SPI.transfer(lowByte(d));

digitalWrite(SS_HC595, LOW);

}

 

 

 Микросхема регистр 74HC165

 74HC165

 Регистр 74HC165  дает возможность добавить 8 портов на вход,но при этом занимает 3 цифровых выхода.

Микросхемы 74HC165 так же можно наращивать для увеличения входов и при этом дополнительные выводы микропроцессора не занимаются.Цена одной микросхемы 74HC165 - 0.35$.

 

 

 

 
// 
#define latch_SH_in 44 // SH(1)
#define data_SH_in 50  // QH (9)
#define clock_SH_in_out 52// CLK(2)
//CLK INH(15) на минус
//SER (10) на минус или при каскаде-с предыдущего регистра


void setup()
{

  Serial.begin(9600);
  
  pinMode(latch_SH_in, OUTPUT);
  pinMode(data_SH_in, INPUT);
  pinMode(clock_SH_in_out, OUTPUT);


}
void loop()
{

uint8_t a = 0; //int,если 2 регистра. 
digitalWrite(latch_SH_in, HIGH);

for (int i=7; i>=0; i--) { // i=15,если 2 регистра
   digitalWrite(clock_SH_in_out,LOW);
   delayMicroseconds(1);
   a |= (digitalRead(data_SH_in) ? (1<<i) : 0);
   digitalWrite(clock_SH_in_out,HIGH);   
   delayMicroseconds(1);

  }
  
digitalWrite(latch_SH_in, LOW);

Serial.print("<");
Serial.print(a, BIN);
Serial.print(">");

if (!((a>>0)&1))  Serial.print(0);
if (!((a>>0)&2))  Serial.print(1);
if (!((a>>0)&4))  Serial.print(2);
if (!((a>>0)&8))  Serial.print(3);
if (!((a>>0)&16))  Serial.print(4);
if (!((a>>0)&32))  Serial.print(5);
if (!((a>>0)&64))  Serial.print(6);
if (!((a>>0)&128))  Serial.print(7);
// выдаст номера портов,которые подключены на GND.
  
Serial.println("--");
delay(1000); 
}

 

 

 

 
// 
#include <SPI.h>

#define SS_HC165 8 // SH(1)

// QH (9) на SCK (13 uno,52 mega)
// CLK(2) на MISO (12 uno,50 mega)
//CLK INH(15) на минус
//SER (10) на минус или при каскаде-с предыдущего регистра

void setup()
{

  Serial.begin(9600);
  
 SPI.begin();
  pinMode(SS_HC165, OUTPUT);
}
void loop()
{

digitalWrite(SS_HC165, HIGH);
uint8_t a = SPI.transfer(0);
digitalWrite(SS_HC165, LOW);

Serial.print(a,BIN);
Serial.print(">");
if (!((a>>0)&1))  Serial.print(0);
if (!((a>>0)&2))  Serial.print(1);
if (!((a>>0)&4))  Serial.print(2);
if (!((a>>0)&8))  Serial.print(3);
if (!((a>>0)&16))  Serial.print(4);
if (!((a>>0)&32))  Serial.print(5);
if (!((a>>0)&64))  Serial.print(6);
if (!((a>>0)&128))  Serial.print(7);
// выдаст номера портов,которые подключены на GND.
  
Serial.println("--");
delay(1000); 
}

 

 

 

 74HC165 и 74HC595 при использовании вместе могут использовать общий пин синхронизации.В итоге при подключении к м/к в сумме используют 5 выводов.

При использовании варианта с SPI на шине могут находится другие устройства,например Ethernet .В итоге используется дополнительно всего 1 вывод на регистр для выбора канала,а SCK,MISO,MOSI - общие. 

 

Микросхема PCF8574

PCF8574Микросхема PCF8574.Так же используется шина  I2C,но выводов всего 8.

Примерная цена 1.15$.

 

#include <Wire.h>

#define expander B0100000  // адрес на шине i2c
                           

void setup() {
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  Serial.println("Writing B00000000.");
  expanderWrite(B00000000);
  Serial.print("Read: ");
  Serial.println(expanderRead(), BIN);
  delay(1000);
  Serial.println("Writing B11111111.");
  expanderWrite(B11111111);
  Serial.print("Read: ");
  Serial.println(expanderRead(), BIN);
  delay(1000);
}


void expanderWrite(byte _data ) {
  Wire.beginTransmission(expander);
  Wire.write(_data);
  Wire.endTransmission(); 
}

byte expanderRead() {
  byte _data;
  Wire.requestFrom(expander, 1);
  if(Wire.available()) {
    _data = Wire.read();
  }
  return _data;
}

Данный скетч не тестировался !!
 

 

 

Примеры реализации расширения портов можно посмотреть тут .

{showhide title="Откройте,чтобы увидеть пример работы MCP23017 с Arduino и Energia без использования библиотек."changetitle="Закройте"}

Home`s Smart © 2013-2016. г.Киров.
Цитирование материалов возможно только со ссылкой на сайт. Использование фотоматериалов только с разрешения авторов.