在論壇上看到有人發這個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自動搜索,音量控制,頻率設定,紅外遙控。