[RISC-V MCU 应用开发]基于ESP32层+RDA5807的高灵敏数字选台FM收音机

收音机作为90年之前出生的人来讲是一种放不下的情怀,儿时家里穷,没电视,收音机是唯一获取世界信息与高端娱乐的家用电器,就跟另外一件家电手电筒一样的重要地位。
今年世界战乱不断,很担心发生第三次世界大战,于是决定做一台收音机。这也是我第一次尝试做基于现代数字芯片的收音机。上学时候做过传统的模拟收音机。
那么开始讲述这台收音机怎么做的吧。

RDA5807做了一个DIY收音机,可以收到17个电台 - DIY 讨论区 - 21ic电子技术开发论坛
这是我开始这项DIY项目时候的第一个贴
原理图如下所示


采用LCD显示内容,通过一个旋转编码器进行选台和调节
 


由于本人是左撇子,所以旋钮放在左边了。
 


背后预留了BK1088E模块的接口,用于调试下一个项目全波段收音机。
上实物图


第一行显示FM,频率值,音量+声道(色块长度表示音量,色块双绿色条表示立体声,如果是单声道就显示一整块黄色音量条)
第二行显示信号强度
第三行显示当前模式:模式0表示正常模式,此时滚动轮子切换电台(自动搜索下一个电台),如果按一下滚轮进入模式+1,模式1为音量调节,模式2为手动选台。
第四行为频率刻度,第五行为大的数码管字体的当前频率。
通过以下函数实现基础UI的绘制

复制

void UI_Init(void)

{

  tft.initR(INITR_BLACKTAB);  //初始化屏幕

  tft.fillScreen(Display_Backround_Color);

  tft.setFont();//初始化字体

  tft.setTextColor(Display_Text_Color);

//绘制刻度线

  tft.drawFastHLine(0, 65, tft.width(), ST77XX_RED);

  for(uint8_t x=4;x<128;x=x+12)

  {

    tft.drawFastVLine(x, 65, 5, ST77XX_BLUE);

  }



//  tft.drawFastVLine(4+(((rx.getFrequency()/100.0)-76.0)*(120.0/(108-76))), 60, 5, ST77XX_GREEN);

  tft.drawFastVLine(4+(((nowFre.toFloat())-76.0)*(120.0/(108-76))), 60, 5, ST77XX_GREEN);



  tft.setCursor(0, 72);

  tft.print("76");

  tft.setCursor(110, 72);

  tft.print("108");





  //绘制线框,用于显示频率

  tft.drawRect(0,0,tft.width(),15,ST77XX_GREEN);

  tft.drawRect(2,2,18,11,ST77XX_BLUE);

  tft.drawRect(25,2,64,11,ST77XX_BLUE);



  tft.setTextSize(1);

  tft.setCursor(5, 4);

  tft.print("FM");

  tft.setCursor(28, 4);

  tft.print(nowFre);

  tft.setCursor(68, 4);

  tft.print("MHz");



  //绘制线框,用于显示信号强度

  tft.drawRect(0,20,tft.width(),15,ST77XX_GREEN);

  tft.drawRect(2,22,28,11,ST77XX_BLUE);

  tft.drawRect(67,22,58,11,ST77XX_BLUE);



  tft.setTextSize(1);

  tft.setCursor(5, 22+2);

  tft.print("RSSI");

  tft.setCursor(70, 24);

  tft.print(nowRssi);

  tft.setCursor(100, 24);

  tft.print("dbUv");

//设置模式显示位置

  tft.setTextSize(2);

  tft.setCursor(10, 40);

  tft.print("MODE : 0");

//测试数码管字体

  tft.setFont(&digital_718pt7b);

  tft.setTextSize(1); 

  tft.setCursor(5, 120);

  tft.print(nowFre);

  tft.setFont();//恢复默认字体

}

以下是更新频率显示盒更新信号强度的方法

复制

void update_Fre(void)

{

  //更新频率显示

  tft.setTextSize(1);

  tft.setTextColor(Display_Backround_Color);

  tft.setCursor(28, 4);

  tft.print(nowFre);

  tft.drawFastVLine(4+(((nowFre.toFloat())-76.0)*(120.0/(108-76))), 60, 5, Display_Backround_Color);//清理吊当前的频率指示针

  //测试数码管字体

  tft.setFont(&digital_718pt7b);

  tft.setTextSize(1); 

  tft.setCursor(5, 120);

  tft.print(nowFre);



  tft.setFont();//恢复默认字体,更新频率显示

  tft.setTextColor(Display_Text_Color);

  tft.setCursor(28, 4);

  nowFre = String(rx.getFrequency()/100.0); 

  tft.print(nowFre);

  tft.drawFastVLine(4+(((nowFre.toFloat())-76.0)*(120.0/(108-76))), 60, 5, ST77XX_GREEN);//显示新的频率指示针

  //测试数码管字体

  tft.setFont(&digital_718pt7b);

  tft.setTextColor(ST77XX_YELLOW);

  tft.setCursor(5, 120);

  tft.print(nowFre);

  tft.setFont();//恢复默认字体

}



void update_Rss(void)

{

  //更新信号强度显示

  tft.setTextSize(1);

  tft.setTextColor(Display_Backround_Color);

  tft.setCursor(70, 24);

  tft.print(nowRssi);

  tft.setTextColor(Display_Text_Color);

  tft.setCursor(70, 24);

  nowRssi = String(rx.getRssi());

  tft.print(nowRssi); 



//如果是立体声就绘制一个绿色矩形,如果是单声道就绘制一个黄色矩形,矩形的长度表示音量,

  if(rx.isStereo())

  {

    tft.fillRect(90,5,35,5,Display_Backround_Color);

    tft.fillRect(90,5,2+(rx.getVolume()*2),5,ST77XX_GREEN);

    tft.fillRect(90,7,35,1,Display_Backround_Color);//立体声改成双条线

  }

  else

  {

    tft.fillRect(90,5,35,5,Display_Backround_Color);

    tft.fillRect(90,5,2+(rx.getVolume()*2),5,ST77XX_YELLOW);

  }

}

处理编码滚轮的滚动与按键的方法

复制

  if(R_Encoder_Active !=0)

  {

    if(R_Encoder_Active ==1)

    {

      switch (radio_mode)

      {

        case 0: rx.seek(RDA_SEEK_WRAP, RDA_SEEK_UP, showStatus); break;

        case 1: rx.setVolumeUp();                                break;

        case 2: rx.setFrequencyUp();                             break;

        default:break;

      }

       

    } 

    else

    {

      switch (radio_mode)

      {

        case 0: rx.seek(RDA_SEEK_WRAP, RDA_SEEK_DOWN, showStatus); break;

        case 1: rx.setVolumeDown();                                break;

        case 2: rx.setFrequencyDown();                             break;

        default:break;

      }

    }

    R_Encoder_Active =0;

    delay(100);

    update_Fre();

    update_Rss();

  }

  if(Button_Active == 1)

  {

    radio_mode++;

    Button_Active = 0;

    if(radio_mode>5) radio_mode = 0;

    tft.fillRect(80,40,32,14,Display_Backround_Color);

    tft.setTextSize(2);

    tft.setCursor(90,40);

    tft.print(String(radio_mode));

    delay(100);

    update_Fre();

    update_Rss();

  }

主程序初始化方法

复制

  EC11_Init();



  Wire.begin();  // 初始化I2C总线,用于RDA5807通信

  rx.setup();

  rx.setVolume(2);

  rx.setLnaPortSel(3);

  rx.setFrequency(9750); // It is the frequency you want to select in MHz multiplied by 100.

  delay(250);

  rx.setAFC(true);    // Sets Automatic Frequency Control

  UI_Init();


经过实测,该芯片灵敏度非常高,在南京地区户外可以搜到将近30个电台,在写字楼内可以搜到17个电台。
部分电台频率可以看开头那连接的帖子内容。

附加:该芯片收音机的灵敏度跟天线电路关系很大,只有信号输入可靠才能解调出较多清晰的电台。
如果直接一根导线接入,很难收到较好的效果,这也是上一个贴有人说信号强度不够的原因。
以下天线滤波电路是手册给出的。


上图是RDA5807MP封装推荐的,下图是RDA5807M推荐的滤波电路。


另外可以通过仿真软件对天线滤波电路的传输特性进行仿真计算,实际上还要根据自己布线的情况进行参数调整以达到最佳。
下面是对应帖子版本的工程代码包
 

 ST7735_RDA5807.zip (21.59 KB)
下面是另外一个版本的,还是调试修改中,从RDA5807换成了全波段的BK1088E,目前在编写通用的驱动函数中。利用网上开源的已经没问题了,想写一个属于自己的驱动函数,基于C语言的,正在调试修改中。


---------------------
作者:gaoyang9992006
链接:https://bbs.21ic.com/icview-3339954-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值