quarta-feira, 12 de abril de 2023

Usando o timer do microcontrolador EFM8BB1(linha Busy Bee).

     Olá! hoje exploraremos um pouco do microcontrolador Busy Bee EFM8(EFM8BB1), dentre suas principais características está o fato de ter um ADC de 12BITS,funciona a 25mhz interno, pinos compativel com 5V(pois são geralmente pra 3,3V), sensor de temperatura interno, 4 timers de 16 bits, comunicação UART,SPI e SMBUS/I2C.

    Este microcontrolador é totalmente compatível com alguns microcontroladores da linha CIP-51 8051(C8051), sendo praticamente um melhoramento dos projetos anteriores deste componente. Para a utilização deste microcontrolador divergem alguns registradores além do precisar de 2 comando para desligar o "watch dog", sob risco do micro ficar resetando.

    Neste exemplo vou demonstrar como acionar um pino usando como base de tempo o timer2 interno deste microcontrolador, apesar de ser um exemplo simples creio que irá ajudar quem está começando a usar este  microcontrolador com a interface do Simplicity Studio. Veja na figura a seguir. 

O código fonte :

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "si_toolchain.h"             // compiler declarations
#include <SI_EFM8BB1_Register_Enums.h>                // SFR declarations
#include <stdio.h>
#include <string.h>

#define SYSCLK       24500000          // Internal oscillator frequency in Hz

SI_SBIT(BOT1, SFR_P0, 1);                  // não usado aqui
SI_SBIT(BOT2, SFR_P0, 2);                  // não usado aqui

//leds vermelho e sinal de saida

SI_SBIT(LED_1,SFR_P1,2);


int  pisca_led = 0;
long  tempo_1s = 0;

void SiLabs_Startup (void)
{
    WDTCN = 0XDE;//             WDTE = 0 (desliga watchdog )
    WDTCN = 0xAD;//             senão colocar essa seuqencia não desliga deser colocado obrigatoriamente os 2
    PCA0MD = 0x08; //           habilita sytem clok para timer
}


void __delay_ms(uint32_t val)
{//rotina que usa ciclos de maquina - pode variar devido a interrupções
  val = 360*val;
  while(val>1)
           {
            val--;
           }
}

void __delay_us(uint8_t val)
{//rotina que usa ciclos de maquina - pode variar devido a interrupções
  while(val>1)
         {
          val--;
         }
}
void Oscillator_Init (void)
{
   HFO0CAL = 0X00; // para alta frequencia
   CLKSEL = 0x00;                     //SYSCLK: OpcDiv = 24M5Hz  // sem divisão de clock e para alta frequencia// clok interno
}
void PORT_Init(void)
{
              WDTCN = 0XDE;//             WDTE = 0 (desliga watchdog )
              WDTCN = 0xAD;//             senão colocar essa seuqencia não desliga deser colocado obrigatoriamente os 2
              CLKSEL = 0X00; // 24mhz clock interno
             // WDTCN  =  0xDE;//(desliga watchdog )
              XBR0    = 0x00;                     // habilita UART no pino P0.4(TX) and P0.5(RX)  ; logo não serão usado como como IO´s gerais
              XBR2    = 0xC0;                     // habilita crossbar e pull-ups interno desligados

              VDM0CN = 0x00;                     // Colocado porque senão da problema na gravacao da flash(já estava isso)
              RSTSRC = 0x00;                     // desativa reset de falha de oscilação.

              P0MDOUT = 0XC0;                    //somente pino 6 e 7 são saidas
              P1MDOUT = 0xFF;                     //todos saidas
              P2MDOUT = 0xFF;                     //todos saidas so tem 2 saidas

             //configura portas
              P0MDIN  = 0xF9;                     //  apenas  P0.1 e P0.2 são analogica
              P1MDIN  = 0xFF;                     //  are digital

              P0SKIP = 0x3F;      //não usado
              P1SKIP = 0xFE;
              IE_EA = 1; // liga interrupções
}

//-----------------------------------------------------------------------------
// Timer2_Init
//-----------------------------------------------------------------------------
//
// Configure Timer2 to 16-bit auto-reload and generate an interrupt at
// interval specified by <counts> using SYSCLK/48 as its time base.
//
//-----------------------------------------------------------------------------
void Timer2_Init (void)
{  //100us
   TMR2CN0 = 0x00;  /// time 2 no modo 16 bits
   TCON = 0;//não habilita timer 0  e 1
   CKCON0 = 0XFD; //todos os timer serão ligados ao sysclock e na menor divisão para timer 0 e 1(por 4)
   TMR2RLH  = 0xF6; //quando se usa o modo autocarregar puxa daqui o valor
   TMR2RLL  = 0x70;//quando se usa o modo autocarregar puxa daqui o valor
   TMR2    = 0xF670;                      // um valor para primeiro estouro
   IE_ET2     = 1;                        // enable Timer2 interrupts
   TMR2CN0_TR2 = 1;                        // start Timer2
}


//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Timer2_ISR
//-----------------------------------------------------------------------------
// This routine changes the state of the LED whenever Timer2 overflows.
//
//-----------------------------------------------------------------------------
SI_INTERRUPT(Timer2_ISR, TIMER2_IRQn)
{       // tempo de 100us
        TMR2CN0_TF2H = 0; // limpa tanto a interrupção nos bytes baixo como altos
        TMR2CN0_TF2L = 0;// clear Timer2 interrupt flag
        tempo_1s++;
}

//-----------------------------------------------------------------------------
// main() Routine
// ----------------------------------------------------------------------------
// Note: the software watchdog timer is not disabled by default in this
// example, so a long-running program will reset periodically unless
// the timer is disabled or your program periodically writes to it.
//
// Review the "Watchdog Timer" section under the part family's datasheet
// for details. To find the datasheet, select your part in the
// Simplicity Launcher and click on "Data Sheet".
//-----------------------------------------------------------------------------
int main (void)
{
  PORT_Init();
  Timer2_Init ();
  for(;;)
    {

         if(tempo_1s > 10000)
           {//pisca a cada 1s
             tempo_1s = 0;
            if(pisca_led == 0)
                {
                   pisca_led = 1;
                    LED_1 = 1;
                }
              else
                {
                   pisca_led = 0;
                    LED_1 = 0;
                }
           }
    }
}
Formatado no site http://hilite.me/  acessado em 12/04/2023.