FM相关应用
📎 原始文档:https://www.kdocs.cn/l/cordJVMmoNy3 FM相关应用
本文档旨在指导用户快速使用杰理方案调试FM相关的应用,进行快速初步了解。
概述:
AC692X、AC695X、AC696X系列芯片支持FM功能,FM功能描述可以在“用户手册”中的”复杂设备“中有所描述
AC692X:
- FM调频立体声接收系统,覆盖范围:76-108MHz,步进50/100KHz(与蓝牙不可同时用) AC696X:
- FM调频立体声接收系统,覆盖范围:76-108MHz,步进50/100KHz(与蓝牙不可同时用) AC695X:
- FM调频立体声接收系统,覆盖范围:76-108MHz,步进50/100KHz(与蓝牙可同时用)
- FM调频立体声发送系统,覆盖范围:76-108MHz,步进50/100/200KHz(与蓝牙可同时用)(FM发射用AC6952E做 )
通常FM接收功能,分内置FM和外置FM两种,内置FM使用杰理芯片内部的射频模块进行数据的解调,最后将数据发送到DAC模块,从而输出声音,外置FM使用类似于RDA5807等芯片,经过该芯片解调后输出到DAC,杰理方案通过LINEIN/AUX的模块采集输出到DAC。
FM功能相应的代码配置,在各板级头文件件中,如apps\soundbox\board\br23\board_ac695x_demo\board_ac695x_demo_cfg.h
//*********************************************************************************//
// fm 配置 //
//*********************************************************************************//
#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能
#define TCFG_FM_INSIDE_ENABLE ENABLE
#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块
#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块
#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块
#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list
#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR
#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG//用于配置FM的输入来源。如模拟,则是内置FM模块,如是ADC则是使用LINEIN模块采集
#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)
#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE)))
#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram,用于减少访问内部FLASH的高频干扰,增加FM收音灵敏度
#else
#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram,用于减少访问内部FLASH的高频干扰,增加FM收音灵敏度
#endif
#else
#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram,用于减少访问内部FLASH的高频干扰,增加FM收音灵敏度
#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/
#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)
#undef TCFG_LED7_RUN_RAM
#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram)
#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/
//*********************************************************************************//
// fm emitter 配置 //
//*********************************************************************************//
#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE
#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE
#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE
#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE
#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE
代码:
FM接收: 在app_main.c中会进入到app_fm_task,该模式用于FM接收功能。
应用端开发重点关注 ..\apps\soundbox\task_manager\fm文件夹下的源文件,
其中
fm.c是主要用于接收按键消息,设备消息,公共消息,根据相应的消息进行处理
fm_api.c提供了频道搜索,频道检索,频道切换,频道增加删除,静音等api接口
fm_rw.c提供频点存储,读取,检查的api接口
由于FM接收功能可以通过内置FM模块或外置FM芯片来实现,需要通过fm_manage.c来管理各类的驱动代码。
路径 ..\apps\common\device\fm 文件夹下有包含各类芯片的驱动,
fm_manage.c用于管理FM驱动驱动代码,rda5807,qn8035,bk1080,fm_inside是各类驱动的文件夹FM发射: FM发射功能的驱动代码在路径..\apps\common\device\fm_emitter,该文件夹下包含了驱动代码。
FM数据编码发射源代码在路径..\cpu\br23\audio_common,audio_fmtx.c和audio_fmtx.h包含了编码的代码。
FM接收:
1、内置FM搜台软件调试方法
- 用认可的收音机/对比样机先搜一次台,记录下当前位置的清晰台(人声清晰/基本没有雪花声)对应频点 不同天气、不同时间段、不同位置、实际收台效果会有差别,在调试 FM 时要有对比样机做参考,且使用整机测试;(拿笔记录下对比样机的每个电台频点,再记录下样机能收到的每个电台的频点,具体分析是那些频点没有收到)
- 确定FM内部AGC的值 值的设定可参考以下规则:(有放大,设最小;没放大,设最大)
- 加放大电路:建议把AGC的值设置到最小,放大倍数由外部放大电路决定。
- 没有放大电路:首先把AGC的值设置到最大;然后观察是否存在串台现象。若有串台现象就需要降低内部AGC的值,没有则可以使用最大值。 AC696/AC695 AGC的值(范围:-96 ~ -1)
#define FMSCAN_AGC -55 //AGC阈值 -55左右
- 有条件可以用信号发生器,可以测试一下收音的灵敏度/信噪比。一般灵敏度在 15dBu 以下的,收台效果都比较好。
- 对比实际搜台效果。根据前面记录的清晰台频点,对比实际样机少了哪些频点并在样机商听下少掉的频点是否清晰。(例如:你发现88.8MHz这个频点的清晰台没有搜到,就把样机频点设到88.8MHz,听样机的声音。如果声音清晰――可修改搜台判断阈值。如果声音不清晰,软件就没办法了) 备注:在实际调试中,一般只需把清晰台基本搜出来既可,不用太关注不清晰台的数量。因为假台可以通过修改判断阈值进行增加或者减少。
- 搜台阈值修改 主要修改以下三个参数:
- MSCAN_CNR: 台清晰该值越大,调大该值可以过滤大部分假台。
- FMSCAN_P_DIFFER : 全部台 power 都需要大于该值。agc_noise_avg 较高时要大于 FMSCAN_P_DIFFER+1
- FMSCAN_N_DIFFER :当台不是十分清晰时,需要 noise 差异值在这个范围之间
- 参数说明
FMSCAN_SEEK_CNT_MIN //一段时间内的中频波形最小过零点数
FMSCAN_SEEK_CNT_MAX //一段时间内的中频波形最大过零点数
FMSCAN_960_CNR //24M 晶振 96M 谐波的基础 CNR
FMSCAN_1080_CNR //芯片内部 12M 时钟源 108M 谐波的基础 CNR
FMSCAN_AGC agc_noise_avg //超过此值,自动降低 FM 内部增益,从最高增益开始降
FMSCAN_ADD_DIFFER agc_noise_avg //低于此值,判定会增加 FMSCAN_N_DIFFER,降低假台率
FMSCAN_CNR //信号在中频上的载噪比
FMSCAN_P_DIFFER //当前频点最小 power 减 上一个频点最大 power
FMSCAN_N_DIFFER //当前频点最小 noise 减 上一个频点最小 noise
FM_IF //FM 听台中频
- 真台判定条件 ①FMSCAN_SEEK_CNT_MIN <= seek_cnt <= FMSCAN_SEEK_CNT_MAX ②非谐波频点: FMSCAN_CNR <= cnr,谐波频点: FMSCAN_CNR + FMSCAN_960_CNR <= cnr,108M 同理
③当 FMSCAN_ADD_DIFFER <= agc_noise_avg 时: FMSCAN_P_DIFFER + 1 <= power_differ FMSCAN_N_DIFFER 无效 当 FMSCAN_ADD_DIFFER > agc_noise_avg 时: FMSCAN_P_DIFFER <= power_differ (-)FMSCAN_N_DIFFER <= noise_differ <=(+) FMSCAN_N_DIFFER 注意:软件只能把搜索到的清晰台给筛选出来,不能把一个不清晰/串台的台变成清晰。
以上seek_cnt,cnr,agc_noise_avg,power_differ,可以通过串口打印来进行debug,需要把库打印以及相应内置FM驱动底层模块打印打开才会出现。
需在文件apps\soundbox\include\app_config.h中#define LIB_DEBUG 1
以及apps\soundbox\log_config\lib_driver_config.c中const char log_tag_const_i_FM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1);
2、内置FM 驱动API函数
void fm_inside_io_ctrl(int ctrl, ...);
void fm_inside_default_config(void);//默认配置参数
void fm_inside_mem_init(void);
void fm_inside_on(void);//内置收音初始化
void fm_inside_off(void);//关闭内置收音
u8 fm_inside_freq_set(u32 freq);//设置频点 87.5M 填 87500
void fm_inside_int_set(u8 mute);//中断开关
u16 fm_inside_id_read(void);//获取内置收音的ID
s8 fm_inside_rssi_read(void); //获取电台的功率 -96 ~ 0 dB
u8 fm_inside_st_read(void);//获取电台的声道 1:立体声; 0: 单声道;
s8 fm_inside_cnr_read(void);//获取当前频点的载噪比 dB
void fm_inside_set_stereo(u8 set); //set[0,128], 0 mono, 128 stereo。0~128对应0~30dB分离度
void fm_inside_set_abw(u8 set); //audio bandwidth set //set[0,127] <=>2k~16k
void fm_inside_deempasis_set(u8 set);// set[0/1], 0:50us, 1:75us
void fm_inside_agc_set(u8 lpf_gain, u8 lna_atten, u8 lna_en); //配置fm内部增益

3、设置默认FM收音频点方法
clear_all_fm_point(); //清除FM保存频点
save_fm_point(REAL_FREQ(76)); //874 + 76 = 950 对应95.0Khz
save_fm_point(REAL_FREQ(146)); //874 + 146 = 1020 对应102.0 Khz
4、外置FM
RDA5807
695 demo程序:
链接:https://pan.baidu.com/s/1mJW2w22Zeil4T-WimG-Scw
提取码:8888
【金山文档】 AC7006F4_V121最新补丁_RDA5807_20230620
https://kdocs.cn/l/ci6cTVdg8VVD
FM发射:
- 内置FM发射 内置FM发射的产品应用方向有车充点烟器
如何开关FM发射器?
文件路径apps\common\device\fm_emitter\fm_emitter_manage.c
void fm_emitter_manage_stop(void)//关闭发射器
void fm_emitter_manage_start(void)//开启发射器
设置fm发射立体声
fmtx_stereo_onoff(1);//内置fm设置发射立体声
qn8027_write_Bit(QN8027_SYSTEM, 4, 1, 0);//外挂qn8027设置立体声
DAC和FM发射同时输出的时候,只关闭或打开FM发射输出,DAC持续输出声音
目前发布的SDK中FM发射器解码流返回长度0,导致解码流挂机,DAC和FM发射在同一数据流里面,所以DAC会没有声音。
处理方法:
- 开4ms定时唤醒解码流功能,路径cpu\br25\audio_dec\audio_dec.c

- 对cpu\br23\audio_common\audio_fmtx.c 进行修改 参考代码如下:
【金山文档】 AC695N_soundbox_sdk_release_3.1.0
https://kdocs.cn/l/coOnvKU9rEEI
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "app_config.h"
#include "circular_buf.h"
#include "audio_fmtx.h"
#include "fm_emitter/fm_emitter_manage.h"
#if (TCFG_APP_FM_EMITTER_EN)
#define FMTX_DEBUG_ENABLE 1
#if FMTX_DEBUG_ENABLE
#define fmtx_debug printf
#else
#define fmtx_debug(...)
#endif
#define FMTX_TX_BUF_LEN (4*1024)
struct _fmtx_output {
u32 in_sample_rate;
u32 out_sample_rate;
cbuffer_t cbuf;
u8 buf[FMTX_TX_BUF_LEN];
struct audio_src_handle *hw_src;
struct audio_stream_entry entry;
int sr_cal_timer;
u32 points_total;
u32 cnt_total;
u8 ch : 4;
u8 flag : 1;
u8 need_resume : 1;
} *fmtx_output_hdl = NULL;
static u32 fmtx_srI_last = 0;
bool fm_tx_state = 0;
static int audio_stream_fmtx_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, struct audio_data_frame *out)
{
if(fm_tx_state == 1) {
if (fmtx_srI_last != in->sample_rate) {
fmtx_debug("in:%d ---%d\n", fmtx_srI_last, in->sample_rate);
audio_fmtx_output_set_srI(in->sample_rate);
}
u32 len = audio_fmtx_output_write(in->data, in->data_len);
if (len != in->data_len) {
local_irq_disable();
fmtx_output_hdl->need_resume = 1;
local_irq_enable();
// printf("y1");
}
return len;
} else {
//不处理
return in->data_len;
}
}
static void audio_stream_fmtx_data_clear(struct audio_stream_entry *entry)
{
cbuf_clear(&(fmtx_output_hdl->cbuf));
fmtx_debug("fmtx clear\n");
}
static void audio_fmtx_src_irq_cb(void *hdl)
{
if (fmtx_output_hdl) {
audio_stream_resume(&(fmtx_output_hdl->entry));
}
}
int audio_fmtx_src_output_handler(void *parm, s16 *data, int len)
{
int wlen = fmtx_output_hdl->cbuf.total_len - fmtx_output_hdl->cbuf.data_len;
if (wlen > len) {
wlen = len;
}
wlen = cbuf_write(&(fmtx_output_hdl->cbuf), data, wlen);
if (wlen != len) {
local_irq_disable();
fmtx_output_hdl->need_resume = 1;
local_irq_enable();
// printf("y2");
}
return wlen;
}
s16 ref_temp_buf[256];
int audio_fmtx_output_write(s16 *data, u32 len)
{
u32 wlen = 0;
if (fmtx_output_hdl) {
if (fmtx_output_hdl->hw_src) {
wlen = audio_src_resample_write(fmtx_output_hdl->hw_src, data, len);
if (bt_phone_dec_is_running()) {
for (int i = 0; i < (len >> 2); i++) {
ref_temp_buf[i] = data[2 * i] / 2 + data[2 * i + 1] / 2;
}
if (wlen) {
audio_aec_refbuf(ref_temp_buf, wlen / 2);
}
}
} else {
wlen = fmtx_output_hdl->cbuf.total_len - fmtx_output_hdl->cbuf.data_len;
if (wlen > len) {
wlen = len;
}
wlen = cbuf_write(&(fmtx_output_hdl->cbuf), data, len);
}
if (wlen != len) {
local_irq_disable();
fmtx_output_hdl->need_resume = 1;
local_irq_enable();
// printf("y3");
}
}
return wlen;
}
void audio_fmtx_tx_isr(s16 *data, u32 len)
{
u32 wlen = 0;
u32 rlen = 0;
if (fmtx_output_hdl) {
local_irq_disable();
if (fmtx_output_hdl->need_resume) {
fmtx_output_hdl->need_resume = 0;
local_irq_enable();
// printf("n1");
audio_stream_resume(&(fmtx_output_hdl->entry));
} else {
local_irq_enable();
}
fmtx_output_hdl->points_total += len >> 2;
rlen = cbuf_get_data_len(&(fmtx_output_hdl->cbuf));
if ((fmtx_output_hdl->flag == 0) && (rlen < (FMTX_TX_BUF_LEN / 2))) {
memset(data, 0x00, len);
return;
}
fmtx_output_hdl->flag = 1;
if (rlen >= len) {
wlen = cbuf_read(&(fmtx_output_hdl->cbuf), data, len);
} else {
fmtx_debug("fmtx end\n");
wlen = cbuf_read(&(fmtx_output_hdl->cbuf), data, rlen);
memset((u8 *)data + rlen, 0x00, len - rlen);
fmtx_output_hdl->flag = 0;
}
}
}
void audio_fmtx_sr_cal_timer(void *param)
{
if (fmtx_output_hdl) {
if (fmtx_output_hdl->cnt_total == 0) {
fmtx_output_hdl->points_total = fmtx_output_hdl->out_sample_rate * 1000;
fmtx_output_hdl->cnt_total = 999;
}
fmtx_output_hdl->cnt_total++;
fmtx_output_hdl->out_sample_rate = fmtx_output_hdl->points_total / fmtx_output_hdl->cnt_total;
if ((fmtx_output_hdl->points_total > 0xFFF00000) \
&& ((fmtx_output_hdl->cnt_total % 2) == 0)) {
fmtx_output_hdl->points_total >>= 1;
fmtx_output_hdl->cnt_total >>= 1;
}
if (fmtx_output_hdl->hw_src && fmtx_output_hdl->out_sample_rate) {
fmtx_debug("fmtx cal:%d > %d\n",
fmtx_output_hdl->in_sample_rate,
fmtx_output_hdl->out_sample_rate);
audio_hw_src_set_rate(fmtx_output_hdl->hw_src, \
fmtx_output_hdl->in_sample_rate, \
fmtx_output_hdl->out_sample_rate);
}
}
}
void audio_fmtx_output_set_srI(u32 sample_rate)
{
fmtx_debug("audio_fmtx_output_set_srI %d\n", sample_rate);
fmtx_srI_last = sample_rate;
if (fmtx_output_hdl) {
fmtx_output_hdl->points_total = 0;
fmtx_output_hdl->cnt_total = 0;
fmtx_output_hdl->in_sample_rate = sample_rate;
if (fmtx_output_hdl->hw_src) {
fmtx_debug("fmtx set:%d > %d\n", \
fmtx_output_hdl->in_sample_rate, \
fmtx_output_hdl->out_sample_rate);
audio_hw_src_set_rate(fmtx_output_hdl->hw_src, \
fmtx_output_hdl->in_sample_rate, \
fmtx_output_hdl->out_sample_rate);
}
}
}
void audio_fm_tx_start()
{
if(fmtx_output_hdl->sr_cal_timer == NULL) {
fmtx_output_hdl->sr_cal_timer = sys_s_hi_timer_add(NULL, audio_fmtx_sr_cal_timer, 1000);
}
fm_tx_state = 1;
}
void audio_fm_tx_stop()
{
if (fmtx_output_hdl->sr_cal_timer) {
sys_s_hi_timer_del(fmtx_output_hdl->sr_cal_timer);
fmtx_output_hdl->points_total = 0;
fmtx_output_hdl->cnt_total = 0;
fmtx_output_hdl->out_sample_rate = 41667;
fmtx_output_hdl->sr_cal_timer = NULL;
}
fm_tx_state = 0;
}
void *audio_fmtx_output_start(u16 fre)
{
if (fmtx_output_hdl == NULL) {
fmtx_debug("audio_fmtx_output_start\n");
mem_stats();
fmtx_output_hdl = zalloc(sizeof(struct _fmtx_output));
if (fmtx_output_hdl == NULL) {
fmtx_debug("audio_fmtx_output_start malloc err !\n");
return NULL;
}
/* clk_set("sys", 96 * 1000000L); */
/* clk_set_en(0); */
cbuf_init(&(fmtx_output_hdl->cbuf), fmtx_output_hdl->buf, FMTX_TX_BUF_LEN);
fm_emitter_manage_init(fre, audio_fmtx_tx_isr);
fm_emitter_manage_start();
fmtx_output_hdl->in_sample_rate = fmtx_srI_last;
fmtx_output_hdl->out_sample_rate = 41667;
if(fmtx_output_hdl->sr_cal_timer == NULL)
fmtx_output_hdl->sr_cal_timer = sys_s_hi_timer_add(NULL, audio_fmtx_sr_cal_timer, 1000);
fmtx_output_hdl->hw_src = zalloc(sizeof(struct audio_src_handle));
if (fmtx_output_hdl->hw_src) {
audio_hw_src_open(fmtx_output_hdl->hw_src, 2, SRC_TYPE_RESAMPLE);
audio_hw_src_set_rate(fmtx_output_hdl->hw_src, \
fmtx_output_hdl->in_sample_rate, \
fmtx_output_hdl->out_sample_rate);
fmtx_debug("audio fmtx rate:%d -> %d\n", \
fmtx_output_hdl->in_sample_rate, \
fmtx_output_hdl->out_sample_rate);
audio_src_set_output_handler(fmtx_output_hdl->hw_src, NULL, audio_fmtx_src_output_handler);
audio_src_set_rise_irq_handler(fmtx_output_hdl->hw_src, NULL, audio_fmtx_src_irq_cb);
} else {
fmtx_debug("hw_src malloc err ==============\n");
}
fmtx_output_hdl->entry.data_handler = audio_stream_fmtx_data_handler;
fmtx_output_hdl->entry.data_clear = audio_stream_fmtx_data_clear;
/* mem_stats(); */
return (&(fmtx_output_hdl->entry));
}
return NULL;
}
void audio_fmtx_output_stop()
{
fmtx_debug("audio_fmtx_output_stop\n");
if (fmtx_output_hdl) {
fm_emitter_manage_stop();
if (fmtx_output_hdl->sr_cal_timer) {
sys_s_hi_timer_del(fmtx_output_hdl->sr_cal_timer);
}
if (fmtx_output_hdl->hw_src) {
audio_hw_src_stop(fmtx_output_hdl->hw_src);
audio_hw_src_close(fmtx_output_hdl->hw_src);
free(fmtx_output_hdl->hw_src);
fmtx_output_hdl->hw_src = NULL;
}
free(fmtx_output_hdl);
fmtx_output_hdl = NULL;
/* clk_set_en(1); */
}
}
#endif
FAQ:
- AC695/AC696系列FM收音效果差,基本调试思路: 答:
- FM匹配物料放FM天线端,用330nH+4.7PF;
2、功放跑AB类模式,没有其他DC电路干扰;
3、软件开跑RAM的宏,AGC设为-1.;
4、电源干净,地回路完整:VBAT、VDDIO的电容地最快最完整回到芯片地,确保地回路的完整性。错误示范及修改:
5、如果FM要加三极管放大电路,参考如下:
2、AC700X:
AC7006F4SDK121外挂收音芯片5807参考DEMO
链接:https://pan.baidu.com/s/1P1djXnYdeZFfmbM_NRO-YQ
提取码:8888
3、696X当使用外挂FM收音芯片接收FM信号,可以选择将主控芯片进入RC模式来减少芯片内部时钟对FM信号的干扰
void enter_hrc_clock(void) 进入RC模式。
void exit_to_pll_clock(void) 退出RC模式。
代码如下
void jump_ticktmr_isr();
extern int ISR_BASE;
#define ISR_ENTRY (u32)&ISR_BASE
___interrupt
static void SysTickHandler(void){
}
void rc_mode_tick_init(u32 en)
{
unsigned int *israddr = (unsigned int *)ISR_ENTRY;
JL_TIMER3->CON = BIT(14);
israddr[IRQ_TIME3_IDX] = SysTickHandler;
if(en){
TICK_CON = BIT(6);
JL_TIMER3->PRD = 3750;//10ms
JL_TIMER3->CNT = 0;
JL_TIMER3->CON = 0x9|(0b0011<<4);
request_irq(IRQ_TIME3_IDX,1,jump_ticktmr_isr,0);
}
}
void clk_dump()
{
unsigned int *israddr = (unsigned int *)ISR_ENTRY;
printf("%x %x",israddr[IRQ_TIME3_IDX],israddr[IRQ_TICK_TMR_IDX]);
log_info("SPI DIV : %d", JL_SFC->BAUD);
log_debug("SFC_CON : %08x", JL_SFC->CON);
log_debug("SFC_QCNT : %08x", JL_SFC->QUCNT);
log_debug("CACHE_CON : %04x", JL_DSP->CON);
log_info("SYS_DIV : %08x", JL_CLOCK->SYS_DIV);
log_info("CLK_CON0 : %08x", JL_CLOCK->CLK_CON0);
log_info("CLK_CON1 : %08x", JL_CLOCK->CLK_CON1);
log_info("CLK_CON2 : %08x", JL_CLOCK->CLK_CON2);
log_info("CLK_CON3 : %08x", JL_CLOCK->CLK_CON3);
log_info("PLL_CON : %08x", JL_CLOCK->PLL_CON);
log_info("PLL_CON1 : %08x", JL_CLOCK->PLL_CON1);
}
static u8 switch_hrc_flag = 0;
void enter_hrc_clock(void)
{
if(switch_hrc_flag == 0) {
// SFR(JL_CLOCK->CLK_CON0,10,3,0b001);
clk_set("sys", 24 * 1000000L);
// clk_dump();
local_irq_disable();
extern void switch_to_hrc();
switch_to_hrc();
// JL_ANA->WLA_CON8 &= ~BIT(0);
// SFR(JL_CLOCK->CLK_CON1,10,2,0b01);//uart btosc
// JL_UART0->BAUD = (24000000 / 1000000) / 4 - 1;
rc_mode_tick_init(1);
//TICK_CNT = 0;
//TICK_PRD = 16000000 / 100;
//TICK_CON = BIT(0);
// clk_dump();
JL_TIMER1->CON = BIT(14);
JL_TIMER1->PRD = 750;
JL_TIMER1->CNT = 0;
JL_TIMER1->CON = 0x9|(0b0011<<4);
switch_hrc_flag = 1;
local_irq_enable();
}
}
void exit_to_pll_clock(void){
if(switch_hrc_flag == 1) {
local_irq_disable();
//reset
PLL_EN(1);
delay(1); //>10us
PLL_REST(1); //复位释放(需在PLL EN使能10us后才能释放)
delay(10 + 10); //>300us
// clk_dump();
rc_mode_tick_init(0);
clk_set("sys", 96 * 1000000L);
// SFR(JL_CLOCK->CLK_CON1,10,2,0b00);//uart pll48
// JL_UART0->BAUD = (48000000 / 1000000) / 4 - 1;
JL_TIMER1->CON = BIT(14);
JL_TIMER1->PRD = 0x2ee0;
JL_TIMER1->CNT = 0;
JL_TIMER1->CON = 0x19;
switch_hrc_flag = 0;
local_irq_enable();
}
}
还需要添加.s文件到工程中编译
tick_time.S
【金山文档】 tick_time
https://kdocs.cn/l/cgRQ4Hmk4Tuc
提示goto __tick_irq_handler,无法找到源文件目前有V1.1.1版本的修改方法:
system_V1.1.1.rar
4、AC706系列FM收音效果差,基本调试思路:
答:
- FM匹配物料放FM天线端,用公版原理图上推荐的匹配参数;
- 功放跑AB类模式,没有其他DC电路干扰;
- 电源干净,地回路完整:VBAT、VDDIO的电容地最快最完整回到芯片地,确保地回路的完整性。
5、FM模式切换时钟源避开晶振倍频导致的96M干扰(有反馈问题再打)
AC695系列跑LRC时钟补丁说明_20231028175931.rar
701代码SDK修改待补充