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;
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 ); | |
} |
EXEMPLO:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 ); | |
} | |
} |
Mas onde estão as bibliotecas para SSD1306 ..!
ResponderExcluirtá no post anterior a este...
ExcluirPra 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
ResponderExcluirDei 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.
ExcluirOK, minha versao do MikroC é a 6.0.0, vou tentar instalar a versão mais atual para ver se funciona! vlw pela atenção.
ExcluirVlw 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:)
ExcluirTiago 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.
ResponderExcluirObrigado e novamente parabéns pelo seu post. Abs,
cara isso é facil... na biblioteca adiciona um void para decrementar o volume e outro para incrementar, tipo assim...
Excluirvoid 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
Fiz exatamente isso que você mencionou, segue minha função, porem quando faço a chamada dela nada acontece....
Excluirvoid RDA5807P_VOL_UP( RDA5807P * radio )
{
radio->VOLUME++;
RDA5807P_Write( radio );
Delay_ms( 20 );
}
Você já utilizou deste mesmo modo?
Obrigado. Abs.
funciona sim!
Excluiradiciona 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
Olá ! Como eu poderia incluir os botões para volume + e - ? Obrigado.
ResponderExcluirComo usar o RDS dele ? E como adaptar para LCD 16x2 ?
ResponderExcluirEstou com este projeto na bancada, alguem tem alguma tabela das funcionalidades da comunicação I2C? não encontrei nenhuma LIB
ResponderExcluir