sexta-feira, 22 de julho de 2022

Comunicação serial com o microcontrolador C8051F832

         Exemplo de como fazer uma comunicação serial usando o microcontrolador C8051F832 de 16 pinos. Basta colocar os caractere precedido por  "*" para indicar fim de recepção.

/*
 * 
 * Compilador : Simplicity studio
 * Microcontroladores compativeis : C8051F832
 * Autor: Aguivone Moretti Fógia
 * Versão: 1.0
 * Data :  22_07_2022           ->  inicio de teste de comunicação serial
 * Descrição:
 * teste de comunicação serial
 * Basta envia um dado e depois o caracter "*" para indicar fim de recepção
 * exemplo:  teste*  ira ter como retorno "TESTE"
 */

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "si_toolchain.h"
#include <SI_C8051F800_Defs.h>            // SFR
#include <stdio.h>
#include <string.h>

#define SYSCLK           24500000      // SYSCLK em hertz usando clock interno
#define BAUDRATE           19200      // Baud rate em bps

//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------

void SYSCLK_Init (void);
void UART0_Init (void);
void PORT_Init (void);
SI_INTERRUPT_PROTO(UART0_ISR, INTERRUPT_UART0);


//-----------------------------------------------------------------------------
// variaveis globais
//-----------------------------------------------------------------------------

#define UART_TAM_MAX 64
uint8_t UART_Buffer[UART_TAM_MAX] = {0};
uint8_t UART_buffer_tamanho = 0;
uint8_t UART_primeira_entrada = 0;
uint8_t UART_primeira_saida = 0;
uint8_t Enviar_dados =1;
static uint8_t Caracter_temporario;

//-----------------------------------------------------------------------------
// SiLabs_Startup()
// ----------------------------------------------------------------------------
// Essa rotina roda sempre primeiro que o rotina main
//-----------------------------------------------------------------------------
void SiLabs_Startup (void)
{
   PCA0MD &= ~0x40;                    // WDTE = 0 (desliga watchdog )
}

//-----------------------------------------------------------------------------
//Rotina principal
//-----------------------------------------------------------------------------

void main (void)
{

   PORT_Init();                        // inicializa portas
   SYSCLK_Init ();                     // inicializa oscilador
   UART0_Init();                       // inicializa UART
   IE_EA = 1;                          // habilita interrupções
   UART_Buffer[0] ='D';
   UART_Buffer[1] ='I';
   UART_Buffer[2] ='G';
   UART_Buffer[3] ='I';
   UART_Buffer[4] ='T';
   UART_Buffer[5] ='E';
   UART_Buffer[6] =' ';
   UART_Buffer[7] ='A';
   UART_Buffer[8] ='L';
   UART_Buffer[9] ='G';
   UART_Buffer[10] ='O';
   UART_Buffer[11] ='!';
   UART_buffer_tamanho = 12;             // atualiza tamanho do buffer
   UART_primeira_entrada = 12;
   Enviar_dados = 0;                 // limpa flag
   SCON0_TI = 1;                 // indica pra trasnmitir pois tem dados
   while(1)
   {
      // se houver dados recebido será enviado
      if((Enviar_dados == 1) && (UART_buffer_tamanho != 0) && (Caracter_temporario == '*'))//tx pronto /buffer cheio / finalizador de pacote
      {
         Enviar_dados = 0;                 // limpa flag
         SCON0_TI = 1;                 // indica pra trasnmitir pois tem dados
      }

   }
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// Configure the Crossbar and GPIO ports.
//
// P0.4   digital   push-pull    UART TX = como saida
// P0.5   digital   open-drain   UART RX = como entrada
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
   P0MDOUT |= 0x10;                    // 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
}

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This routine initializes the system clock to use the internal precision
// oscillator at its maximum frequency and enables the missing clock
// detector.
//
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
   OSCICN |= 0x83;                     // Enable the precision internal osc.

   RSTSRC = 0x06;                      // habilita detector de falta de clock e
                                       // deixa monitor de VDD habilitado.

   CLKSEL = 0x00;                      // seleciona a precisão interna.
                                       // clock sem divisão
}

//-----------------------------------------------------------------------------
// 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 RI0 and TI0 bits
   #if (SYSCLK/BAUDRATE/2/256 < 1)
      TH1 = -(SYSCLK/BAUDRATE/2);
      CKCON &= ~0x0B;                  // T1M = 1; SCA1:0 = xx
      CKCON |=  0x08;
   #elif (SYSCLK/BAUDRATE/2/256 < 4)
      TH1 = -(SYSCLK/BAUDRATE/2/4);
      CKCON &= ~0x0B;                  // T1M = 0; SCA1:0 = 01
      CKCON |=  0x01;
   #elif (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;
   #endif

   TL1 = TH1;                          // Initialize Timer1
   TMOD &= ~0xf0;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=  0x20;
   TCON_TR1 = 1;                       // START Timer1
   Enviar_dados = 1;                       // Flag showing that UART can transmit
   IP |= 0x10;                         // Make UART high priority
   IE_ES0 = 1;                         // Enable UART0 interrupts

   SCON0_TI = 1;
}

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

//-----------------------------------------------------------------------------
// UART0_Interrupt
//-----------------------------------------------------------------------------
//
// This routine is invoked whenever a character is entered or displayed on the
// Hyperterminal.
//
//-----------------------------------------------------------------------------
SI_INTERRUPT(UART0_ISR, UART0_IRQn)
{
   if (SCON0_RI == 1)
   {
      if( UART_buffer_tamanho == 0)
        {// tem dados
         UART_primeira_entrada = 0;
        }

         SCON0_RI = 0;                      // limpa flag de interrupção de recepção

         Caracter_temporario = SBUF0;                      // Lê o caracter que está no buffer

      if (UART_buffer_tamanho < UART_TAM_MAX)
      {
         UART_Buffer[UART_primeira_entrada] = Caracter_temporario; // coloca no buffer para transmitir

         UART_buffer_tamanho++;             // atualiza tamanho do buffer

         UART_primeira_entrada++;             // atualiza contagem
      }
   }

   if (SCON0_TI == 1)                    // verifica se houve interrupção de transmissão
   {
     SCON0_TI = 0;                     // limpa flag

      if (UART_buffer_tamanho != 0)         // se tiver dados a enviar envia
      {
         //tem um pacote valido
         if ( UART_buffer_tamanho == UART_primeira_entrada ) {
              UART_primeira_saida = 0;  }

         // armazena informação em Caracter_temporario
         Caracter_temporario = UART_Buffer[UART_primeira_saida];

         if ((Caracter_temporario >= 0x61) && (Caracter_temporario <= 0x7A)) { // se não tiver em caixa alta(maiuscula) passa para caixa alta.
            Caracter_temporario -= 32; }

         SBUF0 = Caracter_temporario;                   // coloca no registrador de transmissão de dados

         UART_primeira_saida++;            // atualiza contagem

         UART_buffer_tamanho--;             // decrementa o tamanho

      }
      else
      {
         UART_buffer_tamanho = 0;           // zera contagem
         Enviar_dados = 1;                   // indica que dados foram enviado
      }
   }
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

Formato no site  http://hilite.me/  no dia 22/07/2022.