本帖最后由 gaoyang9992006 于 2023-11-15 17:58 编辑
#申请原创# @21小跑堂
收音机作为90年之前出生的人来讲是一种放不下的情怀,儿时家里穷,没电视,收音机是唯一获取世界信息与高端娱乐的家用电器,就跟另外一件家电手电筒一样的重要地位。
今年世界战乱不断,很担心发生第三次世界大战,于是决定做一台收音机。这也是我第一次尝试做基于现代数字芯片的收音机。上学时候做过传统的模拟收音机。
那么开始讲述这台收音机怎么做的吧。
https://bbs.21ic.com/icview-3336534-1-1.html
这是我开始这项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语言的,正在调试修改中。
|
设计十分精巧的收音机,小巧且精致,功能比较完善,很不错的DIY项目。上传源码可获得更高的打赏哦~