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