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自動搜索,音量控制,頻率設定,紅外遙控。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM