Пишем программный код для подключения расширителя порта MCP23017 к atmega328P в среде программирования Atmel Studio.

Страница на этапе разработки

В данном уроке мы с Вами подключим расширитель портов MCP23017:

Подключать мы будем к микроконтроллеру Atmega328P, которая находиться на плате Arduino Nano:

Краткая характеристика расширителя портов MCP23017:
Разрешение: 16 бит
Интерфейс: I2C
Напряжение питания: 1.8–5.5 В
Каждая ножка может быть настроена как на вход так и на выход.
Таблица адресов регистров:

ввв

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

//адресса
#define MCP23017_AAA 0x00
#define MCP2301_ADRESS 0x40
//флаг записи
#define MCP23017_W 0x00
#define MCP23017_R 0x01
//регистры
#define MCP23017_IODIRA 0x00
#define MCP23017_IPOLA 0x02
#define MCP23017_GPINTENA 0x04
#define MCP23017_DEFVALA 0x06
#define MCP23017_INTCONA 0x08
#define MCP23017_IOCONA 0x0A
#define MCP23017_GPPUA 0x0C
#define MCP23017_INTFA 0x0E
#define MCP23017_INTCAPA 0x10
#define MCP23017_GPIOA 0x12
#define MCP23017_OLATA 0x14

#define MCP23017_IODIRB 0x01
#define MCP23017_IPOLB 0x03
#define MCP23017_GPINTENB 0x05
#define MCP23017_DEFVALB 0x07
#define MCP23017_INTCONB 0x09
#define MCP23017_IOCONB 0x0B
#define MCP23017_GPPUB 0x0D
#define MCP23017_INTFB 0x0F
#define MCP23017_INTCAPB 0x11
#define MCP23017_GPIOB 0x13
#define MCP23017_OLATB 0x15

#define MCP23017_INT_ERR 255

#define BANK 7
#define MIRROR 6
#define SEQOP 5
#define DISSLW 4
#define HAEN 3
#define ODR 2
#define INTPOL 1
#define Uniplemented 0

void I2C_init(void);// инициализация
void I2C_Start(void);//Старт
void I2C_Stop(void);//Стоп
void I2C_SendByte(unsigned char c);//отправка данных
void I2C_SendByteAdres(unsigned char c, unsigned char addr );// отправка данных по адресу
char I2C_ReadByte(void);// чтение байта
unsigned char I2C_ReadLastByte(void);// чтение последнего байта

//запись значения в регистр А-адрес D- данные
void MCP23017_write_Register(char A, char D){
I2C_Start();
I2C_SendByte(MCP2301_ADRESS|MCP23017_AAA|MCP23017_W);
I2C_SendByte(A);// отправляем адрес регистра
I2C_Start();//рестарт
I2C_SendByte(MCP2301_ADRESS|MCP23017_AAA|MCP23017_W);
I2C_SendByte(D);// отправляем байт данных
I2C_Stop();
}
//чтение значения регистра А-адрес
char MCP23017_read_Register(char A){
char R;
I2C_Start();
I2C_SendByte(MCP2301_ADRESS|MCP23017_AAA|MCP23017_W);
I2C_SendByte(A);// отправляем адрес регистра
I2C_Start();//рестарт
I2C_SendByte(MCP2301_ADRESS|MCP23017_AAA|MCP23017_R);
R=I2C_ReadByte();//читаем байт данных
I2C_Stop();
return R;
}

//функции работают при BANC = 0
#define MCP23017_DDRA_W(x) MCP23017_write_Register(MCP23017_IODIRA,~x)
#define MCP23017_DDRA_R MCP23017_read_Register(MCP23017_IODIRA)

#define MCP23017_PORTA_W(x) MCP23017_write_Register(MCP23017_OLATA,x)
#define MCP23017_PORTA_R MCP23017_read_Register(MCP23017_OLATA)

#define MCP23017_PINA_R MCP23017_read_Register(MCP23017_GPIOA)

#define MCP23017_PUDA_W(x) MCP23017_write_Register(MCP23017_GPPUA,x)
#define MCP23017_PUDA_R MCP23017_read_Register(MCP23017_GPPUA)

#define MCP23017_DDRB_W(x) MCP23017_write_Register(MCP23017_IODIRB,~x)
#define MCP23017_DDRB_R MCP23017_read_Register(MCP23017_IODIRB)

#define MCP23017_PORTB_W(x) MCP23017_write_Register(MCP23017_OLATB,x)
#define MCP23017_PORTB_R MCP23017_read_Register(MCP23017_OLATB)

#define MCP23017_PINB_R MCP23017_read_Register(MCP23017_GPIOB)

#define MCP23017_PUDB_W(x) MCP23017_write_Register(MCP23017_GPPUB,x)
#define MCP23017_PUDB_R MCP23017_read_Register(MCP23017_GPPUB)

 

 


int main(void)
{
I2C_init();
DDRB=0xFF;
char i=1;
MCP23017_DDRA_W(0b11111111);
MCP23017_DDRB_W(0b00000000);
while (1)
{
MCP23017_PORTA_W(0xFF);
PORTB=MCP23017_PINB_R;
_delay_ms(1000);
MCP23017_PORTA_W(0x00);
_delay_ms(1000);

}
}

void I2C_init(void){
TWSR=(0<<TWPS1)|(0<<TWPS0);// настройка делителя
TWBR=0x03; // настройка рабочей частоты шины
}

void I2C_Start(void){
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR&(1<<TWINT))){;}
}

void I2C_Stop(void){
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}

void I2C_SendByte(unsigned char c){
TWDR=c;
TWCR=(1<<TWINT)|(1<<TWEN);
while (!(TWCR&(1<<TWINT))){;}
}

void I2C_SendByteAdres(unsigned char c, unsigned char addr )
{
I2C_Start();
I2C_SendByte(addr);
I2C_SendByte(c);
I2C_Stop();
}

char I2C_ReadByte(void){
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
while (!(TWCR&(1<<TWINT))){;}
return TWDR;
}

unsigned char I2C_ReadLastByte(void){
TWCR=(1<<TWINT)|(1<<TWEN);
while (!(TWCR&(1<<TWINT))){;}
return TWDR;
}