Skip to content

Instantly share code, notes, and snippets.

@tiagohm
Created August 3, 2017 10:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiagohm/69bfa031786f903471e0dd8fd7e75285 to your computer and use it in GitHub Desktop.
Save tiagohm/69bfa031786f903471e0dd8fd7e75285 to your computer and use it in GitHub Desktop.
RDA5807 - Single-Chip Broadcast FM Radio Tuner
/*
RDA5807 - SINGLE-CHIP BROADCAST FM RADIO TUNER
Autor: Tiago Melo
Blog: tiagohm.github.io/microcontrolandos
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;
};
}rda5807_t;
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
};
}rda5807_status_t;
//Inicializa o chip RDA5807.
void RDA5807P_Init(rda5807_t * radio)
{
radio->REG02 = 0xD081; //bass = 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(rda5807_t * 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();
}
//Realiza a busca por uma estação de rádio.
void RDA5807P_Search(rda5807_t * radio, char dir)
{
radio->SEEKUP = dir.B0;
radio->TUNE = 0;
radio->SEEK = 1;
RDA5807P_Write(radio);
radio->SEEK = 0;
Delay_ms(20);
}
rda5807_status_t RDA5807P_Read(rda5807_t * radio)
{
char rdata[4];
char cs = 100;
rda5807_status_t info;
char space = radio->SPACE;
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];
switch(space)
{
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;
}
//Incrementa a frequência.
void RDA5807P_Up(rda5807_t * radio)
{
radio->CHANNEL++;
radio->TUNE = 1;
RDA5807P_Write(radio);
radio->TUNE = 0;
Delay_ms(20);
}
//Decrementa a frequência.
void RDA5807P_Down(rda5807_t * radio)
{
radio->CHANNEL--;
radio->TUNE = 1;
RDA5807P_Write(radio);
radio->TUNE = 0;
Delay_ms(20);
}
void RDA5807P_Set_Frequency(rda5807_t * radio, unsigned long freq_khz)
{
char cs = 100;
char space = radio->SPACE;
switch(space)
{
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);
}
/*
RDA5807 - SINGLE-CHIP BROADCAST FM RADIO TUNER
Autor: Tiago Melo
Blog: tiagohm.github.io/microcontrolandos
Compilador: MikroC PRO PIC
*/
#ifndef RDA5807_H
#define RDA5807_H
void RDA5807P_Init(rda5807_t * radio);
void RDA5807P_Write(rda5807_t * radio);
rda5807_status_t RDA5807P_Read(rda5807_t * radio);
void RDA5807P_Up(rda5807_t * radio);
void RDA5807P_Down(rda5807_t * radio);
void RDA5807P_Set_Frequency(rda5807_t * radio, unsigned long freq_khz);
#endif
/*
Pequeno rádio FM utilizando o chip RDA5807 e um PIC18F.
Pode-se alterar a frequencia e buscar por uma rádio.
Foi utilizado um display SSD1306 pra visualizar as info. da rádio.
Autor: Tiago Melo
Blog: tiagohm.github.io/microcontrolandos
Compilador: MikroC PRO PIC
MCU: PIC18F4550
Bibliotecas utilizadas: RDA5807P, SSD1306, Conversions, Software_I2C
*/
#include "SSD1306.h" //https://tiagohm.github.io/microcontrolandos/pic-ssd1306
#include "RDA5807.h"
/* 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
rda5807_t radio; //configurações do módulo
rda5807_status_t 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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment