terça-feira, 16 de abril de 2013

Expandindo as portas do PIC:

          Vou demonstrar aqui como aumentar o números de pinos do PIC simplesmente usando um CI fabricado pela própria microchip o MCP23S17, com ele você  pode ler e escrever no pinos do chip via comunicação SPI .O programa é bem simples o microcontrolador fica lendo o portB do chip o tempo todo dai se o botão for pressionado ele escreve no portA do chip o valor "0X0F" e quando o botão é liberado ele limpa o portA do chip.
           Esse chip é vendido no site da microchip por 1,50 dólar.Um detalhe que deve ser ressaltado as familias 18F  é que para ler um pino se usar  PORTXbits.RXY e para escrever se usa LATXbits.LXY onde o 'X' é o port e o 'Y' o numero do pino(0 a 7).

O código - fonte:


/*
 *                           usando a SPI(mestre) para comunicar com modulo expansor MCP23S17
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 18F13K22
 * Autor: aguivone
 * Versão: 1
 * Data :  16 de abril de 2013
 */

#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 12000000    // cristal de 20 Mhz
#include <xc.h>

/////////////////////////////////////////////////////configuraçôes do pic //////////////////////////////////////////////////

// CONFIG1H
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config PLLEN = OFF      // 4 X PLL Enable bit (PLL is under software control)
#pragma config PCLKEN = ON      // Primary Clock Enable bit (Primary clock enabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 19        // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = OFF      // MCLR Pin Enable bit (RA3 input pin enabled; MCLR disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config BBSIZ = OFF      // Boot Block Size Select bit (512W boot block size)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)



// defines para o MCP23S17 SPI Slave
#define SPI_SLAVE_ID    0x40
#define SPI_SLAVE_ADDR  0x00      // A2=0,A1=0,A0=0 pois os pinos estão aterrados
#define SPI_SLAVE_WRITE 0x00
#define SPI_SLAVE_READ  0x01

// MCP23S17 registradores padrão ( BANK=0)
#define IODIRA 0x00
#define IODIRB 0x01
#define IOCONA 0x0A
#define GPPUA  0x0C
#define GPPUB  0x0D
#define GPIOA  0x12
#define GPIOB  0x13
//variaveis usadas///////////
  unsigned char conta = 0 ,Botao = 0,porta =0;
/////////////////////////////

// Delay in 1 ms (approximately) for 12 MHz Internal Clock
void delay_ms(long mili)
{
   while(mili > 0)
   {
      _delay(2927);//aprox. 1ms com clock de 12mhz
      mili--;
   }
   // no caso do 18F o valor fica bem acima então é melhor montar essa funcão para que trabalhe bem
}


void ESCREVE_SPI(unsigned char endereco,unsigned char dados)
{
   LATCbits.LC6 = 0;  // ativa CS(chip select do MCP23S17)
  // inicia MCP23S17 OpCode
  SSPBUF = SPI_SLAVE_ID | ((SPI_SLAVE_ADDR << 1) & 0x0E)| SPI_SLAVE_WRITE;  
  while(!SSPSTATbits.BF);//espera completar envio de dados
  SSPBUF = endereco;//envia o endereço do regitrador que se quer acessar
  while(!SSPSTATbits.BF);//espera completar envio de dados
  SSPBUF = dados;//envia os dados que será colocado no registrador
  while(!SSPSTATbits.BF);//espera completar envio de dados
   LATCbits.LC6 = 1;//desabilita chip
}

unsigned char LER_SPI(unsigned char endereco)
{
     LATCbits.LC6 = 0;  // ativa CS(chip select do MCP23S17)
  // inicia MCP23S17 OpCode
  SSPBUF = SPI_SLAVE_ID | ((SPI_SLAVE_ADDR << 1) & 0x0E)| SPI_SLAVE_READ;
  while(!SSPSTATbits.BF);//espera completar envio de dados
  SSPBUF = endereco;//envia o endereço do regitrador que se quer acessar
  while(!SSPSTATbits.BF);//espera completar envio de dados
  SSPBUF = 0X00;//um valor qualquer para pegar os dados
  //desse registrador(assim gera o clock necessario para isto)
  while(!SSPSTATbits.BF);//espera completar envio de dados
   LATCbits.LC6 = 1;//desabilita chip
  return(SSPBUF);
}
void SPI_MASTER()//modo mestre
{
  SSPCON1 = 0X20;//habilita modo SPI // FOSC/4 //
  SSPSTAT = 0XC0;//pega amostras no fim do bit e a trasmissão será na borda de descida
  TRISB = 0X10;//configura portB como saida exceto o pino b4(SDI)
  TRISC = 0X00;//configura portc como saida
  ANSEL = 0x00;//desabilita porta analogicas(para não atrapalhar recepção no pino)
  ANSELH = 0x00;//em alguns casos não funciona nem a interrupção de recepção.
   LATCbits.LC6 = 1;
}
void INICIALIZA_MCP23S17()
{
  ESCREVE_SPI(IOCONA,0x28);   // I/O Registrador de controle: BANK=0, SEQOP=1, HAEN=1 (habilita endereçamento)
  ESCREVE_SPI(IODIRA,0x00);   // GPIOA será saida
  ESCREVE_SPI(IODIRB,0xFF);   // GPIOB será entrada
  ESCREVE_SPI(GPPUB,0xFF);    // habilita resistores de pull up no GPIOB
  ESCREVE_SPI(GPIOA,0x00);    // limpa saidas da GPIOA
}

void main(void)
{
  SPI_MASTER();//inicializa SPI no modo master
  INICIALIZA_MCP23S17();
  for(;;) {
             porta=LER_SPI(GPIOB);    // lê o valor do GPIOB
         if (porta == 0xFE)
               {      // se botão pressionado
                  delay_ms(100);//debounce(filtro de ruidos)
                  porta=LER_SPI(GPIOB);  // lê novamente
                  if (porta == 0xFE)
                  {//pressionado
                    ESCREVE_SPI(GPIOA,0X0F);//muda estado dos bits mais baixos
                  }                  
            }
             else
                  { //não pressionado
                    ESCREVE_SPI(GPIOA,0x00); // limpa o portA
                  }
        delay_ms(1000);//tempo para visualizar mudanças
        }
}

A simulação:

Faça uma visita na página do face, basta procurar por microcontroladores-C,e dê um "curtir" assim vc fica por dentro das novidades do blog!  

Um comentário :

olá,digite aqui seu comentário!