PIC: MCP23008
O MCP23008 é um dispositivo I2C escravo que fornece 8 saídas bi-direcionais.
Os quatro bits mais significativos do endereço do escravo são fixos (0100) e outros três bits são bits do endereço de hardware definidos pelo usuário (pinos A2, A1 e A0). Isso nos permite conectar até oito dispositivos MCP23008 em um mesmo barramento I2C.
Os bits individuais da porta GPIO de 8 bits pode ser configurado como entrada ou de saída. Os pinos da porta também pode ser habilitado o resistor pull-up interno e interrupção por mudança de estado. Estas operações são controladas através de um conjunto de configuração e controle de registros.
IODIR: Controla a direção dos pinos: 1 é entrada; 0 é saída.
IPOL: Controla a polaridade dos bits correspondentes de GPIO. Se definido com 1, o bit do registro GPIO irá armazenar o valor invertido do pino.
GPINTER: Controla o recurso de interrupção por mudança de estado. Se o bit é definido com 1, o pino correspondente estará habilitado para interrupção.
INTCON: Controla como o valor do pino associado é comparado com o recurso de interrupção. Se o bit é definido com 1, o pino I/O correspondente é comparado com o bit associado no registro DEFVAL. Se o bit é definido com 0, o pino I/O correspondente é comparado com o seu valor anterior.
DEFVAL: O valor de comparação padrão é configurado no registo DEFVAL. Se ativado (via GPINTEN e INTCON) para comparar com o registo DEFVAL, um valor oposto no pino associado irá causar uma interrupção. Por exemplo, se os bits GPINT6 (em GPINTEN), IOC6 (em INTCON) e DEF6 (em DEFVAL) = 1, então uma interrupção será gerada quando o pino GP6 é puxado para o nível baixo. A direção do pino GP6 deve ser definido como entrada.
IOCON: Ele contém vários bits para controlar o dispositivo:
- SEQOP controla a função de incremento do ponteiro de endereço. Se for definido com 0, ele estará ativado. O ponteiro do endereço dentro do MCP23008 será incrementada em 1 após cada byte de dados recebidos, se você começar a escrever um byte de registo 0x00 (que é IODIR), o segundo byte você enviar irá para o registro IPOL, terceiro byte vai para GPINTEN, e assim por diante. Isso é útil quando você tem que configurar diversos registros.
- DISSLW controla a taxa de variação no pino SDA.
- ODR configura o pino INT como uma saída em dreno aberto ou saída ativa. Se definido com 1, configura como dreno aberto.
- INTPOL configura a polaridade do pino INT. Esse bit é funcional somente quando o bit ODR = 0.
GPPU: Este registo controla os resistores pull-up para cada pino da porta. Se um bit é definido com 1 e o pino correspondente é configurado como uma entrada, o pino da porta correspondente é puxado internamente com um resistor.
INTF: Flag de interrupção. Se o bit estiver setado indica que o pino associado causou a interrupção. Este registro é "somente leitura".
INTCAP: Ele captura o valor da porta GPIO no momento que ocorreu a interrupção. O registo é atualizado apenas quando ocorre uma interrupção. O registo permanecerá inalterado até que a interrupção é eliminado através de uma leitura de INTCAP ou GPIO.
GPIO: Valor da porta. A leitura deste registro lê a porta. A escrita neste registro modifica o registro OLAT e o valor da porta.
OLAT: Fornece acesso as travas de saídas. Uma leitura resulta na leitura de OLAT e não da à própria porta. A escrita neste registro modifica o valor da saída dos pinos.
BIBLIOTECA
MikroC PRO PIC
//Registros
#define MCP23008_IORDIR 0x00
#define MCP23008_IPOL 0x01
#define MCP23008_GPINTEN 0x02
#define MCP23008_DEFVAL 0x03
#define MCP23008_INTCON 0x04
#define MCP23008_IOCON 0x05
#define MCP23008_GPPU 0x06
#define MCP23008_INTF 0x07 //Read-only
#define MCP23008_INTCAP 0x08 //Read-only
#define MCP23008_GPIO 0x09
#define MCP23008_OLAT 0x0A
#define MCP23008_ADDR 64
void MCP23008_WriteByte( char Address, char RegAddress, char _data )
{
I2C1_Start();
I2C1_Wr( MCP23008_ADDR | ( Address << 1 ) );
I2C1_Wr( RegAddress );
I2C1_Wr( _data );
I2C1_Stop();
}
char MCP23008_ReadByte( char Address, char RegAddress )
{
char read;
I2C1_Start();
I2C1_Wr( MCP23008_ADDR | ( Address << 1 ) );
I2C1_Wr( RegAddress );
I2C1_Repeated_Start();
I2C1_Wr( MCP23008_ADDR | 1 | ( Address << 1 ) );
Delay_ms( 1 );
read = I2C1_Rd(0);
I2C1_Stop();
return(read);
}
void MCP23008_Init( char Address )
{
I2C1_Start();
I2C1_Wr( MCP23008_ADDR | ( Address << 1 ) );
I2C1_Wr(0x00); // IODIR
I2C1_Wr(0x00); // GP0-GP7 como saída
I2C1_Wr(0x00); // IPOL
I2C1_Wr(0x00);
I2C1_Wr(0x00);
I2C1_Wr(0x00);
I2C1_Wr(0x22); // Desabilita escrita sequencial
I2C1_Stop();
}
//Faz a leitura da porta
char MCP23008_Read_Port( char Address )
{
return MCP23008_ReadByte( Address, MCP23008_GPIO );
}
//Escreve um valor para a porta
void MCP23008_Write_Port( char Address, char _data )
{
MCP23008_WriteByte( Address, MCP23008_GPIO, _data );
}
//Define a direção dos pinos( entrada ou saída )
void MCP23008_Set_DirectionPort( char Address, char direction )
{
MCP23008_WriteByte( Address, MCP23008_IORDIR, direction );
}
//Configura os resistores de Pull-up
void MCP23008_Set_PullUp( char Address, char _data )
{
MCP23008_WriteByte( Address, MCP23008_GPPU, _data );
}
EXEMPLO
MikroC PRO PIC
//Habilitar as seguintes bibliotecas:
// - I2C
//PIC16F876A
//CLOCK: 4MHz
//Copie e cole o código da biblioteca aqui!!!
void main()
{
char i = 0;
//configura o pino RB0/INT como entrada
TRISB0_Bit = 1;
//interrupção por borda de subida
INTEDG_Bit = 1;
I2C1_Init( 100000 );
MCP23008_Init( 7 );
//GP0-GP6 são saidas, GP7 Entrada
MCP23008_Set_DirectionPort( 7, 0x80 );
//Habilita int. GP7
MCP23008_WriteByte( 7, MCP23008_GPINTEN, 0x80 );
//Configura interrupção do pino GP7 por borda de descida
MCP23008_WriteByte( 7, MCP23008_DEFVAL, 0x80 );
//Configura a int. do pino GP7 para comparar com o registro DEFVAL
MCP23008_WriteByte( 7, MCP23008_INTCON, 0x80 );
//Habilita resistor de pull-up do pino GP7
MCP23008_Set_PullUp( 7, 0x80 );
while(1)
{
//Espera a interrupção ocorrer
while( !INTF_Bit );
INTF_Bit = 0; //limpa a flag de interrupção
//Poderia ler o registro INTF, verificar se ocorreu a interrupção
//e verificar qual pino disparou o evento. Exemplo abaixo.
//Faz a leitura de GPIO para limpar a interrupção
MCP23008_ReadByte( 7, MCP23008_GPIO );
//Escreve para o dispositivo
MCP23008_Write_Port( 7, ++i & 0x7F );
}
}
EXEMPLO
MikroC PRO PIC
//Habilitar as seguintes bibliotecas:
// - I2C
//PIC16F876A
//CLOCK: 4MHz
//Copie e cole o código da biblioteca aqui!!!
void main()
{
char i = 0;
Uart1_Init( 9600 );
I2C1_Init( 100000 );
MCP23008_Init( 7 );
//GP0-GP3 são saidas, GP4-GP7 Entrada
MCP23008_Set_DirectionPort( 7, 0xF0 );
//Habilita int. GP7-GP4
MCP23008_WriteByte( 7, MCP23008_GPINTEN, 0xF0 );
//Configura interrupção dos pinos GP4-GP7 por borda de descida
MCP23008_WriteByte( 7, MCP23008_DEFVAL, 0xF0 );
//Configura a int. dos pinos GP4-GP7 para comparar com o registro DEFVAL
MCP23008_WriteByte( 7, MCP23008_INTCON, 0xF0 );
//Habilita resistor de pull-up dos pinos GP4-GP7
MCP23008_Set_PullUp( 7, 0xF0 );
while(1)
{
char port;
Delay_ms( 200 );
port = MCP23008_ReadByte( 7, MCP23008_INTF );
if( port == 0 ) //Nao houve nehuma interrupção
continue; //retorna ao inicio do loop
if( port.B7 )
{
Uart1_Write_Text( "GP7" );
}
if( port.B6 )
{
Uart1_Write_Text( "GP6" );
}
if( port.B5 )
{
Uart1_Write_Text( "GP5" );
}
if( port.B4 )
{
Uart1_Write_Text( "GP4" );
}
}
}





Nenhum comentário