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.