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 麻烦不好接,就直接保存到文件中了。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h> //author: ningci date:2017-04-03 15:55 //io ctrl 命令
#define IOCTL_CMD_RESET 101
#define IOCTL_CMD_POWER_ON 102
#define IOCTL_CMD_POWER_OFF 103
#define IOCTL_CMD_FM_MODE 104
#define IOCTL_CMD_AM_MODE 105
#define IOCTL_CMD_MUTE 106
#define IOCTL_CMD_VOL 107
#define IOCTL_CMD_FM_TUNE 108
#define IOCTL_CMD_AM_TUNE 109
#define IOCTL_CMD_FM_SERACH 110
#define IOCTL_CMD_AM_SERACH 111 #define BAROD_BUF_SIZE (1024*1024)
int si47xx_fd, barod_fd;
//保存配置信息和频道信息
unsigned char *barod_buf;
//频道信息
unsigned short *barod_ch; //配置信息
struct si47xx_cfg{
int max_ch;
int ch;
int vol;
}; struct si47xx_cfg *cfg; void welcome()
{
printf("/////////////////////////////////////////\n");
printf("/ Power By: Ning Ci /\n");
printf("/ Press key 's' To Auto Serach All Band /\n");
printf("/ Press key 'm' To Redio Mute /\n");
printf("/ Press key 'p' To Set Redio Prev CH /\n");
printf("/ Press key 'n' To Set Redio Next CH /\n");
printf("/ Press key 'q' To Quit Close Radio /\n");
printf("/////////////////////////////////////////\n");
} void fm_mode()
{
ioctl(si47xx_fd, IOCTL_CMD_FM_MODE, );
} void fm_tune(int frequency)
{
ioctl(si47xx_fd, IOCTL_CMD_FM_TUNE, frequency);
} //最大值是63
void set_vol(int vol)
{
ioctl(si47xx_fd, IOCTL_CMD_VOL, vol);
} void set_ch(int ch)
{
fm_tune(barod_ch[ch]); //读取电台信息显示给用户
printf("ch: %d %.1f Mhz \n", ch, barod_ch[ch]/100.0);
} void serach()
{
int frequency;
//设定开始搜索频率
fm_tune();
//配置信息最大频道清0
cfg->max_ch = ;
while()
{
frequency = ioctl(si47xx_fd, IOCTL_CMD_FM_SERACH, );
if( < frequency)
{
printf("serach: %.1f Mhz\n", frequency/100.0);
//保存频率信息
barod_ch[cfg->max_ch] = frequency;
cfg->max_ch++;
}
else
{
break;
}
}
printf("serach done find %d radio\n", cfg->max_ch);
} void mute()
{
static int is_mute=;
ioctl(si47xx_fd, IOCTL_CMD_MUTE, is_mute%);
is_mute++;
} //测试用
void test()
{
fm_mode();
fm_tune();
set_vol();
} int main(int argc, char **argv)
{
//控制命令
char cmd; struct stat barod_stat; //打印使用信息
welcome(); //打开设备
si47xx_fd = open("/dev/si47xx", O_RDWR);
if( > si47xx_fd)
{
printf("cat't open si47xx \n");
return ;
} //打开或创建一个保存频率的文件
barod_fd = open("./barod_info.txt", O_RDWR | O_CREAT, ); //如果文件大小为0就填充
if(- == fstat(barod_fd, &barod_stat))
{
printf("get barod_info stat err\n");
return ;
}
if( == barod_stat.st_size)
{
ftruncate(barod_fd, BAROD_BUF_SIZE+);
} barod_buf = mmap(NULL, BAROD_BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, barod_fd, );
if(barod_buf == MAP_FAILED)
{
printf("cat't mmap barod_buf \n");
return ;
} //barod_buf = malloc(BAROD_BUF_SIZE); //读取配置信息
cfg = (struct si47xx_cfg *)barod_buf; //读取频道配置信息
barod_ch = (unsigned short *)(barod_buf + sizeof(struct si47xx_cfg)); if( == barod_stat.st_size)
{
memset(barod_buf, , BAROD_BUF_SIZE);
cfg->ch = ;
cfg->vol = ;
} //初始化FM模式
fm_mode();
mute(); //读取保存的电台
set_ch(cfg->ch);
set_vol(cfg->vol); while('q' != (cmd = getchar()))
{
switch(cmd)
{
case 't': test(); break;
case 's': serach(); break;
case '+': set_vol(cfg->vol+=); break;
case '-': set_vol(cfg->vol-=); break;
case 'm': mute(); break;
case 'p': set_ch(--cfg->ch); break;
case 'n': set_ch(++cfg->ch); break;
case 'h': welcome(); break;
}
} munmap(barod_buf, BAROD_BUF_SIZE);
close(si47xx_fd);
close(barod_fd);
return ;
}
完整片源码地址:https://github.com/nejidev/si47xx_radio_linux
实现了,FM/AM/SW自动搜索,音量控制,频率设定,红外遥控。
si4745 FM-AM-SW 音量控制芯片 驱动详解的更多相关文章
- linux usb 驱动详解
linux usb 驱动详解 USB 设备驱动代码通过urb和所有的 USB 设备通讯.urb用 struct urb 结构描述(include/linux/usb.h ). urb 以一种异步的方式 ...
- 25.Linux-Nor Flash驱动(详解)
1.nor硬件介绍: 从原理图中我们能看到NOR FLASH有地址线,有数据线,它和我们的SDRAM接口相似,能直接读取数据,但是不能像SDRAM直接写入数据,需要有命令才行 1.1其中我们2440的 ...
- 16.Linux-LCD驱动(详解)
在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构体: framebuffer_alloc(); 2) 设置fb_info 3) 设置硬件相关的操作 ...
- 使用VS2010编译MongoDB C++驱动详解
最近为了解决IM消息记录的高速度写入.多文档类型支持的需求,决定使用MongoDB来解决. 考虑到MongoDB对VS版本要求较高,与我现有的VS版本不兼容,在leveldb.ssdb.redis.h ...
- 16.Linux-LCD驱动(详解)【转】
转自:https://www.cnblogs.com/lifexy/p/7604011.html 在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构 ...
- 13.Linux键盘驱动 (详解)
版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的 ...
- 18.Llinux-触摸屏驱动(详解)
本节的触摸屏驱动也是使用之前的输入子系统 1.先来回忆之前第12节分析的输入子系统 其中输入子系统层次如下图所示, 其中事件处理层的函数都是通过input_register_handler()函数注册 ...
- 21.Linux-写USB键盘驱动(详解)
本节目的: 根据上节写的USB鼠标驱动,来依葫芦画瓢写出键盘驱动 1.首先我们通过上节的代码中修改,来打印下键盘驱动的数据到底是怎样的 先来回忆下,我们之前写的鼠标驱动的id_table是这样: 所以 ...
- 23.Linux-块设备驱动(详解)
通过上节的块设备驱动分析,本节便通过内存来模拟块设备驱动 参考内核自带的块设备驱动程序: drivers/block /xd.c drivers/block /z2ram.c 1.本节需要的结构体如 ...
随机推荐
- mysql中造3千条数据(3种方法)
方法一:存储过程 1.存储过程如下: delimiter $$ DROP PROCEDURE IF EXISTS data CREATE PROCEDURE data(in i int) BEGIN ...
- 密码子演化假说|凝固事件假说|立体化学假说|共进化假说|代谢途径相关性假说|四重兼并|假四重兼并|最小损伤原则|AU-rich|GC-rich|逐步进化假说|分子机制进化假说
生命组学 将密码子表重排后发现,嘌呤嘧啶含量不同,密码子的氨基酸种类由第一二位决定,同时第三位变化大却没有蛋白质层面上实质性的改变,这说明第三位氨基酸是用于维持氨基酸组成不发生变化同时保证蛋白质稳定性 ...
- 从CVPR 2014看计算机视觉领域的最新热点
2014看计算机视觉领域的最新热点" title="从CVPR 2014看计算机视觉领域的最新热点"> 编者按:2014年度计算机视觉方向的顶级会议CVPR上月落下 ...
- js - __proto__ 、 prototype和constructor
零.资料与前言 0x1 材料: 1.帮你彻底搞懂JS中的prototype.__proto__与constructor(图解) 0x2 前言 之前也尝试总结过 js 中的 __proto__ . pr ...
- [转]<版本一>写代码的小女孩
天冷极了,下着雪,又快黑了.这是NOIP的前夜.在这又冷又黑的晚上,一个衣衫破烂的小女孩在机房敲着代码.她从班里逃出来的时候还拿着一本算导,但是有什么用呢?那是一本很破旧的书——那么大,一向是她妈妈垫 ...
- HTTP 协议的基本知识,包括请求流程、请求方法等
一.什么是http协议? HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(World Wide Web Consortium)和Int ...
- 【转载】Scrapy安装及demo测试笔记
Scrapy安装及demo测试笔记 原创 2016年09月01日 16:34:00 标签: scrapy / python Scrapy安装及demo测试笔记 一.环境搭建 1. 安装scrapy ...
- linux find命令格式及find命令详解
本文详细介绍了linux find命令格式及find命令案例,希望对您的学习有所帮助.1.find命令的一般形式为:find pathname -options [-print -exec -ok . ...
- 组合数学之Pólya计数理论
1 群 群$(G, cdot)$: 闭合, 结合律, 幺元, 逆 1.1 置换群 置换为双射$pi:[n]to [n]$, 置换之间的操作符 $cdot$ 定义为函数的复合, 即$(pi cdot s ...
- PHP RFI 的小tip
有关PHP include的帖子网上已经很多了,wooyun的知识库里面也有一篇总结的很好的文章,传送门:http://drops.wooyun.org/tips/3827,今晚在看书的时候看到RFI ...