首页 > 代码库 > si4745 FM-AM-SW 音量控制芯片 驱动详解

si4745 FM-AM-SW 音量控制芯片 驱动详解

在论坛上看到有人发这个dsp 芯片,仔细看了下,发现功能正合我意,网上能找到的资料(源码)不多

软件环境:linux4.1.36  arm-linux-gcc 4.3.2

实现功能:自动搜台,上一台, 下一台, 音量大小控制,保存设置到文件,断电开机后自动恢复,之前收音状态。

首先是接线

技术分享

 

2440 开发板,mitsumi 车机收音芯片 si4745 ,这里加了一个 PAM8403 ,基本可以算是一个产品了。

先把 si4745 焊接在万能板上,加上排针,方便连线。

 

技术分享

这里i2c , 接在 camera 排针上。

RST 复位接在 EINT20 上,后面要配置成 输出引脚。

PAM8403 功放接线:camera 下面有个 GND ,  5V 来自左侧的排针上。

SI4745: 从3个串口上取3.3v GND 接到。

最后把天线接到 万用表上,基本接线就弄好了。

si4745 模块引线图

技术分享

 

准备工作:阅读 datasheet 确认参数

1, 确定 i2c 器件地址

技术分享

写:0x22 读: 0x23 ,因为在 linux 驱动中只写前7位,所以驱动中要写 0x22>>1 就是 0x11

2, 将控制命令写到 define 中

 技术分享

全部整理出来了,写成一个头文件

SI4745主驱动

1, 电源打开

技术分享

技术分享

技术分享

需要发送3个Byte

0x01  //电源打开

0xd0  //bit 7 bit6 需要设为1 启用 GPO2 CTS bit4 需要设为1 因为使用的是32.768 晶振 bit 3~1 设为0 是 FM 接收模式 :1<<6 | 1<<7 | 1<<4

0x05  //启用模拟声音输出

2, 设置去加重

技术分享

因为FM 在传输过程中,高频成分衰减比较大,所以在发射时要预加重,所以接收时还要去加重。(分离元件FM收音机中还有去加重电容)

这里需要设为 01 50us

请注意,这是一个 Property 属性,下面是发送命令详解

技术分享

0x12 SET_PROPERTY设置属性

技术分享

发送命令

CMD 0x12  //设置命令

ARG1 0x0   //写0

ARG2         //属性名的高8位 去加重是 0x1100 这里写 0x11

ARG3         //属性名的低8位 这里写 0x0

ARG4         //属性值的高8位  去加重属性值是 0x01 50us 高8位是 0x0

ARG5         //属性值的低8位  属性值低8位是 0x01

整理发送命令依次是

0x12

0x0

0x11

0x0

0x0

0x01

3, FM自动搜台

技术分享

命令

0x21

0x8  向上搜,搜到108 后停止

4, FM 搜台状态检查

技术分享

命令

0x22

0x1  清除搜到台的中断位

5, 设置频率

0x20 FM_TUNE_FREQ

6, 设定音量大小

0x4000 RX_VOLUME

好了,基本能用了。

控制源码:

这次因为,at24cxx 麻烦不好接,就直接保存到文件中了。

 

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <sys/mman.h>
  7 
  8 //author: ningci date:2017-04-03 15:55
  9 
 10 //io ctrl 命令
 11 #define IOCTL_CMD_RESET      101
 12 #define IOCTL_CMD_POWER_ON   102
 13 #define IOCTL_CMD_POWER_OFF  103
 14 #define IOCTL_CMD_FM_MODE    104
 15 #define IOCTL_CMD_AM_MODE    105
 16 #define IOCTL_CMD_MUTE       106
 17 #define IOCTL_CMD_VOL        107
 18 #define IOCTL_CMD_FM_TUNE    108
 19 #define IOCTL_CMD_AM_TUNE    109
 20 #define IOCTL_CMD_FM_SERACH  110
 21 #define IOCTL_CMD_AM_SERACH  111
 22 
 23 #define BAROD_BUF_SIZE (1024*1024)
 24 int si47xx_fd, barod_fd;
 25 //保存配置信息和频道信息
 26 unsigned char  *barod_buf;
 27 //频道信息
 28 unsigned short *barod_ch;
 29 
 30 //配置信息
 31 struct si47xx_cfg{
 32     int max_ch;
 33     int ch;
 34     int vol;
 35 };
 36 
 37 struct si47xx_cfg *cfg;
 38 
 39 void welcome()
 40 {
 41     printf("/////////////////////////////////////////\n");
 42     printf("/ Power By: Ning Ci                     /\n");
 43     printf("/ Press key ‘s‘ To Auto Serach All Band /\n");
 44     printf("/ Press key ‘m‘ To Redio Mute           /\n");
 45     printf("/ Press key ‘p‘ To Set Redio Prev CH    /\n");
 46     printf("/ Press key ‘n‘ To Set Redio Next CH    /\n");
 47     printf("/ Press key ‘q‘ To Quit Close Radio     /\n");
 48     printf("/////////////////////////////////////////\n");
 49 }
 50 
 51 void fm_mode()
 52 {
 53     ioctl(si47xx_fd, IOCTL_CMD_FM_MODE, 0);
 54 }
 55 
 56 void fm_tune(int frequency)
 57 {
 58     ioctl(si47xx_fd, IOCTL_CMD_FM_TUNE, frequency);
 59 }
 60 
 61 //最大值是63
 62 void set_vol(int vol)
 63 {
 64     ioctl(si47xx_fd, IOCTL_CMD_VOL, vol);
 65 }
 66 
 67 void set_ch(int ch)
 68 {
 69     fm_tune(barod_ch[ch]);
 70         
 71     //读取电台信息显示给用户
 72     printf("ch: %d %.1f Mhz \n", ch, barod_ch[ch]/100.0);
 73 }
 74 
 75 void serach()
 76 {
 77     int frequency;
 78     //设定开始搜索频率
 79     fm_tune(8800);
 80     //配置信息最大频道清0
 81     cfg->max_ch = 0;
 82     while(1)
 83     {
 84         frequency = ioctl(si47xx_fd, IOCTL_CMD_FM_SERACH, 0);
 85         if(0 < frequency)
 86         {
 87             printf("serach: %.1f Mhz\n", frequency/100.0);
 88             //保存频率信息
 89             barod_ch[cfg->max_ch] = frequency;
 90             cfg->max_ch++;
 91         }
 92         else
 93         {
 94             break;
 95         }
 96     }
 97     printf("serach done find %d radio\n", cfg->max_ch);
 98 }
 99 
100 void mute()
101 {
102     static int is_mute=0;
103     ioctl(si47xx_fd, IOCTL_CMD_MUTE, is_mute%2);
104     is_mute++;
105 }
106 
107 //测试用
108 void test()
109 {
110     fm_mode();
111     fm_tune(9960);
112     set_vol(30);
113 }
114 
115 int main(int argc, char **argv)
116 {
117     //控制命令
118     char cmd;
119 
120     struct stat barod_stat;
121     
122     //打印使用信息
123     welcome();
124 
125     //打开设备
126     si47xx_fd = open("/dev/si47xx", O_RDWR);
127     if(0 > si47xx_fd)
128     {
129         printf("cat‘t open si47xx \n");
130         return 0;
131     }
132 
133     //打开或创建一个保存频率的文件
134     barod_fd = open("./barod_info.txt", O_RDWR | O_CREAT, 0777);
135 
136     //如果文件大小为0就填充
137     if(-1 == fstat(barod_fd, &barod_stat))
138     {
139         printf("get barod_info stat err\n");
140         return 0;
141     }
142     if(0 == barod_stat.st_size)
143     {
144         ftruncate(barod_fd, BAROD_BUF_SIZE+1024);
145     }
146     
147     barod_buf = mmap(NULL, BAROD_BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, barod_fd, 0);
148     if(barod_buf == MAP_FAILED)
149     {
150         printf("cat‘t mmap barod_buf \n");
151         return 0;
152     }
153 
154     //barod_buf = malloc(BAROD_BUF_SIZE);
155     
156     
157     //读取配置信息
158     cfg = (struct si47xx_cfg *)barod_buf;
159     
160     //读取频道配置信息
161     barod_ch = (unsigned short *)(barod_buf + sizeof(struct si47xx_cfg));
162     
163     if(0 == barod_stat.st_size)
164     {
165         memset(barod_buf, 0, BAROD_BUF_SIZE);
166         cfg->ch  = 0;
167         cfg->vol = 35;
168     }
169     
170     //初始化FM模式
171     fm_mode();
172     mute();
173 
174     //读取保存的电台
175     set_ch(cfg->ch);
176     set_vol(cfg->vol);
177 
178     while(q != (cmd = getchar()))
179     {
180         switch(cmd)
181         {
182             case t: test();              break;
183             case s: serach();            break;
184             case +: set_vol(cfg->vol+=5); break;
185             case -: set_vol(cfg->vol-=5); break;
186             case m: mute();               break;
187             case p: set_ch(--cfg->ch);    break;
188             case n: set_ch(++cfg->ch);    break;
189             case h: welcome();            break;
190         }
191     }
192 
193     munmap(barod_buf, BAROD_BUF_SIZE);
194     close(si47xx_fd);
195     close(barod_fd);
196     return 0;
197 }

 

 

 

完整片源码地址:https://github.com/nejidev/si47xx_radio_linux

实现了,FM/AM/SW自动搜索,音量控制,频率设定,红外遥控。

 

si4745 FM-AM-SW 音量控制芯片 驱动详解