找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 16856|回复: 25
打印 上一主题 下一主题
收起左侧

单片机FM收音机制作 带源码与原理图 12864屏显示

  [复制链接]
跳转到指定楼层
楼主

单片机FM收音机的实物图:


单片机FM收音机的pcb图:


单片机FM收音机的原理图:



源程序:
  1. /*****************************************************************
  2.                                                         FM收音机
  3. 作者:Anyrain
  4. 版本:1.0
  5. 说明:
  6.                                                                  
  7.   K1--- 向上搜索电台 K2--- 向下搜索电台                          
  8.   K3--- 音量加       K4--- 音量减                                
  9.                                                                  
  10. *****************************************************************/

  11. #include <reg52.h>
  12. #include <intrins.h>
  13. #include"delay.h"
  14. #include "12864.h"
  15. #include "i2c.h"
  16. #include"ds1302.h"

  17. sbit  K1 = P3^0;
  18. sbit  K2 = P3^2;
  19. sbit  K3 = P3^1;

  20. sbit  K4 = P3^3;

  21. unsigned long frequency;
  22. unsigned char key,timekey,fmkey,mimiflag=0;
  23. unsigned int count,num;

  24. // RDA5807 寄存器初始值设定
  25. unsigned char  RDA_reg_data[8] =
  26. {
  27.    0xd0,0x00,  // 02H         1                1                0                1     XX 0                0         
  28.                                         //        正常操作无静音        立体声  重低音        下搜索        停止搜索
  29.                                         //        0                        000                XX        0                        0
  30.                                         //        自动搜台        32.768                 软件不复位        上电不使能
  31.    0x00,0x10,  // 03H         0000000000        CHAN[9:0]
  32.                                 //        Frequency=Spacing(KHz)*CHAN+BAND
  33.                                 //        0 0                 10                        00 SPACE
  34.                                 //        调谐关 76-108MHz        100KHz
  35.    0x44,0x40,  // 04H        X 0                                X0                                         0             X000
  36.                                         //          disable Seek/Tune Interrupt           去加重75us
  37.                                         //        1                00                          00            00
  38.                                         //        I2C使能        GPIO3高阻 GPIO2高阻 GPIO1高阻
  39.    0x88,0xA8,  // 05H        1                  0010000
  40.                         //        reg0CH读产生中断  seek threshold
  41.                         //        10                00                1000 VOLUME
  42.                         //        LANP        1.8mA        音量
  43. };

  44. /**************************************************************
  45. *********************连续写寄存器子函数************************/

  46. void RDA5807_write_reg(void)
  47. {
  48.    unsigned char i;
  49.    I2C_start();                                        // 收音模块写入操作                       
  50.    I2C_write_byte(0x20);                        // 寄存器连续写操作                                                       
  51.    for(i=0; i<8; i++)
  52.            {
  53.              I2C_write_byte(RDA_reg_data[i]);
  54.            }
  55.    I2C_stop();
  56. }

  57. /**********************************************************
  58. *******************连续读寄存器子函数*********************/

  59. void RDA5807_read_reg(unsigned char *reg_buf)
  60. {
  61.            I2C_start();                                        // 收音模块读取操作   
  62.            I2C_write_byte(0x21);                         // 寄存器连续读操作   
  63.            reg_buf[0] = I2C_read_byte(I2C_ACK);
  64.            reg_buf[1] = I2C_read_byte(I2C_ACK);
  65.            reg_buf[2] = I2C_read_byte(I2C_ACK);
  66.            reg_buf[3] = I2C_read_byte(I2C_NACK);
  67.         I2C_stop();
  68. }

  69. /**********************************************************
  70. ******************模块上电初始化子函数********************/

  71. void RDA5807_power(void)
  72. {
  73.    delayms(50);                                     // 发送软件复位指令,软件复位
  74.    RDA_reg_data[0] = 0x00;
  75.    RDA_reg_data[1] = 0x02;
  76.    RDA5807_write_reg();                         //写指令
  77.    delayms(10);                                            
  78.    RDA_reg_data[0] = 0xd2;                 // 收音模块默认参数,上电使能
  79.    RDA_reg_data[1] = 0x01;
  80.    RDA5807_write_reg();                         //写指令
  81. }

  82. /**********************************************************
  83. ******************FM信号显示子函数********************

  84. void NowSignal()
  85. {
  86.         unsigned char sin;
  87.         unsigned char  reg_data1[4] = {0x00, 0x00, 0x00, 0x00};        //接收寄存初始化
  88.         RDA5807_read_reg(reg_data1);
  89.         delayms(20);
  90.         sin=(reg_data1[2]>>1)&0x7f;
  91.         WriteCommand(0x80);
  92.         if(sin<16)
  93.                 ShowChar(0x0,1);
  94.         else if(sin<32)
  95.                    ShowChar(0x0,2);
  96.         else if(sin<48)
  97.                 ShowChar(0x0,3);
  98.         else
  99.                 ShowChar(0x0,4);
  100. }

  101. **********************************************************
  102. ********************收音模块自动寻台子函数****************/

  103. void RDA5807_FM_seek(void)
  104. {
  105.            unsigned int chan;
  106.            unsigned char  reg_data[4] = {0x00, 0x00, 0x00, 0x00}; //接收寄存初始化
  107.           RDA_reg_data[3] &=~(1 << 4) ;                      //调谐禁用          
  108.            RDA_reg_data[0] |=  (1 << 0);                      //SEEK位置1 内部自动寻台使能
  109.            RDA5807_write_reg();

  110.            while(0 == (reg_data[0]&0x40))                           // 读寄存器直到SF 标志置0,自动搜台结束
  111.            {
  112.              delayms(35);
  113.              RDA5807_read_reg(reg_data);                        // 读取内部状态
  114.            }
  115.         // 获取当前工作频点
  116.            chan = reg_data[0] & 0x03;                                 //READCHAN[9:8]
  117.            chan = reg_data[1] | (chan << 8);                //READCHAN[9:0]
  118.           chan = chan << 6;                                                  //READCHAN[15:6]
  119.                                                                        
  120.         // 保存当前工作频点
  121.            RDA_reg_data[2] = (chan >> 8) & 0xff;        //chan高八位送03H[15:8]

  122.            RDA_reg_data[3] = (chan & 0xff);                //低位送03H[7:6]

  123. }

  124. /**********************************************************
  125. *********************频率显示子函数************************/

  126. void  show_frequency(void)
  127. {
  128.            unsigned int display[5];
  129.         unsigned int temp,i;

  130.            temp = (RDA_reg_data[2]*256)+(RDA_reg_data[3]&0xc0);                 //xxxx xxxx oo00 0000
  131.            temp = temp>>6;                                                                                        //0000 00xx xxxx xxoo
  132.            frequency = (unsigned long)(100*temp+87000)/100;             //M/10
  133.        
  134.            display[0] = (frequency)/1000 ;                                             //百M最高位
  135.            display[1] = (frequency%1000)/100;                                          //十M位
  136.            display[2] = (frequency%100)/10;                                                           //个M位
  137.            display[3] = 10;                                                                  //小数点'.'
  138.            display[4] = (frequency%10);                                                           //ABC.X

  139.            if(display[0] == 0)
  140.            {
  141.              display[0] = display[1];
  142.              display[1] = display[2];
  143.              display[2] = display[3];
  144.              display[3] = display[4];
  145.              display[4] = 18;                                                                          //' '空格
  146.            }
  147.            for(i=0;i<5;i++)
  148.            Displayen(1,6,24+8*i,display[i])        ;                                         //频率显示
  149. }

  150. /**********************************************************
  151. *********************音量显示子函数***********************/

  152. void show_volume()
  153. {
  154.            unsigned char temp,display0[2],i;

  155.            temp = RDA_reg_data[7] & 0x0f;                 //取音量值min0-max15
  156.     display0[0] = temp/10;
  157.            display0[1] = temp%10;
  158.            if(display0[0] == 0)                    //如果高位为0
  159.            {
  160.              display0[0] = display0[1];             //低位显存内容进入高位显存
  161.              display0[1] = 18;                   //低位不显示
  162.            }
  163.           
  164.         for(i=0;i<2;i++)
  165.            Displayen(2,6,48+8*i,display0[i])        ;   //音量值显示
  166. }

  167. /**********************************************************
  168. *********************按键扫描子函数***********************/

  169. void scan()
  170. {
  171.          unsigned char keyx;                                         //用来保存短按的值
  172.          P3=0xff;
  173.          if(!K1)
  174.      {
  175.        delayms(20);
  176.               while(!K1)
  177.                {
  178.                            TR0=1;                                                  //启动定时器
  179.                            if(!timekey)
  180.                                 {
  181.                                         if(!fmkey)
  182.                                                 keyx=1;                                        //进入1状态
  183.                                 }
  184.                         else        keyx=5;
  185.                         while(!K1);                                                //长按时间未到,频道增加
  186.                 }
  187.                         if(count<15)
  188.                                 {
  189.                                         key=keyx;
  190.                                         TR0=0;                                        //关中断 count清零
  191.                                         count=0;       
  192.                                 }
  193.                         else                                                        //长按则进入设置
  194.                                 {       
  195.                                           key=4;                                        //进入4状态
  196.                                          timekey=~timekey;                //timekey=1,设置时间。0正常时钟
  197.                                         count=0;
  198.                                         TR0=0;                                  //停止定时器
  199.                                 }
  200.             
  201.      }
  202.          if(!K2)
  203.      {
  204.        delayms(20);
  205.               while(!K2)
  206.                {
  207.                            TR0=1;                                                  //启动定时器
  208.                            if(!fmkey)                                                //短按处理
  209.                         {
  210.                                 if(timekey)
  211.                                         keyx=6;                                                //进入6状态 设置+
  212.                                 else
  213.                                 keyx=2;                                                //进入2状态 音量加
  214.                         }
  215.                         else
  216.                         {
  217.                                  if(timekey)
  218.                                         keyx=6;                                                //进入6状态 设置+
  219.                         }
  220.                                                   
  221.                         while(!K2);                                                //长按时间未到
  222.                        
  223.                 }

  224.                 if(count<15)
  225.                         {
  226.                                 key=keyx;
  227.                                 TR0=0;                                        //关中断 count清零
  228.                                 count=0;       
  229.                         }
  230.                 else                                                        //长按则进入fm设置
  231.                         {       
  232.                                 key=8;
  233.                                 fmkey=~fmkey;                        //fmkey=1关FM,0开FM       
  234.                                 count=0;
  235.                                 TR0=0;                                  //停止定时器
  236.                         }
  237.               
  238.             
  239.      }

  240.      if(K3 == 0)
  241.      {
  242.        delayms(20);
  243.        while(K3 == 0)
  244.        {        TR0=1;
  245.                  if(!fmkey)
  246.                          {
  247.                            if(timekey)
  248.                                 keyx=7;                                                //进入7状态 设置-
  249.                         else
  250.                            keyx=3;                                                //进入3状态 音量减
  251.                         }
  252.                 else
  253.                    {
  254.                            if(timekey)
  255.                                 keyx=7;                                                //进入7状态 设置-
  256.                    }
  257.                            while(K3 == 0);

  258.        }
  259.            if(count<15)
  260.                         {
  261.                                 key=keyx;
  262.                                 TR0=0;                                        //关中断 count清零
  263.                                 count=0;       
  264.                         }
  265.                 else                                                        //长按则背光点亮
  266.                         {       
  267.                                 mimiflag=~mimiflag;       
  268.                                 count=0;
  269.                                 TR0=0;                                  //停止定时器
  270.                                
  271.                         }
  272.      }

  273.    

  274.          if(!K4)
  275.      {
  276.        delayms(20);
  277.               while(!K4)
  278.                {
  279.                            TR0=1;                                                  //启动定时器       
  280.                         keyx=5;
  281.                         while(!K4);                                                //长按时间未到,频道增加
  282.                 }
  283.                         if(count<15)
  284.                                 {
  285.                                         key=keyx;
  286.                                         TR0=0;                                        //关中断 count清零
  287.                                         count=0;       
  288.                                 }
  289.                         else                                                        //长按则进入设置

  290.                                 {       
  291.                                           key=4;                                        //进入4状态
  292.                                          timekey=~timekey;                //timekey=1,设置时间, timekey=0正常时钟.
  293.                                         count=0;
  294.                                         TR0=0;                                  //停止定时器
  295.                                 }
  296.             
  297.      }
  298. }

  299. /**********************************************************
  300. ************************主函数***************************/

  301. void  main(void)
  302. {  

  303.         unsigned char i,j,flag,onedone,flash=15;        //闪烁标志的位置
  304.            TMOD=0X11;                                        //设置定时器0、1为工作方式1
  305.            TH0=0xb1;                                        //延时50ms
  306.            TL0=0Xe0;
  307.            EA=1;                                           //开总中断
  308.            ET0=1;                                          //开定时中断
  309.            ET1=1;
  310.            TR1=1;
  311.            InitLCD();                                        //lcd初始化
  312.         initdisplay();
  313.         Init_DS1302();                       //将1302初始化
  314.            Displaytime();                                 //初始化显示时间
  315.            RDA5807_power();                                //收音机模块上电
  316.            show_frequency();                        //显示收音机频率
  317.            show_volume();                                   //显示声音

  318.    while(1)
  319.    {
  320.    scan();
复制代码



完整源程序下载:
单片机FM收音机资料.rar (359.18 KB, 下载次数: 351)

评分

参与人数 1黑币 +5 收起 理由
zhaok2013 + 5 很给力!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏23 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:73762 发表于 2017-3-6 22:00 | 只看该作者
这个不错哦,学习
回复

使用道具 举报

板凳
ID:151348 发表于 2017-3-7 08:57 | 只看该作者
这个不错,不但充分利用的单片机IO口,还提供了丰富的外设,相比于一些“最小系统”,高了几个档次
回复

使用道具 举报

地板
ID:102293 发表于 2017-5-13 21:15 | 只看该作者
学习了,谢谢分享!
回复

使用道具 举报

5#
ID:420310 发表于 2018-11-3 23:18 | 只看该作者
学习了,谢谢分享!
回复

使用道具 举报

6#
ID:448822 发表于 2019-2-9 16:15 | 只看该作者
这个不错哦,学习
回复

使用道具 举报

7#
ID:475582 发表于 2019-2-10 19:55 | 只看该作者
很给力
回复

使用道具 举报

8#
ID:475864 发表于 2019-2-12 11:48 | 只看该作者
这个不错哦,学习
回复

使用道具 举报

9#
ID:175749 发表于 2019-4-20 10:02 | 只看该作者
很不错的资料,谢谢楼主
回复

使用道具 举报

10#
ID:317472 发表于 2019-4-21 23:13 | 只看该作者
功能很完善了
回复

使用道具 举报

11#
ID:353831 发表于 2020-1-23 23:17 来自手机 | 只看该作者
楼主你好,1602可以正常显示吗?
回复

使用道具 举报

12#
ID:88256 发表于 2020-1-23 23:55 | 只看该作者
下载一个参考一下,谢谢了!
回复

使用道具 举报

13#
ID:614068 发表于 2020-2-12 10:22 | 只看该作者
下载下来学习一下,谢谢楼主的无私分享
回复

使用道具 举报

14#
ID:704585 发表于 2020-4-12 14:50 | 只看该作者
多谢楼主分享
回复

使用道具 举报

15#
ID:582209 发表于 2020-6-9 12:11 来自手机 | 只看该作者
强啊楼主有pcb吗?
回复

使用道具 举报

16#
ID:462267 发表于 2020-6-23 06:51 | 只看该作者
垃圾,只有个图片
回复

使用道具 举报

17#
ID:771738 发表于 2020-6-27 20:00 | 只看该作者
很不错的资料,谢谢楼主分享!
回复

使用道具 举报

18#
ID:795562 发表于 2020-7-23 21:56 | 只看该作者
收藏备用,谢谢呢
回复

使用道具 举报

19#
ID:666182 发表于 2020-7-24 20:52 | 只看该作者
功能就只有一个吗  只能收听吗
回复

使用道具 举报

20#
ID:666182 发表于 2020-7-24 20:54 | 只看该作者
功能只有一个吗   只能听吗
回复

使用道具 举报

21#
ID:823031 发表于 2020-9-25 09:05 | 只看该作者
能实现正常工作,结收也很稳定,感谢
回复

使用道具 举报

22#
ID:823031 发表于 2020-9-25 09:06 | 只看该作者
功能很完美,能接收稳定信号,感谢分享
回复

使用道具 举报

23#
ID:517951 发表于 2020-11-15 17:46 | 只看该作者
不错,值得学习。51hei有你更精彩!!
回复

使用道具 举报

24#
ID:641660 发表于 2020-12-6 14:34 | 只看该作者
本帖最后由 zcjwp520 于 2020-12-6 14:36 编辑

努力学习大神的技术,想搞一个单片机控制蓝牙,收音机,多路Line输入的前级,带遥控,遥控可以切换音频输入,蓝牙播放上一曲下一曲,暂停,播放,可以控制收音机收台,总音量调整,低音高音调节等。要求1602显示,不知道大神有没有好的推荐,先谢谢了。
回复

使用道具 举报

25#
ID:972895 发表于 2022-5-13 06:40 | 只看该作者
这个相当不错,正想把原来的数码管改为12864,谢谢分享!
回复

使用道具 举报

26#
ID:325985 发表于 2022-5-13 19:59 | 只看该作者
用液晶代替LED数码管要省好多电哦。挺好。学习。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表