segunda-feira, 11 de julho de 2016

Usando 2 portas seriais no mesmo microcontrolador - 16F1947

         Olá, as vezes queremos usar 2 portas seriais ao mesmo tempo a melhor forma de se fazer isso e usar um microcontrolador que possua 2 portas UART(COM) em seu hardware, graças a compatibilidade entre os microcontroladores e com poucas alterações e possível fazer com que um mesmo código execute as configurações da serial e imprima nas duas portas sem grandes dificuldades.
          Neste exemplo tudo que é digitado em qualquer uma das portas é retornado na mesma porta. Veja o código fonte do aquivo "Main.c" e do "serial16F1947.c". A simulação do código é vista na figura a seguir, veja que neste exemplo na serial 1 pressionei F e na serial 2 pressionei H e então recebi o mesmo carácter de volta ficando FF e HH.


O código fonte:


/*
 *               testando hardware do microcontrolador - 2 serial        
 *
 * Compilador : MPlabXC8
 * Microcontrolador: 16F1947
 * Autor: aguivone
 * Versão: 1
 * Data :  11/07/2016*/
#include <xc.h>
#include <stdio.h>
#include "serial16F1947.c"

#define _XTAL_FREQ 16000000//usado para rotinas de  delays
#define LED               LATDbits.LATD4
#define LER_LED           PORTDbits.RD4

//
///////////configuração dos fuses bits/////////////////////////////////////////////
// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable (VCAP pin functionality is disabled)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
//////////////////////////////////////////////////////////////////////////////////

//************************************************************************************/
//VARIAVEIS GLOBAIS
//************************************************************************************/

////variaveis da porta serial
char   gcCaracter;
//*******************************************************************************/
//===================================================================================
//Função:    _interrupcoes
//Descrição: usada para tratar as interrupções geradas pelo microcontrolador.
//===================================================================================
void interrupt interrupcoes(void)//vetor de interrupção
 {
      if(RC1IF)//verifica interrupção da serial na COM1
    {//interrupção da serial
        gcCaracter = RC1REG;   
        escreve_RS232(gcCaracter,0);//finaliza string
        RC1IF = 0;//  limpa flag de interrupção de recepção
    }
    if(RC2IF)//verifica interrupção da serial na COM2
    {//interrupção da serial
        gcCaracter = RC2REG;
        escreve_RS232(gcCaracter,1);//finaliza string
        RC2IF = 0;//  limpa flag de interrupção de recepção
    }
}

//===================================================================================
//Função:    _config_CPU
//Parâmetros: não tem
//Retorno:   não tem retorno.
//Descrição: inicializa os registradores do microcontrolador.
//===================================================================================
void config_CPU()
{
    //configura portas logicas
    TRISA = 0X00;
    TRISB = 0X00;
    TRISC = 0x80;
    TRISD = 0x00;
    TRISE = 0x00;
    TRISF = 0x00;//todos entrada e ainda são as entrasas analogicas
    TRISG = 0x04;
    // inicializa portas logicas configuradas como saida para 0
    LATA = 0;
    LATB = 0;
    LATC = 0;
    LATD = 0;
    LATE = 0;
    LATF = 0;
    LATG = 0;
    inicializa_RS232(9600,1,0);//modo de alta velocidade inicializa COM1
    inicializa_RS232(9600,1,1);//modo de alta velocidade inicializa COM2
    PEIE = 1;//habilita interrupção de perifericos do pic
    GIE = 1; //GIE: Global Interrupt Enable bit  
    __delay_ms(100);
    
}
void main(void) 
{
    config_CPU(); 
    imprime_RS232("Imprimindo: COM 1!\r\n",0); 
    imprime_RS232("Digite um caracter:\r\n",0); 
    imprime_RS232("Imprimindo: COM 2!\r\n",1);  
    imprime_RS232("Digite um caracter:\r\n",1);
    for(;;)
    { 
       //faz nada          
    }
}

O código do arquivo "serial16F1947.c"

/*
 *                          FUNÇOES USADAS NA SERIAL
 *
 * Compilador :      MPlabXC8
 * Microcontrolador: 16F1947
 * Autor:            Aguivone
 * Versão:           1
 * Data de criação:  11 de julho de 2016.
 */

#include <xc.h>
#include <stdio.h>
#include <string.h> //para usar funçoes de string deve se adicionar este header
#define _XTAL_FREQ 16000000//usado para rotinas de  delays

//===================================================================================
//Função:    _inicializa_RS232
//Parâmetros: unsigned long ulVelocidade
//          : unsigned int uiModo
//          : porta serial(1 ou 0) 
//Retorno:   não tem retorno.
//Descrição: usada para iniciar a porta serial.
//===================================================================================
void inicializa_RS232(unsigned long ulVelocidade,unsigned int uiModo,int porta)
{//// por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada.
    // verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado.
    unsigned long valor;
    if(porta == 0)
    {
        RC1STA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.        
            if(uiModo == 1)
            {//modo = 1 ,modo alta velocidade
             TX1STA = 0X24;//modo assincrono,trasmissao 8 bits.
             valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
            }
            else
            {//modo = 0 ,modo baixa velocidade
             TX1STA = 0X20;//modo assincrono,trasmissao 8 bits.
             valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
            }
        SP1BRG = valor;
        RC1IE = 1;//habilita interrupção de recepção
        TX1IE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)

    }
    else
    {
       RC2STA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono.
        if(uiModo == 1)
        {//modo = 1 ,modo alta velocidade
         TX2STA = 0X24;//modo assincrono,trasmissao 8 bits.
         valor =(((_XTAL_FREQ/ulVelocidade)-16)/16);//calculo do valor do gerador de baud rate
        }
        else
        {//modo = 0 ,modo baixa velocidade
         TX2STA = 0X20;//modo assincrono,trasmissao 8 bits.
         valor =(((_XTAL_FREQ/ulVelocidade)-64)/64);//calculo do valor do gerador de baud rate
        }
    SP2BRGL = valor;
    SP2BRGH = valor<<8;
    RC2IE = 1;//habilita interrupção de recepção
    TX2IE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo)
    }
    
}
//===================================================================================
//Função:    _escreve1_RS232
//Parâmetros: char cValor, int porta
//Retorno:   não tem retorno.
//Descrição: usada para escrever 1 caracter.
//===================================================================================
 void escreve_RS232(char cValor,int porta)
{
     if(porta == 0)
    {
        TX1IF = 0;//limpa flag que sinaliza envio completo.
        TX1REG = cValor;
        while(TX1IF ==0);//espera enviar caracter
    }
    else
    {
        TX2IF = 0;//limpa flag que sinaliza envio completo.
        TX2REG = cValor;
        while(TX2IF ==0);//espera enviar caracter
    }
     __delay_us(10);//só pra garantir
}
 
//===================================================================================
//Função:    _imprime_RS232
//Parâmetros: const char ccFrase[], int porta
//Retorno:   não tem retorno.
//Descrição: usada para escrever uma string(vetor de caracteres).
//===================================================================================
 void imprime_RS232(const char ccFrase[],int porta)
{
     unsigned char indice = 0;
     unsigned char tamanho = strlen(ccFrase);     
      while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas
       {
           escreve_RS232(ccFrase[indice],porta);
           indice++;
       }
}


Nenhum comentário :

Postar um comentário

olá,digite aqui seu comentário!