zoukankan      html  css  js  c++  java
  • 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("/////////////////////////////////////////
    ");
     42     printf("/ Power By: Ning Ci                     /
    ");
     43     printf("/ Press key 's' To Auto Serach All Band /
    ");
     44     printf("/ Press key 'm' To Redio Mute           /
    ");
     45     printf("/ Press key 'p' To Set Redio Prev CH    /
    ");
     46     printf("/ Press key 'n' To Set Redio Next CH    /
    ");
     47     printf("/ Press key 'q' To Quit Close Radio     /
    ");
     48     printf("/////////////////////////////////////////
    ");
     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 
    ", 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
    ", 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
    ", 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 
    ");
    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
    ");
    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 
    ");
    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自动搜索,音量控制,频率设定,红外遥控。

  • 相关阅读:
    【STM32F429】第1章 当前主流的小型嵌入式GUI
    【STM32H7】第14章 UDP用户数据报协议基础知识
    【STM32F429】第14章 UDP用户数据报协议基础知识
    【STM32F407】第14章 UDP用户数据报协议基础知识
    【STM32H7】第13章 RL-TCPnet V7.X之创建多个TCP客户端
    【STM32F429】第13章 RL-TCPnet V7.X之创建多个TCP客户端
    【STM32F407】第13章 RL-TCPnet V7.X之创建多个TCP客户端
    【STM32H7】第12章 RL-TCPnet V7.X之TCP客户端
    【STM32F429】第12章 RL-TCPnet V7.X之TCP客户端
    迄今最强综合Demo,H7-TOOL的RTX5全家桶版本整体设计框架
  • 原文地址:https://www.cnblogs.com/ningci/p/6659104.html
Copyright © 2011-2022 走看看