通过串口控制RDA5807收音模块(stm32+c#上位机)
本例子通过串口控制RDA5807收音模块,实现自动搜FM电台, 调节音量,保存喜爱电台频率,通过定义stm32的ADC直接采集输出的音频信号实现动态电平图等功能,文章后有完整的 stm32代码和c#上位机代码
通过网盘分享的文件:软件FM收音机.rar
链接: https://pan.baidu.com/s/15aaPJ75Sll29P3WI9GurVA 提取码: abcd
--来自百度网盘超级会员v6的分享
stm32代码示例
rda5807m.h
#ifndef __RDA5807M_H
#define __RDA5807M_H
#include "sys.h"//IO方向设置
#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}//IO操作函数
#define IIC_SCL PBout(6) //SCL
#define IIC_SDA PBout(7) //SDA
#define READ_SDA PBin(7) //输入SDA //IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号void RDA5807_write_reg(void);
void RDA5807_read_reg(uint8_t *reg_buf);
void RDA5807_power(void);
void RDA5807_FM_seek(void);
void RDA5807_FM_Test(void);
void RDA5807_seek_down(void);
void RDA5807_seek_up(void);
void RDA5807_Init(void);
u16 RDA5807_Freq_Get(void);
void RDA5807_adjust_volume(uint8_t mode);//读现在音量大小
uint8_t RDA5807_rd_volume(void);void MPU9250_Write_Reg(u8 Slave_add,u8 reg_add,u8 reg_dat);
u8 MPU9250_Read_Reg(u8 Slave_add,u8 reg_add);
uint16_t RDA5807M_Read_Reg(uint8_t Address);
uint16_t RDA5807M_ChanToFreq(uint16_t chan);void RDA5807_set_volume(uint8_t mode); //直接设置音量大小void setBasson(void);
void setBassoff(void); #endif /* __RDA5807M_H */
rad5807m.c
#include "rda5807m.h"
#include "delay.h"
#include "usart.h"#include "stm32f10x.h"#define RDA5807M_SLAVE_ADDRESS 0x20uint8_t fm_volume; // 音量// 除了第1个寄存器功能唯1外,其它寄存器功能都多样,几乎1个位1个功能
// 主功能寄存器
#define RDA5807M_Register_ChipID 0x00 // 芯片ID
#define RDA5807M_Register_Multifunction2 0x02 // 多功能寄存器2
#define RDA5807M_Register_Multifunction3 0x03 // 多功能寄存器3
#define RDA5807M_Register_Multifunction4 0x04 // 多功能寄存器4
#define RDA5807M_Register_Multifunction5 0x05 // 多功能寄存器5
#define RDA5807M_Register_Multifunction6 0x06 // 多功能寄存器6
#define RDA5807M_Register_Multifunction7 0x07 // 多功能寄存器7
#define RDA5807M_Register_Multifunction8 0x08 // 多功能寄存器8
#define RDA5807M_Register_MultifunctionA 0x0A // 多功能寄存器A
#define RDA5807M_Register_MultifunctionB 0x0B // 多功能寄存器B
// 其余寄存器
#define RDA5807M_Register_MultifunctionC 0x0C // 多功能寄存器C
#define RDA5807M_Register_MultifunctionD 0x0D // 多功能寄存器D
#define RDA5807M_Register_MultifunctionE 0x0E // 多功能寄存器E
#define RDA5807M_Register_MultifunctionF 0x0F // 多功能寄存器F// RDA5807 寄存器 写
uint8_t RDA_reg_data[8] =
{0xd0,0x00, // 02H0x00,0x00, // 03H0x00,0x40, // 04H0x90,0x88, // 05H
};//IIC初始化
void IIC_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_Init(GPIOB, &GPIO_InitStructure);IIC_SCL=1;IIC_SDA=1;
}//产生IIC起始信号
void IIC_Start(void)
{SDA_OUT(); //sda线输出IIC_SDA=1; IIC_SCL=1;delay_us(4);IIC_SDA=0;//START:when CLK is high,DATA change form high to low delay_us(4);IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{SDA_OUT();//sda线输出IIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highdelay_us(4);IIC_SCL=1;IIC_SDA=1;//发送I2C总线结束信号delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{u8 ucErrTime=0;SDA_IN(); //SDA设置为输入IIC_SDA=1;delay_us(1);IIC_SCL=1;delay_us(1);while(READ_SDA){ucErrTime++;if(ucErrTime>250){IIC_Stop();return 1;}}IIC_SCL=0;//时钟输出0return 0;
}
//产生ACK应答
void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=1;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{u8 t;SDA_OUT();IIC_SCL=0;//拉低时钟开始数据传输for(t=0;t<8;t++){IIC_SDA=(txd&0x80)>>7;txd<<=1;delay_us(2); //对TEA5767这三个延时都是必须的IIC_SCL=1;delay_us(2);IIC_SCL=0;delay_us(2);}
}//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();//SDA设置为输入for(i=0;i<8;i++ ){IIC_SCL=0;delay_us(2);IIC_SCL=1;receive<<=1;if(READ_SDA)receive++;delay_us(1);}if (!ack)IIC_NAck();//发送nACKelseIIC_Ack(); //发送ACKreturn receive;
}/*** @brief 写寄存器值* @param 无* @retval 无*/
void RDA5807_write_reg(void)
{uint8_t i;uint8_t ucAck;IIC_Start();/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 *///IIC_Send_Byte(RDA5807M_SLAVE_ADDRESS | I2C_WR);IIC_Send_Byte(0X20);/* 检测ACK */ucAck = IIC_Wait_Ack();if (ucAck == 1){IIC_Stop();}// 寄存器连续写操作for(i=0; i<8; i++){IIC_Send_Byte(RDA_reg_data[i]);/* 检测ACK */ucAck = IIC_Wait_Ack();if (ucAck == 1){IIC_Stop();}}IIC_Stop();
}/*** @brief 连续读寄存器子函数* @param reg_buf:寄存器* @retval 无*/
void RDA5807_read_reg(uint8_t *reg_buf)
{uint8_t i;uint8_t ucAck;IIC_Start();/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 *///IIC_Send_Byte(RDA5807M_SLAVE_ADDRESS | I2C_RD);IIC_Send_Byte(0X21);/* 检测ACK */ucAck = IIC_Wait_Ack();if (ucAck == 1){IIC_Stop();}for (i = 0; i < 4; i++){if (i == 3)reg_buf[i] = IIC_Read_Byte(0);elsereg_buf[i] = IIC_Read_Byte(1);}IIC_Stop();
}/*** @brief 模块上电初始化子函数* @param 无* @retval 无*/
void RDA5807_power(void)
{delay_ms(50);// 发送软件复位指令RDA_reg_data[0] = 0x00;RDA_reg_data[1] = 0x02;RDA5807_write_reg();delay_ms(10);// 收音模块默认参数RDA_reg_data[0] = 0xd0;RDA_reg_data[1] = 0x01;RDA5807_write_reg();
}/*** @brief 收音模块自动寻台模式* @param 无* @retval 无*/
extern float gzpd;
void RDA5807_FM_seek(void)
{uint16_t chan;uint8_t reg_data[4] = {0x00, 0x00, 0x00, 0x00};RDA_reg_data[3] &= ~(1 << 4); //调谐禁用// 内部自动寻台使能RDA_reg_data[0] |= (1 << 0); //SEEK位置1RDA5807_write_reg();// 等待STC 标志置位while(0 == (reg_data[0] & 0x40)){delay_ms(40);// 读取内部状态RDA5807_read_reg(reg_data);}// 获取当前工作频点// chan = reg_data[0]; chan = reg_data[0] & 0x03ff;// chan = reg_data[1] | (chan << 8);// chan = chan << 6;chan = RDA5807M_Read_Reg(RDA5807M_Register_MultifunctionA) & 0x03FF;//return RDA5807M_ChanToFreq(chan);// gzpd=chan;//gzpd=RDA5807M_ChanToFreq(chan);gzpd=(chan*21.61+8700)/100;// printf("\r\n 寻台成功 \r\n");
// printf("当前工作频点为:%d" , chan);// 保存当前工作频点RDA_reg_data[2] = (chan >> 8) & 0xff;RDA_reg_data[3] = (chan & 0xff);//RDA5807_write_reg(); //自己加的
}////////////////////////////////////////////////////////////////////////////////
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答 void MPU9250_Write_Reg(u8 Slave_add,u8 reg_add,u8 reg_dat)
{IIC_Start();IIC_Send_Byte(Slave_add);IIC_Wait_Ack();IIC_Send_Byte(reg_add);IIC_Wait_Ack();IIC_Send_Byte(reg_dat);IIC_Wait_Ack();IIC_Stop();
}u8 MPU9250_Read_Reg(u8 Slave_add,u8 reg_add)
{u8 temp=0;IIC_Start();IIC_Send_Byte(Slave_add);temp=IIC_Wait_Ack();IIC_Send_Byte(reg_add);temp=IIC_Wait_Ack();IIC_Start(); //IIC_Send_Byte(Slave_add+1);temp=IIC_Wait_Ack();temp=IIC_Read_Byte(0);IIC_Stop();return temp;
}
uint16_t RDA5807M_Read_Reg(uint8_t Address)
{u16 ls;ls=MPU9250_Read_Reg(0x20,Address);return ls;
}void setBasson(void) //设置重低音模式
{uint16_t regCtrl = RDA5807M_Read_Reg(0x02);regCtrl |= 0x1000; //#define RADIO_REG_CTRL_BASS 0x1000//else//regCtrl &= (~0x1000);// registers[RADIO_REG_CTRL] = regCtrl;// _saveRegister(RADIO_REG_CTRL);MPU9250_Write_Reg(0x20,0x02,regCtrl); } void setBassoff(void) //设置重低音模式
{uint16_t regCtrl = RDA5807M_Read_Reg(0x02);//regCtrl |= 0x1000; //#define RADIO_REG_CTRL_BASS 0x1000//elseregCtrl &= (~0x1000);// registers[RADIO_REG_CTRL] = regCtrl;// _saveRegister(RADIO_REG_CTRL);MPU9250_Write_Reg(0x20,0x02,regCtrl); } // 频率(以MHz为单位*100)(如108MHz=>10800)
uint16_t RDA5807M_ChanToFreq(uint16_t chan)
{uint16_t freqStart = 0; // 频率起始uint16_t freqEnd = 0; // 频率结束float freqSpace = 0; // 频率间隔uint16_t readReg = 0; // 获取寄存器值readReg = (RDA5807M_Read_Reg(RDA5807M_Register_Multifunction3) & 0x000C) >> 2; // 波段功能值位转实际起始频率switch(readReg){case 0x00:freqStart = 8700; // 87MHz = 87.00MHzfreqEnd = 10800;break;case 0x01:freqStart = 7600;freqEnd = 9100;break;case 0x02:freqStart = 7600;freqEnd = 10800;break;case 0x03:if((RDA5807M_Read_Reg(RDA5807M_Register_Multifunction7) >> 9) & 0x01){freqStart = 6500;freqEnd = 7600;}else{freqStart = 5000;freqEnd = 7600;}break;}readReg = (RDA5807M_Read_Reg(RDA5807M_Register_Multifunction3) & 0x0003);switch(readReg){case 0x00:freqSpace = 10; // 100K = 0.1Mbreak;case 0x01:freqSpace = 20;break;case 0x02:freqSpace = 5;break;case 0x03:freqSpace = 2.5;break;}readReg = freqStart + chan * freqSpace;// 范围约束readReg = readReg >= freqEnd ? freqEnd : 0;readReg = readReg <= freqStart ? freqStart : 0;return readReg;
}/////////////////////////////////////////////////////////////////////////////////*** @brief 向下搜台* @param 无* @retval 无*/
void RDA5807_seek_down(void)
{RDA_reg_data[0] &= ~(1 << 1); //向下搜台RDA5807_FM_seek();
// printf("\r\n 向下寻台 \r\n");
}/*** @brief 向上搜台* @param 无* @retval 无*/
void RDA5807_seek_up(void)
{RDA_reg_data[0] |= (1 << 1); //SEEK UPRDA5807_FM_seek(); //自动寻台// printf("\r\n 向上寻台 \r\n");
}/*** @brief 初始化* @param 无* @retval 无*/
void RDA5807_Init(void)
{IIC_Init();RDA5807_power();// printf("\r\n 上电成功 \r\n");RDA_reg_data[7] = 0x8f; // 05H寄存器低四bit 改变音量RDA5807_write_reg();fm_volume = RDA_reg_data[7] & 0xff; //取音量值// printf("当前音量为%d" , fm_volume);RDA5807_seek_up();
}/*** @brief 得到当前电台频率* @param 无* @retval 频率值(单位10Khz)*/
u16 RDA5807_Freq_Get(void)
{u16 temp,freq;temp = (RDA_reg_data[2]*256)+(RDA_reg_data[3]&0xc0); //计算temp = temp>>6;freq = (u16)(10*temp+8700);return freq; //返回频率值
}/*** @brief 调节音量* @param mode: 1 加大 0 减小* @retval 无*/
void RDA5807_adjust_volume(uint8_t mode)
{if(mode){if((RDA_reg_data[7] & 0x0f) < 0xf)RDA_reg_data[7]++;}else{if((RDA_reg_data[7] & 0x0f) > 0)RDA_reg_data[7]--;}RDA_reg_data[0] = 0xd0;RDA5807_write_reg();
}void RDA5807_set_volume(uint8_t mode) //直接设置音量大小
{RDA_reg_data[7]=mode;RDA_reg_data[0] = 0xd0;RDA5807_write_reg();
} //读现在音量大小
uint8_t RDA5807_rd_volume(void)
{uint8_t fm_volume1;fm_volume1 = RDA_reg_data[7] & 0xff; //取音量值return fm_volume1;
}