使用RDA5807m实现调台收音功能
- 连续读写方式
- 标准IIC读写方式
- 过程记录
最近用RDA5807M实现调台收音的功能,在这里记录下整个历程(主要是程序实现)。
RDA5807是用IIC协议通信的,我用stm32作为控制器,通过CLOCK和DATA两个引脚和stm32连接,外围电路按照规格书给的应用电路。
RDA5807M的datasheet只给出了连续读写的方式,但在其他系列比如RDA5807N编程指南里描述了标准IIC读写方式,区别于IIC的器件地址不同。
连续读写方式
连续读写方式的器件地址是0010000B,加上读写标志,即0x20(写操作)和0x21(读操作)。
连续读写的方式不可以直接操作寄存器的地址,只有一个固定的开始寄存器地址,(写0x02H,读0x0AH),内部有一个增量地址计数器。
每个寄存器都是16bit的,写寄存器默认从0x02H开始,按字节算,写进去的数据依次为0x02H的高字节,0x02H低字节,0x03H高字节…,读寄存器时,默认从0x0AH开始读,所以读出来的数据依次是0x0AH的高字节,0x0AH的低字节…
读写顺序按照datasheeet给出的时序图,用stm32任意两个引脚模拟IIC通信,要注意在发送之后是否有收到ACK。
标准IIC读写方式
这是带寄存器地址的方式,IIC器件地址0010000B,加上读写标志,即0x22(写),0x23(读),这种方式可以单独对相应的寄存器操作,并且可以直接读写每一个寄存器。
过程记录
开始的时候这两种读写方式我都尝试过,都遇到了不同的问题。
一开始我先用标准读写方式,我能够读写,但是02H和03H这两个写不进去,写完以后读出来的跟写的不一样。
于是我就改成了用连续读写的方式,不能实现连续写,写入两个字节之后再继续写就收不到ACK。搜了很多东西,也请教了曾经做过这个的大佬,他们当时遇到的问题是IIC延时太短,来不及收到ACK,我也试过还是不行,各种办法都试了一下,甚至还有一天试了个通宵。
一个星期之后另一个队友重做了一块板(之前在IIC接口加了上拉电阻没有用,重做板之后03H还是读出来不对),加了上拉之后,其他都正常,这次的问题是03H的第四位写1读出来是0,但实际是可以正常工作。
还要注意的是IIC通信,串口通信对传输线的要求比较高,之前用杜邦线,传输数据会乱,所以建议做通信绝对不要用杜邦线。还有前面提到的延时也是必要的。频繁读写会造成RDA不正常工作或者出现奇怪的音效。
实现调频率收音也就是TUNE模式主要设置02H,03H以及读0AH,0BH。
排除所有不可能的,剩下的那个即使再不可思议,那也是事实
在什么尝试都没有用的时候,怀疑板的问题是很合理的,确认代码没有问题的情况下板也查不出来什么的时候不如重做一块。
下面是基于stm32模拟IIC的代码,按照标准IIC读写的方式
//读写寄存器
unsigned int ReadReg(u8 reg_Addr)
{unsigned int buf = 0;IIC_Start();IIC_Send_Byte(RDA_WRITE);IIC_Wait_Ack();IIC_Send_Byte(reg_Addr);IIC_Wait_Ack();IIC_Start();IIC_Send_Byte(RDA_READ);IIC_Wait_Ack();buf = IIC_Read_Byte(1);buf = buf<<8;buf = buf|IIC_Read_Byte(0);IIC_Stop();return buf;
}
void WriteReg(u8 reg_Addr, u16 value)
{IIC_Start();IIC_Send_Byte(RDA_WRITE);IIC_Wait_Ack();IIC_Send_Byte(reg_Addr);IIC_Wait_Ack();IIC_Send_Byte(value>>8);IIC_Wait_Ack();IIC_Send_Byte(value&0xFF);IIC_NAck();IIC_Stop();
}
RDA FM系列芯片的初始操作顺序:复位 → 读取芯片ID(可有可无) → 上电(使能) → 写初始化数据。
复位和使能后都需要延时(尤其是使能后)
RDA5807M初始化:
void RDA_init(void)
{unsigned int temp;WriteReg(RDA_R02,0x0002); delay_ms(50);WriteReg(RDA_R02,0xc001);delay_ms(600);WriteReg(RDA_R03,0x1A10);WriteReg(RDA_R04,0x0400);WriteReg(RDA_R05,0x86ad);WriteReg(0x06,0x8000);WriteReg(0x07,0x5F1A);
}
Frequency = Channel Spacing (kHz) x CHAN+ 87.0 MHz
设置频率(设置频率之后一定要延时):
void Set_Fre(u32 fre) //88MHz~108MHz 200KHz步进
{u16 chan, temp;chan = (int)((fre-87000)/200);temp |= chan<<6;//chan[15:6]temp |= 1<<4; //tune enabletemp |= 1; //200kWriteReg(RDA_R03, temp);delay_ms(40);
}
写完之后读寄存器测试读的和写的是否对应
最后能够实现功能感谢队友
感谢不放弃
以上部分内容参考RDA5807M datasheet和RDA5807N 编程指南