quarta-feira, 8 de novembro de 2023

Frequencímetro com 2 canais usando o C8051F380 e mostrando via serial RS232 da Silicon Labs,.

     Olá, neste artigo vou aproveitar o código que já havia sido planejado no exemplo do post anterior, quando se configura o hardware para captura já pega o sinal que é inserido nos pinos T0(P3.4 - pino26) e T1(P3.5 - pino25).

    Pode-se mudar as configurações para estar na faixa desejada para sua necessidade, neste exemplo um range previsto é  algo em torno de 750hz a 4,75KHZ.

    Deixei também alguns leds para testar se estava lendo o sinal no pino, e se havia processamento no microcontrolador.

O código fonte:

// Target:         C8051F380 e C8051F382
// Tool chain:     Simplicity Studio / Keil C51 9.51
//autor: Aguivone Moretti
//

//Data: 06_11_2023 - serial ok e modulos CCP ok
//Data: 07_11_2023 - calculado para um range de 3khz a 19Mhz(embora dê mais porem não fica muito bom)
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "si_toolchain.h"
#include <SI_C8051F380_Register_Enums.h>
#include <stdio.h>
#include <string.h>

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

#define SYSCLK       48000000          // Internal oscillator frequency in Hz
#define BAUDRATE      19200           // Baud rate of UART in bps
#define INT_DEC       256              // Integrate and decimate ratio

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
SI_INTERRUPT_PROTO(PCA0_ISR, PCA0_IRQn);
void Liga_Port4(const char pino);
void Desliga_Port4(const char pino);
void Config_Init(void);
void UART0_Init (void);
//-----------------------------------------------------------------------------
//definicão dos pinos
//-----------------------------------------------------------------------------

SI_SBIT(SW1, SFR_P0, 6);                  // SW1 ='0' botão pressionado
SI_SBIT(SW2, SFR_P0, 7);                  // SW2 ='0' botão pressionado


//leds vermelho e sinal de saida
SI_SBIT(LED_1, SFR_P0, 0);                      // LED='1' Ligado     ->  lacoA
SI_SBIT(LED_2, SFR_P0, 1);                      // LED='1' Desligado  ->  lacoB
//led verde
#define LED_freq1    0x7F  
#define LED_freq2    0xBF  
//led azul
#define LED_Status   0xF7  // P4.3
//led vermelho
#define LED_ping     0xEF  //P4.4

//-----------------------------------------------------------------------------
//definicão das variaveis globais
//-----------------------------------------------------------------------------
bool flag_teste;
unsigned char porta4 = 0XFF;
uint16_t pisca =0;
char liga_pino_status  = 0;

// variaveis da serial RS232

#define  UART_BUFFERSIZE 10
uint8_t  UART_Buffer_rx[UART_BUFFERSIZE];
uint8_t  UART_Buffer_tx[UART_BUFFERSIZE];//para transmissão
uint8_t  pos_buffer=0;
uint8_t  tam_buffer_tx=0;
uint8_t  pos_buffer_tx=0;
bool     tem_recp = 0;
bool     rec_232 = 0;
bool     trans_232 = 0;

//variaveis para timers e captura

bool     sinal0 = 0;
bool     sinal1 = 0;

float periodo_1  = 0;
uint16_t periodo_anterior_1=0;
uint16_t periodo_atual_1=0;
uint8_t  num_itens1 = 0;

float periodo_2 = 0;
uint16_t periodo_anterior_2=0;
uint16_t periodo_atual_2=0;
uint8_t  num_itens2 = 0;

//-----------------------------------------------------------------------------
// SiLabs_Startup() Routine
// é chamada após reset
//-----------------------------------------------------------------------------
void SiLabs_Startup (void)
{
   PCA0MD = 0x00;                      // Disable watchdog timer
}


//------------------------ -----------------------------------------------------
// configura todo o hardware necessario
//-----------------------------------------------------------------------------

void Config_Init (void)
{

      IE_EA = 0; //desabilita todas as interrupções.

   //configura oscilador
      OSCICN  = 0X83;                     // IHFOsc Enable, sem divisão ira rodar a 12MHz
      CLKMUL  = 0XC0;                     // talvez nem precise neste microcontrolador -> habilita  e inicializa pll
      CLKSEL  = 0X03;                     // SYSCLK derived from the Internal High-Frequency Oscillator.sem divisão  48MHZ se estiver habilitado o clksel

      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   = 0x00;  //  todos os timer ligado ao clock do sistema por meio do prescaler / clock dividido por 12(repensar depois)
      SPI0CN  = 0x02;                     //Select Mode 3-Wire pra liberar pino NSS

    //configura portas //////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

      P0MDOUT = 0x20;                     // coloca pino 4 como saida
      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;

      P4 = 0XFF;  //portas de p4 ligadas (desliga leds)

      XBR0   = 0x01;                     // CP1AE,CP1E,CP0AE,CP0E,SYSCKE,SMB0E,SPI0E,(UART0E)  ///habilita UART0
      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)
      RSTSRC = 0x02;                     // ativa reset de falha de oscilação.

    //configura modulos de captura /////////////////////////////////////////////////////////////////////////

      TMOD = 0x11;                       // 16-bit timer0 e timer1 interrupção no pino


      PCA0CN = 0x00;                      // Stop counter; clear all flags
      PCA0CPM0 = 0x21;                   //  ;5:CapPos, 4:CapNeg// habilita modulo ccp0 na borda de subida
      PCA0CPL0 = 0x00;
      PCA0CPH0 = 0x00;

      PCA0CPM1 = 0x21;                  //  ;5:CapPos, 4:CapNeg// habilita modulo ccp1 na borda de subida
      PCA0CPL1 = 0x00;
      PCA0CPH1 = 0x00;

      PCA0CPM2 = 0x00;     // desabilitado
      PCA0CPM3 = 0x00;
      PCA0CPM4 = 0x00;

      PCA0MD = 0x09;     //desliga watdog - clock sem divisão - habilita interrupção do counter/timer overflow
   //   PCA0MD = 0x03;     //desliga watdog - clock dividido por 4 - habilita interrupção do counter/timer overflow //se mudar aqui deverá mudar os calculos
  //    PCA0MD = 0x01;     //desliga watdog - clock dividido por 12 - habilita interrupção do counter/timer overflow
      EIP1 =   0x10;     //seta para alta prioridade , EIP1.PPCA0
      EIE1 =   0x10;     //Habilita Interrupcao da Captura
      PCA0CN_CR = 1;      // Habilita contadores



}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//-----------------------------------------------------------------------------

void UART0_Init (void)
{
   SCON0 = 0x10;                       // SCON0: 8-bit variable bit rate
                                       //        level of STOP bit is ignored
                                       //        RX enabled
                                       //        ninth bits are zeros
                                       //        clear SCON0_RI and SCON0_TI bits
   if (SYSCLK/BAUDRATE/2/256 < 1) {
      TH1 = -(SYSCLK/BAUDRATE/2);
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   } else if (SYSCLK/BAUDRATE/2/256 < 4) {
      TH1 = -(SYSCLK/BAUDRATE/2/4);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01
      CKCON |=  0x01;
   } else if (SYSCLK/BAUDRATE/2/256 < 12) {
      TH1 = -(SYSCLK/BAUDRATE/2/12);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 00
   } else {
      TH1 = -(SYSCLK/BAUDRATE/2/48);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 10
      CKCON |=  0x02;
   }
   IE_ES0 = 1;                         //habilita interrupção de serial
   TL1 = TH1;                          // Init Timer1
   TMOD &= ~0xF0;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=  0x20;
   TCON_TR1 = 1;                            // START Timer1

}

//-----------------------------------------------------------------------------
// 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;
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// UART0_Interrupt
//-----------------------------------------------------------------------------
//
// This routine is invoked whenever a character is entered or displayed on the
// Hyperterminal.
//
//-----------------------------------------------------------------------------

SI_INTERRUPT(UART0_Interrupt, UART0_IRQn)
{
   if (SCON0_RI == 1)
   {
       char RX_232 = SBUF0;
       SCON0_RI = 0;
       if(pos_buffer >= UART_BUFFERSIZE)  // tem um bug no compilador ou chip que faz reseta
                {//erro descarta, pois é maior que o tamanho maximo do buffer
                  rec_232=0; //não recebendo
                  pos_buffer=0;//limpa buffer
                  tem_recp = 0;//sinaliza fim de pacote
                }
       if(rec_232 && RX_232 == '*')
                {//esta recebendo e chegou delimitador de fim
                  rec_232=0; //não recebendo
                  tem_recp = 1;//sinaliza fim de pacote
                  Liga_Port4(LED_ping);
                }
       if(rec_232)
         {//esta recebendo
           UART_Buffer_rx[pos_buffer] = RX_232;
           pos_buffer++;
         }
       if(RX_232 == '#')
         {
           pos_buffer=0;//sinaliza recepção
           rec_232=1; //recebendo
         }
   }
   if (SCON0_TI)  //testa se tem transmissão
     {
        SCON0_TI = 0;                          // limpa flag de tranmissão
        if(trans_232 == 1)
          {

           if (pos_buffer_tx <  tam_buffer_tx)
            {// transmitindo
               SBUF0  = UART_Buffer_tx[pos_buffer_tx];//escreve na porta serial
               pos_buffer_tx++;

            }
            else
              {
                trans_232 = 0; //fim de transmissao
                pos_buffer_tx =0;
              }
        }
     }

}
void  imprime_hexa(char dados[] ,uint8_t tam)
{
    while(trans_232);  //faz nada só espera enviar todo o pacote  talvez por um time out
       //se ja houver dados para ser enviado espera terminar para comecar a enviar. // veja que pode travar um pouco aqui o processamento
    tam_buffer_tx = 0;
    while(tam > tam_buffer_tx)
      {
         UART_Buffer_tx[tam_buffer_tx] = dados[tam_buffer_tx];//transfere dados
         tam_buffer_tx++;
      }
    trans_232 = 1;//sinaliza que deve transmitir
    SCON0_TI = 1; //para dar inicio a transmissão
}


//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This is the ISR for the PCA.  It handles the case when a capture occurs on
// channel 0, and updates the variables to reflect the new capture information.
//
//-----------------------------------------------------------------------------

SI_INTERRUPT(PCA0_ISR, PCA0_IRQn)
{
        periodo_atual_1  = (PCA0CPH0<<8) + PCA0CPL0;//pega valores  depois vê se é pra tratar
        periodo_atual_2  = (PCA0CPH1<<8) + PCA0CPL1;
   /*  if(PCA0CN_CF)      // houve estouro do contador (1 só pra todos)
       {
         //a fazer
         PCA0CN_CF = 0;
       }*/
     if(PCA0CN_CCF0)      // interrupção no modulo 0
           {
             PCA0CN_CCF0 = 0;// Clear module 0 interrupt flag.

            if(num_itens1<10)
              {
                  if(periodo_atual_1> periodo_anterior_1)
                    {
                      periodo_1 = (periodo_atual_1 - periodo_anterior_1)+periodo_1;
                    }
                  else
                    {
                      periodo_1  = (( 65535 - periodo_anterior_1) + periodo_atual_1)+periodo_1;
                    }
                num_itens1++;
              }

           }
     if(PCA0CN_CCF1)      // interrupção no modulo 2
            {
             PCA0CN_CCF1 = 0;// Clear module 0 interrupt flag.
              if(num_itens2<10)
                {
                  if(periodo_atual_2> periodo_anterior_2)
                        {
                          periodo_2 = (periodo_atual_2 - periodo_anterior_2)+periodo_2;
                        }
                      else
                        {
                          periodo_2  = (( 65535 - periodo_anterior_2) + periodo_atual_2)+periodo_2;
                        }
                  num_itens2++;
                }

            }
     PCA0CN = 0X40;//limpa todos os estouros e deixa o modo captura e timer ligado
     periodo_anterior_1 = periodo_atual_1;
     periodo_anterior_2 = periodo_atual_2;

}
void long_to_char(long valor)
{
    char Buffer_serial_out[5]; //delimitador pra facilitar jogar no excel
    Buffer_serial_out[0]='0';
    Buffer_serial_out[1]='0';
    Buffer_serial_out[2]='0';
    Buffer_serial_out[3]='0';
    Buffer_serial_out[4]='0';
    if(valor < 65535)
    {
        while(valor>=10000)
             {
                 valor = valor - 10000;
                 Buffer_serial_out[0]++;
             }
        while(valor>=1000)
           {
               valor = valor - 1000;
               Buffer_serial_out[1]++;
           }
        while(valor>=100)
           {
               valor = valor - 100;
               Buffer_serial_out[2]++;
           }
        while(valor>=10)
           {
               valor = valor - 10;
               Buffer_serial_out[3]++;
           }
        while(valor>=1)
           {
               valor = valor - 1;
               Buffer_serial_out[4]++;
           }
        imprime_hexa(Buffer_serial_out ,5);
    }

}

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

void main (void)
{  //variaveis locais
   Config_Init();                       // inicializa CPU
   UART0_Init();                       // inicializa UART0

   LED_1 = 1;//desliga leds
   LED_2 = 1;
   Desliga_Port4(LED_freq1);
   Desliga_Port4(LED_freq2);
   Desliga_Port4(LED_Status);
   liga_pino_status  = 0;
   IE_EA = 1;//habilita interrupções globais
   flag_teste = 0;
   while (1)
   {
       if(tem_recp)//recebeu dados
                        {
                           //trata os dados recebidos que estão em : UART_Buffer_RX

                             imprime_hexa("\n\r",2);//salta linha e retorna para o inicio de linha
                             imprime_hexa("dados =>" ,8);
                             imprime_hexa(UART_Buffer_rx ,pos_buffer);
                             pos_buffer = 0;
                             tem_recp = 0;//sinaliza que já leu
                             Desliga_Port4(LED_ping);
                        }

       if(num_itens1==10)
              {
               imprime_hexa("\n\r",2);//salta linha e retorna para o inicio de linha
               imprime_hexa("freq1=> " ,8);
               if(periodo_1 > 30000)  //pra não ultrapassar o limite de impressão
                 {
                   imprime_hexa("(hz)",4);
                   periodo_1 = 250000000/((periodo_1/10)*5.199);//já tira a media
                 }
               else
                 {
                   imprime_hexa("(khz)",5);
                   periodo_1 = 250000/((periodo_1/10)*5.199);//já tira a media
                 }
               long_to_char(periodo_1);
               if(sinal0 == 0 )
                  {
                    Liga_Port4(LED_freq1);
                    sinal0 = 1;
                  }
                else
                  {
                    Desliga_Port4(LED_freq1);
                    sinal0 = 0;
                  }
               num_itens1 = 0;
               periodo_1 = 0;
              }
       if(num_itens2==10)
               {
                imprime_hexa("\n\r",2);//salta linha e retorna para o inicio de linha
                imprime_hexa("freq2=> " ,8);
                if(periodo_2 > 30000)  //pra não ultrapassar o limite de impressão
                   {
                     imprime_hexa("(hz)",4);
                     periodo_2 = 250000000/((periodo_2/10)*5.199);//já tira a media
                   }
                 else
                   {
                     imprime_hexa("(khz)",5);
                     periodo_2 = 250000/((periodo_2/10)*5.199);//já tira a media
                   }
                long_to_char(periodo_2);// valor em htz
                if(sinal1 == 0 )
                     {
                      Liga_Port4(LED_freq2);
                      sinal1 = 1;
                     }
                     else
                     {
                       Desliga_Port4(LED_freq2);
                       sinal1 = 0;
                     }
                num_itens2 = 0;
                periodo_2 = 0;
               }
                     pisca++;
                     if(pisca > 100)
                       { // pisca led
                         if(liga_pino_status  == 0)
                           {
                             liga_pino_status  = 1;
                             Liga_Port4(LED_Status);
                             SCON0_TI = 0;
                           }
                         else
                           {
                             liga_pino_status  = 0;
                             Desliga_Port4(LED_Status);
                           }
                        pisca =0;
                       }
   }
}

formatado em : http://hilite.me/  acessado em 08/11/2023.

sexta-feira, 3 de novembro de 2023

Configurando o 8051CF380 para 48MHZ ( através do pll, com oscilador interno) e configurando a porta serial

     Neste exemplo é demonstrado alguns aspectos na configuração deste microcontrolador :

1 - Como configurar o PLL para gerar 48MHZ interno.

2 - Configurando a serial para receber e enviar dados, com funções prontas e mais otimizadas.

3 - Como acionar e configura o PORT4.

4 - Exemplo de leitura de pinos e acionamento das IO's.

        Aqui é usado o caracter '/' para indicar inicio de dados, mas pode ser trocado por outro, e o caracter '\n' para fim de dados. Assim basta digitar num terminal serial os dados da seguinte forma : "/dados\n."

O código fonte :

//Autor : Aguivone M. F.
//Compilador: Simplicity studio - Silicon labs 
// EXEMPLO DE COMO USAR A A SERIAL E OS PINOS DO MICROCONTROLADOR C8051F380-A-GQ //----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- #include <SI_C8051F380_Register_Enums.h> //----------------------------------------------------------------------------- // Global CONSTANTS //----------------------------------------------------------------------------- #define SYSCLK 48000000 // frequencia em Hz #define BAUDRATE 9600 // Baud rate da UART0 em bps // todos o led são ligados ao VCC #define LED_freq1 0x7F #define LED_freq2 0xBF #define LED_Status 0xF7 // P4.3 #define LED_ping 0xEF //P4.4 unsigned char porta4 = 0XFF; //----------------------------------------------------------------------------- // Function PROTOTYPES //----------------------------------------------------------------------------- SI_INTERRUPT_PROTO(UART0_Interrupt, UART0_IRQn); void SYSCLK_Init (void); void UART0_Init (void); void PORT_Init (void); //----------------------------------------------------------------------------- // Global Variables //----------------------------------------------------------------------------- // variaveis da serial RS232 #define UART_BUFFERSIZE 30 uint8_t UART_Buffer_rx[UART_BUFFERSIZE]; uint8_t UART_Buffer_tx[UART_BUFFERSIZE];//para transmissão uint8_t pos_buffer=0; uint8_t tam_buffer_tx=0; uint8_t pos_buffer_tx=0; bool tem_recp = 0; bool rec_232 = 0; bool trans_232 = 0; uint16_t pisca =0; char liga_pino_status = 0; //----------------------------------------------------------------------------- // SiLabs_Startup() - POSIÇÃO INICIAL A SER EXECUTADA // ---------------------------------------------------------------------------- void SiLabs_Startup (void) { PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer } //----------------------------------------------------------------------------- // 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; } //----------------------------------------------------------------------------- // PORT_Init - INICIALIZA AS PORTAS //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure the Crossbar and GPIO ports. // // P0.4 digital push-pull UART TX // P0.5 digital open-drain UART RX // //----------------------------------------------------------------------------- void PORT_Init (void) { P0MDIN = 0xFF; // are digital P0MDOUT = 0x20; // Enable UTX as push-pull output XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX) XBR1 = 0x40; // Enable crossbar and weak pull-ups P4MDOUT = 0x04; // enable Switches as open-drain P4MDIN = 0xFF; // are digital P4 = 0XFF ; //portas de p4 ligadas (desliga leds) } //----------------------------------------------------------------------------- // SYSCLK - INICIA A CONFIGURAÇÃO DO CLOCK //----------------------------------------------------------------------------- void SYSCLK_Init (void) { // configurado para 48mhz OSCICN = 0X83; // IHFOsc Enable, sem divisão ira rodar a 12MHz CLKMUL = 0XC0; // talvez nem precise neste microcontrolador -> habilita e inicializa pll CLKSEL = 0X03; // SYSCLK derived from the Internal High-Frequency Oscillator.sem divisão 48MHZ se estiver habilitado o clksel 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; RSTSRC = 0x04; // Enable missing clock detector } //----------------------------------------------------------------------------- // UART0_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1. //----------------------------------------------------------------------------- void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is ignored // RX enabled // ninth bits are zeros // clear SCON0_RI and SCON0_TI bits if (SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2); CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx CKCON |= 0x08; } else if (SYSCLK/BAUDRATE/2/256 < 4) { TH1 = -(SYSCLK/BAUDRATE/2/4); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01 CKCON |= 0x01; } else if (SYSCLK/BAUDRATE/2/256 < 12) { TH1 = -(SYSCLK/BAUDRATE/2/12); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00 } else { TH1 = -(SYSCLK/BAUDRATE/2/48); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10 CKCON |= 0x02; } IE_ES0 = 1; //habilita interrupção de serial TL1 = TH1; // Init Timer1 TMOD &= ~0xF0; // TMOD: timer 1 in 8-bit autoreload TMOD |= 0x20; TCON_TR1 = 1; // START Timer1 } //----------------------------------------------------------------------------- // Interrupt Service Routines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // UART0_Interrupt //----------------------------------------------------------------------------- // // This routine is invoked whenever a character is entered or displayed on the // Hyperterminal. // //----------------------------------------------------------------------------- SI_INTERRUPT(UART0_Interrupt, UART0_IRQn) { if (SCON0_RI == 1) { char RX_232 = SBUF0; SCON0_RI = 0; if(pos_buffer >= UART_BUFFERSIZE) // tem um bug no compilador ou chip que faz reseta {//erro descarta, pois é maior que o tamanho maximo do buffer rec_232=0; //não recebendo pos_buffer=0;//limpa buffer tem_recp = 0;//sinaliza fim de pacote } if(rec_232 && RX_232 == '\n') {//esta recebendo e chegou delimitador de fim rec_232=0; //não recebendo tem_recp = 1;//sinaliza fim de pacote Liga_Port4(LED_ping); } if(rec_232) {//esta recebendo UART_Buffer_rx[pos_buffer] = RX_232; pos_buffer++; } if(RX_232 == '/') { pos_buffer=0;//sinaliza recepção rec_232=1; //recebendo } } if (SCON0_TI) //testa se tem transmissão { SCON0_TI = 0; // limpa flag de tranmissão if(trans_232 == 1) { if (pos_buffer_tx < tam_buffer_tx) {// transmitindo SBUF0 = UART_Buffer_tx[pos_buffer_tx];//escreve na porta serial pos_buffer_tx++; } else { trans_232 = 0; //fim de transmissao pos_buffer_tx =0; } } } } void escreve_frase(char dados[] ,uint8_t tam) { while(trans_232); //faz nada só espera enviar todo o pacote talvez por um time out //se ja houver dados para ser enviado espera terminar para comecar a enviar. // veja que pode travar um pouco aqui o processamento tam_buffer_tx = 0; while(tam > tam_buffer_tx) { UART_Buffer_tx[tam_buffer_tx] = dados[tam_buffer_tx];//transfere dados tam_buffer_tx++; } trans_232 = 1;//sinaliza que deve transmitir SCON0_TI = 1; //para dar inicio a transmissão } //----------------------------------------------------------------------------- // MAIN Routine //----------------------------------------------------------------------------- void main (void) { // enable) PORT_Init(); // Initialize Port I/O SYSCLK_Init (); // Initialize Oscillator UART0_Init(); IE_EA = 1;//habilita todas as interrupções escreve_frase("Escreva na formato: /xx\n \r" ,25); while(1) { if(tem_recp)//recebeu dados { //trata os dados recebidos que estão em : UART_Buffer_RX escreve_frase("\n\r",2);//salta linha e retorna para o inicio de linha escreve_frase("recebeu dados =>" ,16); escreve_frase(UART_Buffer_rx ,pos_buffer); pos_buffer = 0; tem_recp = 0;//sinaliza que já leu Desliga_Port4(LED_ping); } pisca++; if(pisca > 65500) { // pisca led if(liga_pino_status == 0) { liga_pino_status = 1; Liga_Port4(LED_Status); SCON0_TI = 0; } else { liga_pino_status = 0; Desliga_Port4(LED_Status); } pisca =0; } } } //----------------------------------------------------------------------------- // End Of File //-----------------------------------------------------------------------------

Formatado em http://hilite.me/  acessado em 03_11_2023.