KiCad文件
全屏
内容介绍
内容介绍
一、所选任务介绍
本项目以自主设计 PCB 的 NS800RT5039 单片机为核心,完成全部基础任务及多项额外扩展任务:
- 基础任务:UART 串口输出指定字符串、2MHz 互补 PWM 波形(50% 占空比 25% 占空)生成;
- 额外任务:RC 低通滤波器设计与 ADC 采集(2MHz PWM 不同占空比电压测量)、音频频谱分析 + 音乐播放 + 频率测试;
- 加分项:完成 NS800RT5039 开发板原理图设计、PCB 绘制、打样及测试全流程。
二、项目描述
本项目聚焦 NS800RT5039 芯片的高性能外设应用,自主搭建硬件平台并开发配套软件,实现 “硬件设计 - 功能开发 - 实测验证” 的完整闭环。项目核心目标是挖掘芯片在高频 PWM 控制、模拟信号采集、数字信号处理(DSP)等场景的应用潜力,通过自主设计 PCB 优化硬件适配性,最终实现串口通信、高频互补 PWM 输出、RC 滤波与 ADC 数据采集、音频频谱分析四大核心功能。
三、芯片选型 / 硬件介绍
核心芯片:
选用纳芯微 NS800RT5039 实时控制 MCU,该芯片基于 260MHz Arm Cortex-M7 内核,集成 eMath 硬件数学加速核;配备 16 对互补 PWM 输出(支持 100 皮秒高精度控制)、3 个 12 位 5MSPS ADC(INL/DNL±1.5LSB),完美匹配项目高频控制与高精度采集需求。
硬件组成:
- 核心模块:NS800RT5039 芯片、8MHz 无源晶振;
- 功能模块:RC 低通滤波器(1.6kΩ 电阻 + 10nF 电容)、驻极体麦克风、0.96寸O LCD 屏;
- 接口模块:USB-TTL 串口、 DAPLINK、PWM 输出测试端子、ADC 输入接口;
- PCB 设计:采用 2层板设计,电源层与地层分离,PWM 输出引脚远离模拟信号区,关键信号走线阻抗匹配,确保 2MHz 高频信号完整性。
四、方案框图 + 设计思路
1. 系统方案框图
2. 设计思路
- 核心控制:利用芯片高主频内核与丰富外设,实现多任务并行处理;
- PWM 与滤波:通过 ePWM 外设生成 2MHz 互补波形,RC 滤波器提取平均电压,ADC 采集并转换为电压值;
- 音频处理:麦克风采集音频信号,经 eMath 核完成 FFT 变换,将频谱数据映射到O LCD 屏;
- 数据验证:采用 “万用表实测 + ADC 采集” 双验证方式,确保数据准确性。
五、原理图、PCB 设计
- 原理图设计:基于 kicad 绘制,核心电路包括:
- PWM 电路:配置 ePWMA0/ePWMA1 为互补输出,预留死区时间配置接口;
- ADC 电路:ADC0 通道接入 RC 滤波器输出,串联 1.6kΩ 限流电阻;
- PCB 设计:
- 布局:核心芯片居中,电源模块、数字模块、模拟模块分区布局,减少干扰;
- 布线:电源走线宽度≥1mm,PWM 信号走线长度≤3cm,模拟地与数字地单点连接;
- 打样测试: PCB 打样(1.6mm 板厚,沉金工艺),焊接后经通断测试、电源稳定性测试合格。
六、软件流程图 + 调试软件说明 + 关键代码说明
1. 软件流程图

2. 调试软件
- 开发环境:Keil MDK 5.38(支持 Arm Cortex-M7 编译);
- 调试工具:DAPLINK、串口助手(波特率 115200)、带屏12指神探;
- 测试工具:数字万用表、12 指神探(PWM 波形捕获)。
3. 关键代码说明
- PWM 初始化(2MHz 50% 占空比互补输出):
void my_pwm_Init(void)
{
EPWM_setClockPrescaler(EPWM2, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_2); //pwm接入时钟
EPWM_setTimeBasePeriod(EPWM2, 64); //设置周期 - 对应2MHz
EPWM_setTimeBaseCounter(EPWM2, 0); //计数器初始值
EPWM_setTimeBaseCounterMode(EPWM2, EPWM_COUNTER_MODE_UP); //向上计数模式
EPWM_disablePhaseShiftLoad(EPWM2); //禁用移位偏移值
EPWM_setPhaseShift(EPWM2, 0); //相位偏移值为0
// 保持50%占空比
EPWM_setCounterCompareValue(EPWM2, EPWM_COUNTER_COMPARE_A, 32); //设置pwm1A的比较值
EPWM_setCounterCompareShadowLoadMode(EPWM2, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
// 保持50%占空比
EPWM_setCounterCompareValue(EPWM2, EPWM_COUNTER_COMPARE_B, 32); //设置pwm1B的比较值
EPWM_setCounterCompareShadowLoadMode(EPWM2, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
// 以下动作限定器配置保持不变
// 通道A配置 - 标准PWM
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
// 通道B配置 - 互补输出(与A相反)
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); // 改为在CMPA时变高
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
EPWM_setActionQualifierAction(EPWM2, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
/* 边缘延迟配置保持不变 */
EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM2, EPWM_RED_LOAD_ON_CNTR_ZERO);
EPWM_disableRisingEdgeDelayCountShadowLoadMode(EPWM2);
EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM2, EPWM_FED_LOAD_ON_CNTR_ZERO);
EPWM_disableFallingEdgeDelayCountShadowLoadMode(EPWM2);
my_pwm1_gpio_Init();
}
void my_pwm1_gpio_Init(void)
{
/* EPWM2A GPIO configuration */
GPIO_setAnalogMode(GPIO_2, GPIO_ANALOG_DISABLED);
GPIO_setPinConfig(GPIO_2_EPWM2_A);
GPIO_setPadConfig(GPIO_2, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(GPIO_2, GPIO_QUAL_SYNC);
/* EPWM1B GPIO configuration */
GPIO_setAnalogMode(GPIO_3, GPIO_ANALOG_DISABLED);
GPIO_setPinConfig(GPIO_3_EPWM2_B);
GPIO_setPadConfig(GPIO_3, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(GPIO_3, GPIO_QUAL_SYNC);
}
- ADCA通道0和1 pwm触发初始化(用于麦克风ADC采集,PWM输出搭配低通滤波):
#define myADC_SAMPLE_WINDOW 8U
#define myADC0_BASE ADCA
void myADC0_init(void)
{
/* ADC Initialization: Write ADC configurations and power up the ADC.
Set the analog voltage reference selection and ADC module's offset trims.
This function sets the analog voltage reference to internal
(with the reference voltage of 1.65V or 2.5V) or external for ADC. */
ADC_setVREF(ADCA, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);
/* Configures the analog-to-digital converter module prescaler. */
ADC_setPrescaler(ADCA, ADC_CLK_DIV_4);
/* Sets the timing of the end-of-conversion pulse */
ADC_setInterruptPulsePosMode(ADCA, ADC_PULSE_END_OF_CONV);
/* Powers up the analog-to-digital converter core. */
ADC_enableConverter(ADCA);
/* Delay for 1ms to allow ADC time to power up */
Delay_us(1000);
/* SOC Configuration: Setup ADC EPWM channel and trigger settings */
/* Disables SOC burst mode. */
ADC_disableBurstMode(ADCA);
/* Sets the priority mode of the SOCs. */
ADC_setSOCPriority(ADCA, ADC_PRI_ALL_ROUND_ROBIN);
/* Start of Conversion 0 Configuration */
/* Configures a start-of-conversion (SOC) in the ADC and its interrupt SOC trigger.
SOC number : 0
Trigger : ADC_TRIGGER_SW_ONLY
Channel : ADC_CH_ADCIN0
Sample Window : 8 SYSCLK cycles
Interrupt Trigger : ADC_INT_SOC_TRIGGER_NONE */
ADC_setupSOC(ADCA, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN0, 8U);
ADC_setInterruptSOCTrigger(ADCA, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_NONE);
/* Start of Conversion 1 Configuration */
/* Configures a start-of-conversion (SOC) in the ADC and its interrupt SOC trigger.
SOC number : 1
Trigger : ADC_TRIGGER_SW_ONLY
Channel : ADC_CH_ADCIN1
Sample Window : 8 SYSCLK cycles
Interrupt Trigger : ADC_INT_SOC_TRIGGER_NONE */
ADC_setupSOC(ADCA, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN1, 8U);
ADC_setInterruptSOCTrigger(ADCA, ADC_SOC_NUMBER1, ADC_INT_SOC_TRIGGER_NONE);
/* ADC Interrupt 1 Configuration
Source : ADC_SOC_NUMBER1
Interrupt Source : enabled
Continuous Mode : disabled */
ADC_setInterruptSource(ADCA, ADC_INT_NUMBER1, ADC_SOC_NUMBER1);
ADC_clearInterruptStatus(ADCA, ADC_INT_NUMBER1);
ADC_disableContinuousMode(ADCA, ADC_INT_NUMBER1);
ADC_enableInterrupt(ADCA, ADC_INT_NUMBER1);
}
/**
* @brief EPWM1 Configurations
*/
void EPWM_init(void)
{
SYSCON_UNLOCK;
/* Disable sync(Freeze clock to PWM as well) */
SYSCON_enableTbclkSync(SYSCON, false);
SYSCON_LOCK;
/* Enable EPWM1SOCA */
EPWM_enableADCTrigger(EPWM1, EPWM_SOC_A);
/* Enable TBCTR=CMPA event to genarate SOCA */
EPWM_setADCTriggerSource(EPWM1, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
/* Configure the SOC to occur on the first up-count event */
EPWM_setADCTriggerEventPrescale(EPWM1, EPWM_SOC_A, 1);
/* Set EPWM1 PRD = 2599U */
EPWM_setTimeBasePeriod(EPWM1, 12999);
/* Set EPWM1 CMPA = 1300U */
EPWM_setCounterCompareValue(EPWM1, EPWM_COUNTER_COMPARE_A, 1300);
/* Set the local ePWM module clock divider to /2 */
EPWM_setClockPrescaler(EPWM1, EPWM_CLOCK_DIVIDER_2, EPWM_HSCLOCK_DIVIDER_1);
/* Configure ePWM Counter runs in up-count mode. */
EPWM_setTimeBaseCounterMode(EPWM1, EPWM_COUNTER_MODE_UP_DOWN);
/* SYSCON configurations */
SYSCON_UNLOCK;
/* Enable SYSCON EPWM1SOCAEN */
SYSCON_enableEpwmSocA(SYSCON, SYSCON_EPWM1SOCAEN, true);
/* Enable sync and clock to PWM */
SYSCON_enableTbclkSync(SYSCON, true);
SYSCON_LOCK;
}
- ADC中断
uint16_t dars=0;
volatile uint8_t bufferFull_bos = 0;
double adc_v=0.0;
void adcA_ISR(void)
{
uint16_t numddd=0;
myADC0Results[index++] = ADC_readResult(ADCARESULT, ADC_SOC_NUMBER0);
dars=(dars+1)%1000;
if(!dars)
{
numddd=ADC_readResult(ADCARESULT, ADC_SOC_NUMBER1);
adc_v=(numddd/4095.0)*1.6;
printf("ADC:%.1f\n",adc_v); //解算出来的电压打印
//printf("ADC:%.d\n",numddd);
}
if(255 == index && bufferFull_bos == 0)
{
index = 0;
bufferFull_bos = 1;
bufferFull = 2;
}
else if(63 <= index && bufferFull_bos)
{
index = 1;
bufferFull_bos = 0;
bufferFull = 1;
}
ADC_clearInterruptStatus(ADCA, ADC_INT_NUMBER1);
if(true == ADC_getInterruptOverflowStatus(ADCA, ADC_INT_NUMBER1))
{
ADC_clearInterruptOverflowStatus(ADCA, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA, ADC_INT_NUMBER1);
}
}
七、实物演示及说明
基础功能演示:
- 串口输出:PC 串口助手稳定显示 “Hello, NOVOSENSE Wedesign project.”,波特率 115200,无丢包;

- PWM 波形:12 指神探捕获到 2MHz 互补波形,高低电平切换无重叠,占空比 50%;
RC 滤波与 ADC 采集:
- 实测数据:2MHz PWM 占空比 25% 时,万用表读数 0.8V,ADC 采集值 1024(计算电压 0.82V);占空比 50% 时,万用表 1.6V,ADC 采集值 2048(计算电压 1.65V),误差≤2%;
- 理论对比:根据公式 Vavg=Vref×DUTY(Vref=1.6V),3.3V 系统下 25% 占空比理论值 0.825V,50% 占空比 1.65V,实测值与理论值高度吻合;
- 音频功能演示:
- 音乐播放:OLCD 屏显示当前歌曲名称,LED 阵列随节奏律动;
- 频率测试:可检测 200Hz-2.4kHz 音频信号,LCD 屏实时显示频率值。
八、遇到的难点及解决方法
- 难点 1:2MHz 高频互补 PWM 波形出现导通重叠(直通风险);
- 解决:通过 EPWM 外设配置 100ns 死区时间,利用芯片硬件死区生成单元,避免上下桥臂同时导通;
- 难点 2:RC 滤波后电压纹波较大,ADC 采集波动;
- 解决:优化 RC 参数(1.6kΩ+10nF,截止频率 1.59kHz);
- 难点 3:音频信号噪声干扰频谱显示;
- 解决:麦克风电路增加二级放大(增益 40dB)与 50Hz 陷波滤波,利用 eMath 核的 FIR 滤波功能进一步降噪。
4.难点4:在官方开发板NS800RT509调试出50kHZ的pwm,但是在自己画的开发板实际产生的pwm只有2kHZ。
- 解决:更换外部晶振和搭配电容;
九、心得体会
本次项目实现了从硬件设计到软件开发的全流程实践,深刻体会到 NS800RT5039 芯片的高性能优势:eMath 核大幅提升了音频 FFT 运算效率,高精度 PWM 与 ADC 外设简化了高频控制与采集方案。自主设计 PCB 的过程中,我掌握了高速信号布线、电磁兼容设计的核心技巧,也认识到硬件与软件协同优化的重要性。
意见建议:
- 建议官方提供更详细的外设驱动例程(如 eMath 核 FFT 配置);
- 希望增加 NS800RT 系列芯片的在线技术支持,以及出给刚开始学习这个开发板提供相关配置视频;
通过本次项目,我不仅提升了嵌入式系统设计能力,更感受到自主创新的乐趣,未来将继续探索芯片在电机控制、电源转换等领域的深度应用。
软硬件
附件下载
test.rar
kile程序
团队介绍
我们是一支专注于嵌入式系统开发与硬件创新的专业队伍,在单片机应用、PCB 设计、数字信号处理等领域。以 NS800RT5095 芯片为核心,成功完成自主开发板设计及多任务功能实现,涵盖高频 PWM 控制、高精度 ADC 采集、音频频谱分析等方向,具备从硬件设计到软件调试的全流程落地能力,致力于在工业控制与消费电子领域探索芯片应用新场景。
团队成员
如风
评论
0 / 100
查看更多
猜你喜欢
基于纳芯微NS800RT5039评估板设计的音乐律动器该项目使用了纳芯微NS800RT5039评估板,c语言,实现了基础任务+音乐律动器的设计,它的主要功能为:使用epwm输出规定频率的互补PWM,用ADC采样麦克风制作的律动器,在OLED上显示频谱图和音乐的响度。
zxyyl
39
基于纳芯微NS800RT5039评估板实现PWM输出该项目使用了纳芯微NS800RT5039评估板,实现了PWM输出的设计,它的主要功能为:串口输出,输出PWM信号。
TetraPak
64
基于纳芯微微控制器NS800RT5039评估板设计音乐律动器(音乐频谱)该项目使用了纳芯微微控制器NS800RT5039评估板,实现了音乐律动器的设计,它的主要功能为:根据音乐节奏显示各频率分量。
游泳的鸟儿
37