通過RDA5807製作一個收音機

川騷278發表於2020-12-27

參加2020年智慧車競賽的聲音信標組 奮戰了一個月 可惜並沒有獲得獎項,正巧該車的收發Chirp波的模組為RDA5807,閒暇之餘,參考了RDA5807的資料手冊,製作了一個通過STM32作為主控的RDA5807 收音機
rda5807.c

#include<stdio.h>
#include<sys.h>
#include<delay.h>
#include<RDA5807.h> 
#include<lcd.h>
u16 RXFreq=0;
u8  Vol=0;
u8  RDA_State=0;

//初始化I2C 
void rda5807_i2c_init(void)
{
	IIC_Init();
}


void RDA_ReadReg(u8 regAddr)
{
	 u16 buf;
    
    IIC_Start();
    IIC_Send_Byte(RDA_WRITE);//傳送晶片地址 方向為寫
    IIC_Wait_Ack();	
    IIC_Send_Byte(regAddr);//傳送暫存器地址
    IIC_Wait_Ack();		
    IIC_Start();
    IIC_Send_Byte(RDA_READ);//傳送晶片地址 方向為讀
    IIC_Wait_Ack();	
    buf = IIC_Read_Byte(1); 
    buf = buf<<8;
    buf =buf|IIC_Read_Byte(0); 
    IIC_Stop();
    return buf;
}
void RDA_WriteReg(u8 regAddr,u16 val)
{
	
    IIC_Start();
    IIC_Send_Byte(RDA_WRITE);	//傳送晶片地址 方向為寫
    IIC_Wait_Ack();	 
    IIC_Send_Byte(regAddr);	//傳送暫存器地址
    IIC_Wait_Ack();	 
    IIC_Send_Byte(val>>8);
    IIC_Wait_Ack();	
    IIC_Send_Byte(val&0xFF);
    IIC_Wait_Ack();	
    IIC_Stop();
}

void RDA_Vol(u8 vol)
{
    u16 temp=0;

    if(RDA_State==1)
    {  
        temp=RDA_ReadReg(RDA_R05);		
        temp&=0xfff0;				   
        RDA_WriteReg(RDA_R05,temp|vol);			
    }
}
//訊號強度獲取	0~127
u16 RDA_RSSI(void)
{
    u16 temp=0;

    if(RDA_State==1)
    {
        temp=RDA_ReadReg(RDA_R0B);		
        temp=(temp>>9)&0x7f;    
    }
    
    if(temp<30)
    {
        LED0=0;
        LED1=0;
    }
    else if(temp>=30 && temp<50)
    {
       LED0=0;
       LED1=1;
    }
    else if(temp>=50 && temp<70)
    {
        LED0=1;
        LED1=0;
    }
    else if(temp>=70)
    {
        LED0=1;
        LED1=1;
    }
    
    return temp;     
}


//搜臺方向 1向上搜尋 0向下搜尋
void RDA_Seek_Direction(u8 direction)
{
    u16 temp; 
    
    if(RDA_State==1)
    {
        temp=RDA_ReadReg(RDA_R02);        
        if(direction == 1)
            temp|= 1<<9;	//1<<9 => 1000000000		
        else
            temp&=~(1<<9);
        
        RDA_WriteReg(RDA_R02,temp);
    }
}

u16 RDA_Search_Freq(void)  
{
    u16 temp;

    temp=RDA_ReadReg(RDA_R02);		
    temp |= (1<<8);     
    RDA_WriteReg(RDA_R02,temp) ;		  //SEEK位置一  使能自動搜臺
    while((RDA_ReadReg(RDA_R0A)&(1<<14)) == 0)  // 等待STC位置一 表示搜尋完成
    {
        delay_ms(10);  //延時10ms    
    }
    temp = (RDA_ReadReg(RDA_R0A)&0x3FF) + 870 ;  //獲取當前頻率
    return temp;   //返回搜到電臺頻率 單位是:100Khz	 
}
//頻率設定 單位是:100KHz 87~108MHz
void RDA_Set_Freq(u16 freq)
{
    u16 temp=0,chan=0;    
        
    temp=RDA_ReadReg(RDA_R03);	
    temp&=0x3F;
    
    chan=freq-870;
       
    temp|=chan<<6;
    
    
    temp|=1<<4;
    RDA_WriteReg(RDA_R03,temp) ;	
    delay_ms(50);
    
    RDA_Freq_View(freq);
}
//1 使能晶片 0 禁用晶片
void RDA_Enable(void)
{
    u16 temp;
    
    temp=RDA_ReadReg(RDA_R02);

    if((temp&0x01)==0)
    {
        RDA_Init();
        RDA_State=1;
    }
    else
    {      
        RDA_WriteReg(RDA_R02,0);		
        
        RDA_State=0;
    }    
}
void RDA_Init(void)		  
{	
    RXFreq=998;
    Vol=2;
    RDA_State=1;

    RDA_WriteReg(RDA_R02,0x0002);        //軟體復位
    delay_ms(30);
    RDA_WriteReg(RDA_R02,0xd281);        //晶振選擇32.768Khz 向上搜尋 重低音 立體聲  SKMODE = 1搜尋到邊頻時停止 
    RDA_WriteReg(RDA_R03,0x0000);        //步進100Khz 頻帶為87M~108M	
    RDA_WriteReg(RDA_R04,0x0040);        //基本配置	
    RDA_WriteReg(RDA_R05,0x88A2);        //音量設定為vol=2 搜尋閥值為8      
    
    RDA_Set_Freq(RXFreq);
    RDA_SPK();
    LCD_Init();
} 

void RDA_Freq_Down(void)
{ 
    RXFreq-=1;	        //頻率減,步進100KHZ    
    if(RXFreq<870)     RXFreq=870;                           
    RDA_Set_Freq(RXFreq);	//頻率設定
}

void RDA_Freq_Up(void)
{
    RXFreq+=1;		//頻率加,步進100KHZ
    if(RXFreq>1080)    RXFreq=1080;
    RDA_Set_Freq(RXFreq);	//頻率設定    
}
//大
void RDA_Vol_Big(void)
{  
    if(Vol<15)
    {
        Vol++;		//音量加 
        RDA_Vol(Vol);   //音量設定   0~15    
    }
}

void RDA_Vol_Small(void)//下
{
    if(Vol>0)           //音量減 
    {
        Vol--;
        RDA_Vol(Vol);		   
    }
}
void RDA_Freq_View(u16 freq)
{
    u16 ge,shi,bai,xiao;  

    xiao=freq%10;
    ge=(freq%100)/10;
    shi=(freq%1000)/100;
    bai=freq/1000;

    LED0=!LED0;
     LCD_ShowNum(50,140,xiao,3,16);
     LCD_ShowNum(50,170,ge,3,16);	
	 LCD_ShowNum(50,200,shi,3,16);
     LCD_ShowNum(50,230,bai,3,16);	
    
    
}

//功放
void RDA_SPK(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB,PE埠時鐘
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB.5 埠配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推輓輸出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;		 //IO口速度為50MHz
 GPIO_Init(GPIOF, &GPIO_InitStructure);					 //根據設定引數初始化GPIOB.5
 GPIO_SetBits(GPIOF,GPIO_Pin_5);						 //PB.5 輸出高


}
//此處得加 標頭檔案 myiic.h gpio.h 以及延時函式的.h 以及LED.h 
 


 

RDA5807.h

#ifndef __RDA5807_H
#define __RDA5807_H
#include "myiic.h"   

#include "stm32f10x.h"

extern u16 RXFreq;
extern u8 Vol;
extern u8 RDA_State;
extern u16 add;

//#define SPK_PIN        GPIO_PIN_5
//#define SPK_PORT       GPIOF
//#define SPK_R GPIO_WriteReverse(SPK_PORT,SPK_PIN);

//RDA 的暫存器地址
#define RDA_R02		0X02  //DHIZ[15],DMUTE[14]靜音,MONO[13]聲道,BASS[12]重低音,SEEKUP[9],SEEK[8],SKMODE[7],CLK_MODE[6:4]時鐘源選擇,SOFTRESET[1]軟復位,ENABLE[0]電源使能
#define RDA_R03		0X03  //CHAN[15:6],TUNE[4],BAND[3:2],SPACE[1:0] 設定頻率 頻寬 步長
#define RDA_R04		0X04  //STCIEN[14],DE[11],I2Senable[6],
#define RDA_R05		0X05  //INT_MODE[15],SEEKTH[14:8](設定自動搜尋訊號強度閥值),LNA_PORT_SEL[7:6]=0b10,LNA_ICSEL_BIT[5:4],VOLUME[3:0]音量;
#define RDA_R0A		0X0A  //STC[14]seek complete SF[13]seek fail readchan[9:0]當前頻道
#define RDA_R0B		0X0B  //RSSI[15:9],FM TRUE[8]當前頻道是一個節目臺
#define RDA_R0E   0X0E
#define RDA_READ        0x23  //讀RDA5807
#define RDA_WRITE	0x22  //寫RDA5807

u16 RDA_ReadReg(u8 regAddr); 
void RDA_WriteReg(u8 regAddr,u16 val);
void RDA_Init(void);
void RDA_Enable(void);
u16  RDA_RSSI(void);
void RDA_Seek_Direction(u8 direction);
u16  RDA_Search_Freq(void);
void RDA_Set_Freq(u16 freq);
void RDA_Freq_Down(void);
void RDA_Freq_Up(void);
void RDA_Freq_View(u16 freq);
void RDA_Vol(u8 vol);
void RDA_Vol_Big(void);
void RDA_Vol_Small(void);
void RDA_SPK(void);

#endif

KEY.c

//按鍵初始化函式
void KEY_Init(void) //IO初始化
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOF,ENABLE);//使能PORTA,PORTF時鐘

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設定成上拉輸入GPIO_Mode_IN_FLOATING
 	GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIOE4,3

	//初始化 WK_UP-->GPIOA.0	  下拉輸入
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0設定成輸入,預設下拉	  
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0

}
//按鍵處理函式
//返回按鍵值
//mode:0,不支援連續按;1,支援連續按;
//0,沒有任何按鍵按下
//1,KEY0按下
//2,KEY1按下
//2,KEY2按下
//2,KEY3按下
//2,KEY4按下
//3,KEY5按下 WK_UP
//注意此函式有響應優先順序,KEY0>KEY1>KEY_UP!!
u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按鍵按鬆開標誌
	if(mode)key_up=1;  //支援連按		  
	if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==0||KEY4==0||WK_UP==1))
	{
		delay_ms(10);//去抖動 
		key_up=0;
		if(KEY0==0)return KEY0_PRES;
		else if(KEY1==0)return KEY1_PRES;
		else if(KEY2==0)return KEY2_PRES;
		else if(KEY3==0)return KEY3_PRES;
		else if(KEY4==0)return KEY4_PRES;
		else if(WK_UP==1)return WKUP_PRES;
	}else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1&&WK_UP==0)key_up=1; 	    
 	return 0;// 無按鍵按下
}


KEY.h

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"



//#define KEY0 PEin(0)   	//PF0
//#define KEY1 PEin(1)	//PF1
//#define KEY1 PEin(2)	//PF2
//#define KEY1 PEin(3)	//PF3
//#define KEY1 PEin(4)	//PF4
//#define WK_UP PAin(0)	//PA0  WK_UP

#define KEY0  GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_0)//讀取按鍵0
#define KEY1  GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_1)//讀取按鍵1
#define KEY2  GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_2)//讀取按鍵2
#define KEY3  GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_3)//讀取按鍵3
#define KEY4  GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_4)//讀取按鍵4
#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//讀取按鍵5(WK_UP) 

 

#define KEY0_PRES 	1	//KEY0按下
#define KEY1_PRES	2	//KEY1按下
#define KEY2_PRES	3	//KEY1按下
#define KEY3_PRES	4	//KEY1按下
#define KEY4_PRES	5	//KEY1按下
#define WKUP_PRES   6	//KEY_UP按下(即WK_UP/KEY_UP)


void KEY_Init(void);//IO初始化
u8 KEY_Scan(u8);  	//按鍵掃描函式					    
#endif

main.c

#include "stm32f10x.h"
#include "RDA5807.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "myiic.h"
#include "usart.h"
#include "delay.h"
#include "sys.h"
int main(void)
{    
    u16 time=0;
    vu8 key=0;		
		int bushu = 10;
		delay_init();	    	 //延時函式初始化	  
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設定中斷優先順序分組為組2:2位搶佔優先順序,2位響應優先順序
		uart_init(115200);	 	//串列埠初始化為115200
		LED_Init();
		LCD_Init();
		KEY_Init();
		IIC_Init();
		RDA_Init();
	 	POINT_COLOR=RED;//設定字型為紅色 
		while(1)
		{
 		key=KEY_Scan(0);	//得到鍵值
	   	if(key)
		{						   
			switch(key)
			{				 
				case KEY0_PRES:
					RDA_Seek_Direction(0);
           RXFreq=RDA_Search_Freq();
           RDA_Freq_View(RXFreq);
					break; 
				case KEY1_PRES:
					RDA_Seek_Direction(1);
           RXFreq=RDA_Search_Freq();
           RDA_Freq_View(RXFreq);
					break;
				//case KEY2_PRES;
					// RDA_Vol_Small();
				//	break;
				case WKUP_PRES:
					 RDA_Vol_Big(); 
					break;
				case KEY4_PRES:
					 RDA_Enable();
					break;
				case KEY3_PRES:
					 RDA_Freq_Down();
					break;
				case KEY2_PRES:
					RDA_Freq_Up();
					break;								
			}
		}else 
		delay_ms(10); 
		time++;
//		 LCD_ShowNum(50,230,time,3,16);
		 if(time>100)
      {
        time=0;     
//780 282 683			
        printf("頻率:%d\r\n",RXFreq);
        printf("訊號:%d\r\n",RDA_RSSI());
        printf("音量:%d\r\n",Vol); 
				printf("0x0E :%d\r\n",add);
        printf("\r\n"); 
      }
	}	 
			
			
			
			
     
    }







自己設定的按鍵數目較少,並且懶得折騰按鍵的識別方式
只採用按下識別,所以需要的按鍵特別多	


參考了 RDA5807程式設計指南,
做出來搞得很亂,採用的天線是粉刺針 ?在這裡插入圖片描述
通過按鍵控制 上下搜臺以及調頻收臺,最終通過耳機可以聽到廣播

相關文章