Fork me on GitHub

Microcontrolandos

O Blog está passando por uma fase de mudanças. Todos os posts estão sendo atualizados, códigos, links e imagens estão sendo arrumados. Conteúdos novos ainda estão por vir.

PIC: RDA5807

Compartilhe:

PIC: RDA5807



RDA5807P é um circuito integrado que é capaz de sintonizar emissoras de rádio FM, operando na faixa de 76MHz até 108MHz.

CARACTERÍSTICAS

  • Duas bandas de frequência;
  • Mono ou Stereo;
  • Indicador de força do sinal ( RSSI );
  • Controle de volume;
  • Comunicação I2C;
  • Tensão de alimentação: 5V;
VANTAGENS
Este chip possui as mesmas características do TEA5767. A vantagem de utilizá-lo é que eu encontrei uma placa pronta para utilizar, precisando apenas conectar os fios, ao contrário do TEA5767 ( talvez exista um módulo para ele, mas não encontrei ) que precisa soldar os fios e correr o risco de destruir a plaquinha ( acabei arrancando uns componentes, rs ). Outra vantagem do RDA5807P é que é possível controlar o volume da saída, mesmo utilizando fones de ouvido, o som é muito alto.

FUNCIONAMENTO
Possui 4 registradores internos de 16 bits, utilizados para sua configuração, como a frequência atual, volume, seleção da banda, ativar o modo de busca, entre outros. Para realizar a operação de escrita, basta enviar o endereço do dispositivo ( 0x20 ) e os 8 bytes.


Para poder sintonizar uma frequência, devemos escrever nos bits CHAN, setar o bit TUNE e enviar os todos os bytes. Podemos calcular o valor da frequência através dessa fórmula: F = SPACE * CHAN + ( 87000 ou 76000 );

Para realizar uma busca, devemos definir a direção da busca ( pra cima ou pra baixo ) definindo um valor para o bit SEEKUP. Também devemos setar o bit SEEK e enviar todos os bytes.

Também possui 2 registradores de 16 bits, que são utilizados para leitura, informando a frequência atual, a força do sinal captado e contendo vários bits de sinalização.


CÓDIGO DA BIBLIOTECA
MikroC PRO PIC
/*
RDA5807 - SINGLE-CHIP BROADCAST FM RADIO TUNER
Autor: Tiago
Blog: microcontrolandos.blogspot.com.br
Compilador: MikroC PRO PIC
*/
#define RDA5807P_ADDRESS 0x20
typedef struct
{
union
{
char ENABLE : 1; //Power Up Enable. 0 = Disabled; 1 = Enabled.
char RESET : 1; //Soft reset. 1 = Reset.
char : 2;
char CLK_MODE : 3; //000 = 32.768kHz, 001 = 12Mhz, 101 = 24Mhz, 010 = 13Mhz, 110 = 26Mhz, 011 = 19.2Mhz, 111 = 38.4Mhz
char SKMODE : 1; //Seek Mode.
char SEEK : 1; //Seek. 0 = Disable stop seek; 1 = Enable.
char SEEKUP : 1; //Seek Up. 0 = Seek down; 1 = Seek up.
char : 2;
char BASS : 1; //Bass Boost. 0 = Disabled; 1 = Bass boost enabled
char MONO : 1; //Mono Select. 0 = Stereo; 1 = Force mono.
char DMUTE : 1; //Mute Disable. 0 = Mute; 1 = Normal operation.
char DHIZ : 1; //Audio Output High-Z Disable. 1 = Normal operation.
unsigned REG02;
};
union
{
char SPACE : 2; //Channel Spacing. 00 = 100 kHz, 01 = 200 kHz, 10 = 50kHz, 11 = 12.5KHz
char BAND : 2; //Band Select. 00 = 87–108 MHz (US/Europe), 01 = 76–91 MHz (Japan), 10 = 76–108 MHz (world wide), 11 = 65 –76 MHz ( East Europe) or 50-65MHz
char TUNE : 1; //Tune. 0 = Disable, 1 = Enable.
char : 1;
char CHANNEL : 10; //Channel Select. Se BAND = 0, Freq = SPACE(kHz) x CHANNEL + 87.0 MHz...
unsigned REG03;
};
union
{
char : 1;
char STCIEN : 1; //Seek/Tune Complete Interrupt Enable.
char : 2;
char DE : 1; //De-emphasis. 0 = 75 us; 1 = 50 us
char : 4;
char I2S_ENABLED : 1; //I2S bus enable. If 1, enabled.
char GPIO3 : 2;
char GPIO2 : 2;
char GPIO1 : 2;
unsigned REG04;
};
union
{
char VOLUME : 4; //DAC Gain Control Bits. Volume scale is logarithmic.
char : 4;
char SEEKTH : 7; //Nivel minino do sinal ( RSSI ) para encontrar uma radio.
char INT_MODE : 1; //If 0, generate 5ms interrupt.
unsigned REG05;
};
}RDA5807P;
typedef struct
{
unsigned long FREQUENCY;
union
{
char LEVEL : 8; //RSSI ( 7 bits )
char STC : 1; //STC. 1 = Busca/Sintonizacao terminou.
char SF : 1;
char STEREO : 1; //1 = Stereo, 0 = Mono.
char FM_TRUE : 1; //1 = the current channel is a station.
char FM_READY : 1; //FM Ready
};
}RDA5807PInfo;
/* Funções */
void RDA5807P_Init( RDA5807P * radio );
void RDA5807P_Write( RDA5807P * radio );
RDA5807PInfo RDA5807P_Read( RDA5807P * radio );
void RDA5807P_Up( RDA5807P * radio );
void RDA5807P_Down( RDA5807P * radio );
void RDA5807P_Set_Frequency( RDA5807P * radio, unsigned long freq_khz );
void RDA5807P_Init( RDA5807P * radio )
{
radio->REG02 = 0xD081; //boss = true, enable = true, mute = false, seekmode = 1
radio->REG03 = 0x0010; //space = 100KHz, tune = true
radio->REG04 = 0x0000;
radio->REG05 = 0x88AF; //volume maximo
RDA5807P_Write( radio );
}
void RDA5807P_Write( RDA5807P * radio )
{
char i;
unsigned * wData = (unsigned*)radio;
Soft_I2C_Start();
Soft_I2C_Write( RDA5807P_ADDRESS );
for( i = 0; i < 4; i++ )
{
Soft_I2C_Write( ((char*)wData)[1] ); //High
Soft_I2C_Write( ((char*)wData)[0] ); //Low
wData++;
}
Soft_I2C_Stop();
}
void RDA5807P_Search( RDA5807P * radio, char dir )
{
radio->SEEKUP = dir.B0;
radio->TUNE = 0;
radio->SEEK = 1;
RDA5807P_Write( radio );
radio->SEEK = 0;
Delay_ms( 20 );
}
RDA5807PInfo RDA5807P_Read( RDA5807P * radio )
{
char rData[4];
char cs = 100;
RDA5807PInfo info;
Soft_I2C_Start();
Soft_I2C_Write( RDA5807P_ADDRESS | 1 );
rData[1] = Soft_I2C_Read(1); //High
rData[0] = Soft_I2C_Read(1); //Low
rData[3] = Soft_I2C_Read(1); //High
rData[2] = Soft_I2C_Read(0); //Low
Soft_I2C_Stop();
info.STC = rData[1].B6;
info.SF = rData[1].B5;
info.STEREO = rData[1].B2;
info.FM_TRUE = rData[3].B0;
info.FM_READY = rData[2].B7;
info.LEVEL = rData[3] >> 1;
rData[1] &= 0x3; //limpa os 6 bits mais significativos...ja foram lidos acima.
radio->CHANNEL = ((unsigned*)&rData)[0];
R3 = radio->SPACE;
switch( R3 )
{
case 1 : cs = 200; break;
case 2 : cs = 50; break;
case 3 : cs = 12; break;
}
info.FREQUENCY = cs * (unsigned long)((unsigned*)&rData)[0] + ( !radio->BAND ? 87000UL : 76000UL );
return info;
}
void RDA5807P_Up( RDA5807P * radio )
{
radio->CHANNEL++;
radio->TUNE = 1;
RDA5807P_Write( radio );
radio->TUNE = 0;
Delay_ms( 20 );
}
void RDA5807P_Down( RDA5807P * radio )
{
radio->CHANNEL--;
radio->TUNE = 1;
RDA5807P_Write( radio );
radio->TUNE = 0;
Delay_ms( 20 );
}
void RDA5807P_Set_Frequency( RDA5807P * radio, unsigned long freq_khz )
{
char cs = 100;
R3 = radio->SPACE;
switch( R3 )
{
case 1 : cs = 200; break;
case 2 : cs = 50; break;
case 3 : cs = 25; break;
}
radio->CHANNEL = ( freq_khz - ( !radio->BAND ? 87000UL : 76000UL ) ) / cs;
radio->TUNE = 1;
RDA5807P_Write( radio );
radio->TUNE = 0;
Delay_ms( 20 );
}
view raw RDA5807P.C hosted with ❤ by GitHub

EXEMPLO:





/*
PROJETO: Radio FM com RDA5807P
MCU: PIC18F4550
Compilador: MikroC PRO PIC
Autor: Tiago
Blog: microcontrolandos.blogspot.com.br
Bibliotecas utilizadas: RDA5807P, SSD1306, Conversions
*/
/* pinos */
sbit Soft_I2C_Sda at RD0_Bit;
sbit Soft_I2C_Scl at RD1_Bit;
sbit Soft_I2C_Sda_Direction at TRISD0_Bit;
sbit Soft_I2C_Scl_Direction at TRISD1_Bit;
/* constantes */
const int UP = 5;
const int DOWN = 6;
const int SEARCH = 7;
/* variáveis */
char flags = 0; //armazena os estados dos botões
RDA5807P radio; //configurações do módulo
RDA5807PInfo info; //informação da rádio selecionada
char msg[12]; //usado para armazenar a conversão de um número em string
void main()
{
ADCON1 = 15; //desliga o conversor analogico
CMCON = 7; //desliga o comparador analogico
TRISB = 255; //defina todos os pinos como entrada
Soft_I2C_Init(); //iniciliza a comunicacao I2C
INTCON2.NOT_RBPU = 0; //habilita os resistores de pull-up
RDA5807P_Init( &radio ); //inicializa o módulo
SSD1306_Init(); //inicializa o display
SSD1306_Clear(); //limpa o display
SSD1306_Out8( 0, 4, "RADIO FM", 0 ); //escreve um texto
SSD1306_Out8( 5, 0, "SINAL:", 1 ); //escreve um texto
while( 1 )
{
if( !PORTB.UP ) flags.UP = 1; //botao UP foi pressionado
else if( !PORTB.DOWN ) flags.DOWN = 1; //botao DOWN foi pressionado
else if( !PORTB.SEARCH ) flags.SEARCH = 1; //botao SEARCH foi pressionado
if( PORTB.UP && flags.UP ) //botao UP foi liberado
{
flags.UP = 0; //limpa a flag
RDA5807P_Up( &radio ); //incrementa a frequência atual do rádio
}
else if( PORTB.DOWN && flags.DOWN ) //botao DOWN foi liberado
{
flags.DOWN = 0; //limpa a flag
RDA5807P_Down( &radio ); //decrementa a frequência atual do rádio
}
else if( PORTB.SEARCH && flags.SEARCH ) //botao SEARCH foi liberado
{
flags.SEARCH = 0; //limpa a flag
RDA5807P_Search( &radio, 1 ); //realiza a busca por estações de rádio
}
info = RDA5807P_Read( &radio ); //realiza a leitura da informação da rádio atual
/* Exibe a frequência no display */
WordToStr( info.FREQUENCY / 100, msg ); //converte a frequência( MHz ) em string
SSD1306_Chr8( 3, 4, msg[1], 1 );
SSD1306_Chr8( 3, 5, msg[2], 1 );
SSD1306_Chr8( 3, 6, msg[3], 1 );
SSD1306_Chr8( 3, 7, '.', 1 );
SSD1306_Chr8( 3, 8, msg[4], 1 );
SSD1306_Out8( 3, 9, "MHz", 1 );
/* Exibe a força de sinal da rádio atual */
ByteToStr( info.LEVEL, msg ); //converte o valor do sinal em string
SSD1306_Out8( 5, 6, msg + 1, 1 );
Delay_ms( 80 );
}
}
view raw RDA5807P_demo.C hosted with ❤ by GitHub

Escreva um comentário

14 comentários:

  1. Mas onde estão as bibliotecas para SSD1306 ..!

    ResponderExcluir
  2. Pra mim ta dando um erro nas estruturas "union", o erro fala "Invalid declarator expected'(' or identifier" e indica onde fecha a chave do "union" no ";"... ja tentei diversas coisas e nada, sabe o que pode ser? bem que vc poderia tirar um print da janela "edit project" pra saber como que ficou a configuração no teste

    ResponderExcluir
    Respostas
    1. Dei Ctrl+C, Ctrl+V no código e aqui tá compilando numa boa...Utilize a ultima versão do MikroC. Sobre os bits de configuração, eu não coloco porque cada um pode utilizar um PIC diferente, clock diferente, etc, e em geral não há muito o que alterar nas configurações.

      Excluir
    2. OK, minha versao do MikroC é a 6.0.0, vou tentar instalar a versão mais atual para ver se funciona! vlw pela atenção.

      Excluir
    3. Vlw Tiago, era o mikroC mesmo, funcionou perfeito, eu modifiquei para usar o lcd 16x2 e deu certo, gostei do som desse RDA ta bem legal por ser um circuito minusculo rs... ainda vou modificar mais pra tentar usar com outros periféricos, se eu tiver outras duvidas no codigo eu te pergunto rsrs... vlw mesmo me ajudou bastante.

      Excluir
  3. Tiago meus parabéns pelo seu post, seu código funcionou perfeitamente aqui. Só uma dúvida, queria coloca botões para controle de volume, criei as funções para fazer isso e realizo o incremento e decremento do char VOLUME, porem não surte efeito... Existe algum formular para isso? Não consegui achar nada especifico na net que pudesse me ajuda.

    Obrigado e novamente parabéns pelo seu post. Abs,

    ResponderExcluir
    Respostas
    1. cara isso é facil... na biblioteca adiciona um void para decrementar o volume e outro para incrementar, tipo assim...
      void RDA5807P_VOLDW( RDA5807P * radio)
      {
      radio->VOLUME--;
      RDA5807P_Write( radio );
      Delay_ms( 40 );
      }
      faça outro pra incrementar, e depois comanda no programa principal. ok flw

      Excluir
    2. Fiz exatamente isso que você mencionou, segue minha função, porem quando faço a chamada dela nada acontece....
      void RDA5807P_VOL_UP( RDA5807P * radio )
      {
      radio->VOLUME++;
      RDA5807P_Write( radio );
      Delay_ms( 20 );
      }

      Você já utilizou deste mesmo modo?

      Obrigado. Abs.

      Excluir
    3. funciona sim!
      adiciona tbm uma chamada na biblioteca na parte
      onde ta escrito /* funções */ coloca o seu void RDA5807_VOl_UP(RDA6807*radio); lá
      agora no programa faz um if pro botao
      if(se tal botao + for pressionado)
      {
      limpa o flag;
      RDA5807_VOL_UP(&radio);
      }
      isso tem que dar certo, senão é outra coisa ok. cabe a vc analisar.
      flw

      Excluir
  4. Olá ! Como eu poderia incluir os botões para volume + e - ? Obrigado.

    ResponderExcluir
  5. Como usar o RDS dele ? E como adaptar para LCD 16x2 ?

    ResponderExcluir
  6. Estou com este projeto na bancada, alguem tem alguma tabela das funcionalidades da comunicação I2C? não encontrei nenhuma LIB

    ResponderExcluir