一、项目介绍
该项目为使用微控制器芯片NS800RT5039 / 评估板NSSinePad-NS800RT5039 完成以下设计要求:
1.调用Uart串口,完成在串口输出 “Hello, NOVOSENSE Wedesign project.” 字符串任务。
2.调用ePWM外设,实现在对应输出端口,输出一对互补PWM波形,波形频率2MHz,占空比50%。并使用12指神探捕获对应波形截图未购买12指神探的可以用万用表电压档测量并拍照)。

评估板NSSinePad-NS800RT5039
二、项目设计思路
1.对于串口打印字符串任务,重定义fputc函数以实现printf函数调用uart打印字符串。
2.对于输出互补PWM波形任务,计算并得到预分频系数、重载值、比较值对ePWM外设进行配置。
3.对于使用12指神探任务,安装好固件,熟悉上位机的使用,对PWM进行捕获。
三、硬件介绍
微控制器芯片NS800RT5039
NS800RT5037/5039/5049/3025: 中端算力实时控制MCU
NS800RT5037/5039/5049/3025采用运行在200~260MHz的Cortex M7内核,配合自研的eMath浮点数学运算加速核,可以实现迅速的环路控制和高效的实时控制运算。高速高精度的ADC、100ps的高精度PWM、专用的PWM事件管理器跟高速比较器的快速联动可以保障每个高速环路的精准控制。

产品特性:
• 200~260MHz Cortex M7内核,核内32KB缓存
• eMATH支持各种浮点三角函数运算及FFT、卷积、矩阵运算
• 512KB Flash(带ECC), 388KB SRAM(带ECC),其中256KB TCM
• 2*16通道 DMA,串口支持DMA
• 3*12位快至 5M ADC,最大32通道
• 7*2个快速比较器
• 2*12位DAC
• 3路高带宽差分运放
• 最多32路PWM,其中16个100ps的高精度PWM
• 7个高速捕获口、2个QEP接口
• 8路Sigma-Delta滤波器
• 3个串口、2个高速串口/硬件LIN接口、1个CAN-FD、1个CAN2.0、3个I2C、3个SPI、1个QSPI、一个SDIO
• 支持AES128/192/256,支持SHA-1/SHA-2加密运算
• 支持真随机数产生器
• 支持安全启动
• 通过IEC60730安全认证
• 符合AECQ-100 Grade1设计
• 符合ISO26262 ASIL-B和IEC61508 SIL2设计
• 提供工业级和汽车级产品
功能框图:

评估板NSSinePad-NS800RT5039
NSSinePad-NS800RT5039/49 是基于 NS800RT5039/49 实时微控制器设计的旨在帮助用户快 速开展芯片学习、评估等工作的低成本开发板。基于该开发板,用户可以方便使用 NS800RT5039/49 实时微控制器的所有外设、内存。除实时微控制器芯片外,该开发板还具有 板载CAN 收发器(支持CAN2.0B 及 CAN-FD)、两个 5V 编码器(eQEP)接口芯片及板载 DAP Link 调试/仿真器。
开发板功能区域图:

四、方案框图

五、关键代码说明
1.重定义fputc函数:
//等待串口发送缓冲区为空后,将要发送的字符 ch 写入串口的数据寄存器
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
int fputc (int ch, FILE *f)
{
(void)f;
while (BOARD_SERIALCOM->STAT.BIT.TDRE == 0)
{
;
}
BOARD_SERIALCOM->DATA.WORDVAL = ch;
return ch;
}
#endif
需要注意的是:需要将uart的波特率设置为与电脑串口助手相同的波特率
#define BOARD_SERIALCOM_BAUDRATE (115200UL)
#define BOARD_SERIALCOM UART1
/* Set baudrate */
UART_setBaud(BOARD_SERIALCOM, BOARD_SERIALCOM_BAUDRATE);
2.对ePWM外设初始化
//ePWM参数
#define EPWM_CMPA EPWM_CMPB
#define EPWM_CMPB (EPWM_TIMER_TBPRD / 2)
#define EPWM_EDGEDELAY_A 0
#define EPWM_TIMER_TBPRD 130U /* PWM周期值 */
void EPWM_init(void)
{
EPWM_setClockPrescaler(myEPWM4_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
EPWM_setTimeBasePeriod(myEPWM4_BASE, EPWM_TIMER_TBPRD);
EPWM_setTimeBaseCounter(myEPWM4_BASE, 0);
EPWM_setTimeBaseCounterMode(myEPWM4_BASE, EPWM_COUNTER_MODE_UP);
EPWM_disablePhaseShiftLoad(myEPWM4_BASE);
EPWM_setPhaseShift(myEPWM4_BASE, 0);
EPWM_setCounterCompareValue(myEPWM4_BASE, EPWM_COUNTER_COMPARE_A, EPWM_CMPB);
EPWM_setCounterCompareShadowLoadMode(myEPWM4_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareValue(myEPWM4_BASE, EPWM_COUNTER_COMPARE_B, EPWM_CMPB);
EPWM_setCounterCompareShadowLoadMode(myEPWM4_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
EPWM_setActionQualifierAction(myEPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
EPWM_setDeadBandDelayPolarity(myEPWM4_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
EPWM_setDeadBandDelayMode(myEPWM4_BASE, EPWM_DB_RED, true);
EPWM_setRisingEdgeDelayCountShadowLoadMode(myEPWM4_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO);
EPWM_disableRisingEdgeDelayCountShadowLoadMode(myEPWM4_BASE);
EPWM_setRisingEdgeDelayCount(myEPWM4_BASE, EPWM_EDGEDELAY_A);
EPWM_setDeadBandDelayMode(myEPWM4_BASE, EPWM_DB_FED, true);
EPWM_setFallingEdgeDelayCountShadowLoadMode(myEPWM4_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO);
EPWM_disableFallingEdgeDelayCountShadowLoadMode(myEPWM4_BASE);
EPWM_setFallingEdgeDelayCount(myEPWM4_BASE, EPWM_EDGEDELAY_A);
}
这里的ePWM时钟分频和ePWM高速时钟分频都设置为1也就是不分频,则ePWM的时钟频率为系统时钟频率260Mhz。ePWM周期值设置为130模式设置为增计数模式,则输出的PWM频率为260Mhz/130 = 2Mhz。比较值设置为周期值的一半65则输出的PWM的占空比为50% 。这里的死区延时我设置成了0,是为了让两路PWM严格反相,占空比均为 50% 。
3. 12指神探的使用

这里需要注意的是对高频PWM进行捕获时需要将下面三路模拟捕获通道左键关闭。尤其在这个项目中2MHz的PWM,采用10倍与PWM的频率进行捕获,也就是两路20MHz,及其占用带宽所以需要将三路模拟捕获通道关闭。
4.主函数
int main(void)
{
/* 初始化器件时钟和外设 */
Device_init();
/* 禁用外设寄存器锁定 */
Device_unlockPeriphReg();
/* 禁用同步(同时冻结 PWM 时钟) */
SYSCON_UNLOCK;
SYSCON_enableTbclkSync(SYSCON, false);
SYSCON_LOCK;
/* 板级初始化 */
Board_init();
/* 外设初始化 */
peripheral_init();
/* 启用同步并为 PWM 提供时钟 */
SYSCON_UNLOCK;
SYSCON_enableTbclkSync(SYSCON, true);
SYSCON_LOCK;
printf("Hello, NOVOSENSE Wedesign project.\n");
printf("PWM Start!\n");
printf("PWM Freq:%dMHz\n",260/EPWM_TIMER_TBPRD);
printf("Duty Cycle:%d%%\n",EPWM_CMPA*100/EPWM_TIMER_TBPRD);
/* 中断初始化。禁用全局中断。 */
Interrupt_initModule();
/* 中断向量表初始化。向量表重映射。 */
Interrupt_initVectorTable();
/* 无限循环 */
while(1)
{
}
}
六、实物演示

示波器捕获PWM波

带屏12指神探接线

上位机显示的PWM波

串口助手接收到的串口信息
七、遇到的难点及解决方法
因为是首次使用纳芯微的产品,还是遇到了很多问题的。首先就是资料包内容的分类比较繁琐,有很多的套娃文件夹,且我发现了两套的数据手册和用户手册,这两套手册的版本尽然还不一样。其次是例程文件夹的设计也不够简单明了,例程嵌套了多层文件夹,若想要移植单个功能的例程工程操作较为复杂,且主流IDE对中文的适配不是很好,若直接在解压好的源文件中打开例程工程,大概率会由于有中文路径报错。当然!上述问题都是些基础问题,但是对于首次接触的小白还是会产生一些奇怪的问题,且这些问题还未涉及到代码层面还是有优化空间。
其他的代码层面遇到的问题和解决办法我都在 “五、关键代码说明” 处详细介绍了。
八、心得体会及建议
通过这次WeDesign 7活动体验了纳芯微NS800RT5039评估板,还是学习到了很多内容。起初只是知道这块MCU对标的是TI的C2000,所以对这款MCU很感兴趣。经过详细的了解,发现这款MCU确实非常强大,高速的浮点数学运算能力、高速高精度的ADC、100ps的高精度PWM等功能值得深入的学习和使用。由于是首次使用ePWM功能,好好的去将ePWM的各项属性学习了一下,学习到了ePWM的增计数和增减计数模式,实现输出中心对称的PWM;学习到了ePWM的死区控制,实现输出互补的一对PWM;学习到了ePWM的影子寄存器配置,实现影子寄存器到活动寄存器的同步更新,避免运行时产生毛刺。本次活动还使用到了12指神探,一款基于RP2040开发的带屏逻辑分析仪,小巧精致但功能强大!也是学习了逻辑分析仪的使用和上位机的配置。总的来说还是学习到了非常多的知识,和很多工具的使用。
建议就是希望硬禾学堂能够组织更多有趣的好玩的开发板活动,也希望今后可以将资料包内容做的言简意赅,方便大佬们使用也方便小白入门。
最后非常感谢硬禾学堂和纳芯微组织的这次活动!
资料链接
1. 12指神探资料:带显示屏的基于RP2040多功能嵌入式编程学习、硬件调试平台
2. 12指神探逻辑分析仪使用方法:基于RP2040的多通道逻辑分析仪的使用方法分享