在论坛上看到有人发这个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自动搜索,音量控制,频率设定,红外遥控。