sexta-feira, 27 de agosto de 2021

Acionando os pinos de I/O do C8051F382 em C

Olá pessoal!        
        Marcando meu retorno aos exemplos de chips e tecnologias utilizadas na área de pesquisa e desenvolvimento vou colocar alguns exemplos de como utilizar os microcontroladores da Silicon Labs, em especifico os da serie C8051F38XX que apresentam um alto desempenho porém tem como empecilho a falta de uma memória rom interna como os PIC´s e AVR´s, outro ponto negativo é o gravador desses microcontroladores que são mais caros e mais difíceis de encontrar.
        O software de programação utilizado será o Simplicity Studio e o toochain  "Keil C51 9.51", quanto a este software gostei muito pois apresenta poucos bugs e as funções em C são bem tranquilas de se utilizar.
como programa inicial vou postar um exemplo de como acionar os pinos deste microcontrolador, uma observação é o PORT4 que apresenta um comportamento diferenciado em relação ao outros pinos.
        Um complicador em relação a outros modelos de microcontroladores é o "Digital
Crossbar" que deve ser setado corretamente pois conforme se configura os pinos com funções especiais ele acaba por mudar também a função dos outros pinos com funções especiais, ou seja se vc configura um pino como interrupção ele poderá te impedir de usar um outro pino que tem uma outra função, te obrigando a escolher outro pino, porem uma vantagem é poder "chavear funções de hardware para mais pinos. A figura a seguir mostra como é essa arquitetura(retirado do datasheet do fabricante).Esse recurso pode ser desabilitado por meio dos registradores PXSKIP (onde em X é colocado o PORT em questão).
        
       Segue abaixo um exemplo de código que usa o PORT0 e o PORT4, para ler 2 botões e acionar leds através destes pinos.

O Código fonte :

// Target:         C8051F382
// Tool chain:     Simplicity Studio / Keil C51 9.51
// Autor: Aguivone Moretti Fogia
// Data: 27/08/2021
//
//exemplo de como usar botoes e leds
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <SI_C8051F380_Register_Enums.h>

//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------

#define SYSCLK       12000000          // Internal oscillator frequency in Hz
//entradas porta 0
SI_SBIT(BOT1, SFR_P0, 6);                  // BOT1 ='0' botão pressionado
SI_SBIT(BOT2, SFR_P0, 7);                  // BOT2 ='0' botao pressionado

unsigned char porta4 = 0XFF;

//Saidas porta 0
SI_SBIT(LED1, SFR_P0, 0);                      // LED='0' Ligado   //pois ligado ao VCC
SI_SBIT(LED2, SFR_P0, 1);                      // LED='1' Desligado
// A porta 4 tem um funcionamento diferente em relação as outras
//ledes ligado ao port 4
#define LED3  0x7F
#define LED4  0xBF


//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
SI_INTERRUPT_PROTO(PCA0_ISR, PCA0_IRQn);

void OSCILLATOR_Init (void);
void PORT_Init (void);
void Liga_Port4(const char pino);
void Desliga_Port4(const char pino);
bool flag_teste;
//-----------------------------------------------------------------------------
// SiLabs_Startup() Routine
// ----------------------------------------------------------------------------
// This function is called immediately after reset, before the initialization
// code is run in SILABS_STARTUP.A51 (which runs before main() ). This is a
// useful place to disable the watchdog timer, which is enable by default
// and may trigger before main() in some instances.
//-----------------------------------------------------------------------------
void SiLabs_Startup (void)
{
   PCA0MD = 0x00;                      // Disable watchdog timer
}

//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------

void main (void)
{
   uint16_t LOOP;
   uint16_t LOOP_max =65000;
   PORT_Init ();                       // Initialize crossbar and GPIO
   OSCILLATOR_Init ();                 // Initialize oscillator
   LOOP =0;
   IE_EA = 0;
   flag_teste = 0;
   while (1)
   {
     LOOP++;
         if(LOOP>LOOP_max)
         {
              Liga_Port4(LED3);
              LED1=0; //liga led
              LOOP=0;
         }
         if(LOOP ==(LOOP_max/2))
             {
              Desliga_Port4(LED3);
              LED1=1; //desliga led
             }
         if(BOT1)
           {
             Liga_Port4(LED4);
           }
           else
             {
               Desliga_Port4(LED4);
             }
        if(BOT2)
           {
              LED2=0; //liga led
           }
           else
             {
               LED2=1;//desliga led
             }
   }
}

//-----------------------------------------------------------------------------
// tratamento especial para port 4
//-----------------------------------------------------------------------------
void Desliga_Port4(const char pino)
{//desliga em nivel alto
   porta4 = porta4 | (~pino);
   P4 = porta4;
}
void Liga_Port4(const char pino)
{
  porta4 = porta4 & pino;
  P4 = porta4;
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function initializes the system clock to use the internal oscillator
// at 12 MHz.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
   OSCICN = 0x83;                      // Set internal oscillator to run  (desabilitou osc interno)
                                       // at its maximum frequency(pois setou os 2 ultimos bit)
   CLKSEL = 0x00;                      // Select the internal osc. as (SYSCLK/4)
                                       // the SYSCLK source
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function configures the crossbar and GPIO ports.
//
// P0.0   digital   open-drain     PCA0 CEX0
// P0.1   digital   push-pull
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
      OSCICN  = 0X81;                     // IHFOsc Enable, OpcDiv:3MHz
      CLKMUL  = 0XC0;                     // talvez nem precise neste microcontrolador -> habilita  e inicializa pll
      CLKSEL  = 0X03;                     // SYSCLK derived from the Internal High-Frequency Oscillator.
      PFE0CN  = 0X20;                     //(para High Speed) Prefetch Engine Control,otimiza tempo de execução lendo 2 bytes de execução por vez
      /* FLSCL.FOSE(7) = 0 for < 10MHz and 1 for SYSCLK > 10MHz
      FLSCL.FLRT(4) = 0 for < 25MHz and 1 for SYSCLK > 25MHz */
      FLSCL   = 0x90;
      CKCON   = 0x30;
      SPI0CN  = 0x02;                     //Select Mode 3-Wire pra liberar pino NSS

      P0MDIN  = 0xFF;                     //  are digital
      P1MDIN  = 0xFF;                     //  are digital
      P2MDIN  = 0xFF;                     //  are digital
      P3MDIN  = 0xFF;                     //  are digital
      P4MDIN  = 0xFF;                     //  are digital

      P0MDOUT = 0x10;                     // enable Switches as open-drain
      P1MDOUT = 0x00;                     // enable Switches as open-drain
      P2MDOUT = 0x00;                     // enable Switches as open-drain
      P3MDOUT = 0x00;                     // enable Switches as open-drain
      P4MDOUT = 0x04;                     // enable Switches as open-drain

      P0SKIP = 0xCF;                      // TXeRX precisa do Skip pra funcionar
      P1SKIP = 0xFF;
      P2SKIP = 0xFF;
      P3SKIP = 0xCF;

      XBR0   = 0x01;                     // CP1AE,CP1E,CP0AE,CP0E,SYSCKE,SMB0E,SPI0E,(UART0E)
      XBR2   = 0x00;                     // RESRV,RSRV,RESRV,RESRV,RESRV,RESRV,SMB1E, UART1E
      XBR1   = 0xC2;                     // WEAKPUD,(XBARE),T1E,T0E,ECIE,(PCA0ME):000:Nenhum,001:CEX0,010:CEX0eCEX1,...
      // VDM0CN -> monitor de tensão de reset
      VDM0CN = 0x80;                    //Colocado porque senão da problema na gravacao da flash(já estava isso)

      P4 = 0xD8        ;  //portas de p4 desligadas
     // P4 = 0        ;  //portas de p4 ligadas
}

Formatado por : http://hilite.me/  27/08/2021
Formatado por : http://hilite.me/ 27/08/2021