- 2024-11-17
-
发表了主题帖:
【中科昊芯HXS320F28025C】电力电子中ADC的使用。
本帖最后由 jixulifu2 于 2024-11-17 23:54 编辑
一、DSP的ADC的过人之处:
在涉及模拟信号到数字信号转换的场景中。ADC(模数转换器)模块扮演着至关重要的角色。使用DSP做电力电子项目相对于传统性能孱弱的32单片机我总结了以下几个优势:
1.在电力电子系统中,需要对各种模拟信号(如电压、电流等)进行实时采集和处理。DSP的ADC模块可以快速、准确地将这些模拟信号转换为数字信号,供后续的数字信号处理算法使用。例如,HXS320F28025C的ADC模块可以实现高精度的模数转换,支持多种触发方式,EPWM SOCA触发,确保在特定时刻进行采样。
2.电力电子系统中的控制策略通常需要实时反馈和调整。DSP的ADC模块可以提供高精度和高频率的采样,使得控制算法能够基于最新的系统状态进行调整。例如,在逆变器控制中,通过ADC采集的电流和电压信号可以用于实现精确的闭环控制,提高系统的稳定性和效率。
3.电力系统中的电力质量监测是一个重要的应用领域。DSP的ADC模块可以用于实时监测电网的电压和电流波形,检测谐波、电压波动、频率偏差等问题。通过高速ADC采集的数据,DSP可以快速执行傅里叶变换(FFT)等算法,分析电网的电力质量。
4.在电力电子设备中,故障检测和保护是确保系统安全运行的关键。DSP的ADC模块可以实时监测关键参数,如电流、电压和温度,一旦检测到异常,可以立即触发保护机制。例如,通过逐波限流控制技术,DSP可以快速响应过载和短路情况,保护设备免受损坏。
二、中科昊芯HXS320的ADC了解:
12 位逐次逼近(SAR)型 ADC。包括通道选择 MUX、 采样保持(S/H)电路、 逐次逼近电路、 电压参考电路和其他模拟支持电路。 包装器由配置和控制 ADC 的数字电路组成。 这些电路
包括可编程转换逻辑、 结果寄存器、 模拟电路接口、 外设总线接口、 后处理电路以及其他片上模块接口。
每个 ADC 都具有以下功能:
•由 VREFHI 和 VREFLO 引脚设置的比率外部参考
•2.5V 或 3.3V 的可选内部参考
•单端信号转换
•输入多路复用器, 多达 16 个通道( 单端) 或 8 个通道( 差分)
•16 个可配置 SOC
•16 个可单独寻址的结果寄存器
•多个触发源
-S/W-软件立即启动
-所有 ePWMs-ADCSOC A 或 B
-GPIO XINT2
-CPU 计时器 0/1/2
-ADCINT1/2
•四个灵活的 PIE 中断
•突发模式
•四个后处理块, 每个块具有:
-饱和偏移校准
-设定点计算错误
-高、 低和过零比较, 具有中断和 ePWM 跳闸功能
-触发采样延迟捕获
最基础的EPWM触发ADC配置代码:
void Adc_config(void)
{
/*ADC参考电压配置为:ADC_REFERENCE_INTERNAL-内部参考电压,
* ADC_REFERENCE_3_3V-3.3V*/
ADC_setVREF(ADCA_BASE,ADC_REFERENCE_INTERNAL,ADC_REFERENCE_3_3V);
/*配置ADC时钟为ADC_CLK_DIV_2_0-2分频对应SYSCLK/8=20M*/
ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_8_0);
/*配置ADC中断脉冲模式:ADC_PULSE_END_OF_CONV-转换完成产生脉冲触发中断*/
ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);
/*ADC上电使能转换*/
ADC_enableConverter(ADCA_BASE);
/*延时1ms完成ADC模块上电*/
DEVICE_DELAY_US(5000);
/*屏蔽ADC突发模式*/
ADC_disableBurstMode(ADCA_BASE);
/*配置ADC_SOC转换优先级:ADC_PRI_ALL_ROUND_ROBIN-从A0开始循环转换*/
ADC_setSOCPriority(ADCA_BASE, ADC_PRI_ALL_ROUND_ROBIN);
/*配置SOC:ADC_SOC_NUMBER0-SOC0,
* ADC_TRIGGER_EPWM1_SOCA-通过EPWM_SOCA触发
* ADC_CH_ADCIN0-通过通道A0输入采样,
* 采样周期为8*SYSCLK(最大512*SYSCLK)*/
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER2,
ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN0, 8U);
/*配置SOC0触发源:ADC_INT_SOC_TRIGGER_NONE-不通过ADCINT内部触发*/
ADC_setInterruptSOCTrigger(ADCA_BASE, ADC_SOC_NUMBER2, ADC_INT_SOC_TRIGGER_NONE);
/*配置ADC_SOC_NUMBER0-SOC0中断源为ADC_INT_NUMBER1-ADCINT1*/
ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER2);
/*配置ADC_INT_NUMBER1-ADCINT1中断使能*/
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
/*清除ADC_INT_NUMBER1-ADCINT1中断状态*/
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
/*屏蔽ADC_INT_NUMBER1-ADCINT1连续模式*/
ADC_disableContinuousMode(ADCA_BASE, ADC_INT_NUMBER1);
}
最常用的ADC配置就不研究了,常用的32单片机碰到过压过流时,软件处理的方式对于时间的需求还是太高,不能做到瞬时响应,硬件过流检测又需要添加调试更多的电路,而HXS320内置了这种错误联防机制,可以第一时间切换EPWM输出,防止损坏器。
我们来看看例程中带有错误联防安全机制的配置
void main(void)
{
/*系统时钟初始化*/
Device_init();
/*GPIO锁定配置解除*/
Device_initGPIO();
/*关中断,清中断*/
Interrupt_initModule();
/*初始化中断向量表*/
Interrupt_initVectorTable();
/*中断入口地址INT_ADCA1,指向执行adcA1ISR中断服务程序*/
Interrupt_register(INT_ADCA1, &adcA1ISR);
#ifdef ENABLE_PROFILING
//
// Setup profiling GPIO
//
setupProfileGpio();
#endif
/*配置EPWM_GPIO*/
initEPWMGPIO();
/*配置ADC模块电压:ADC_REFERENCE_INTERNAL-内部参考电压
*ADC_REFERENCE_3_3V-参考电压3.3V */
ADC_setVREF(ADCA_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);
ADC_setVREF(ADCC_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);
/*ADC模块上电配置*/
configureADC(ADCA_BASE);
/*关闭外设时钟TBCLKSYNC,以便于EPWM配置*/
SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
/*配置EPWM1-EPWM3频率及SOC事件*/
EPWM_configureSignal(EPWM1_BASE, &pwmSignal1);
EPWM_configureSignal(EPWM2_BASE, &pwmSignal2);
EPWM_configureSignal(EPWM3_BASE, &pwmSignal3);
/*单次错误联防事件配置*/
configureOSHTripSignal(EPWM1_BASE);
/*周期错误联防事件配置*/
configureCBCTripSignal(EPWM2_BASE);
/*直接事件触发配置*/
configureDirectTripSignal(EPWM3_BASE);
/*配置ADC_SOC*/
configureADCSOC(ADCA_BASE, 2U, 8);
/*配置极限探测PPB后处理:SOC0,
* 高极限-3600-对应3.3V*3600/4096=2.9V
* 低极限-0-对应3.3V*0/4096=0V*/
configureLimitDetectionPPB(0U, 3600U, 0U);
/*中断使能INT_ADCA1*/
Interrupt_enable(INT_ADCA1);
/*实时打开全局中断*/
EINT;
ERTM;
/*使能外设时钟TBCLKSYNC,以完成EPWM配置,且时基同步*/
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
/*ADC_SOC_NUMBER0-SOC0通过软件强制触发*/
ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0);
do
{}
while(1);
}
void configureOSHTripSignal(uint32_t epwmBase)
{
/*配置XBAR_EPWM_MUX00_ADCAEVT1-EPWM_ADC复用事件
* 通过XBAR_TRIP7-事件7交叉开关输入*/
XBAR_setEPWMMuxConfig(XBAR_TRIP7, XBAR_EPWM_MUX00_ADCAEVT1);
/*使能XBAR_TRIP7-事件7交叉开关输入
* 通过XBAR_MUX00-交叉开关0输入*/
XBAR_enableEPWMMux(XBAR_TRIP7, XBAR_MUX00);
/*选择数据比较事件DC输入:
* 通过EPWM_DC_TRIP_TRIPIN7-事件7
* 触发EPWM_DC_TYPE_DCAH-DCAH事件*/
EPWM_selectDigitalCompareTripInput(epwmBase,
EPWM_DC_TRIP_TRIPIN7,EPWM_DC_TYPE_DCAH);
/*产生数字比较事件DCAEVT1的条件配置:
* EPWM_TZ_DC_OUTPUT_A1-EPWMxA_DCAEVT1
* EPWM_TZ_EVENT_DCXH_HIGH-DCAH置高*/
EPWM_setTripZoneDigitalCompareEventCondition(epwmBase,
EPWM_TZ_DC_OUTPUT_A1,EPWM_TZ_EVENT_DCXH_HIGH);
/*EPWM数字比较事件源:EPWM_DC_MODULE_A-DC事件A模块
*EPWM_DC_EVENT_1-DCAEVT1事件
*EPWM_DC_EVENT_SOURCE_ORIG_SIGNAL-不经过滤波的原信号*/
EPWM_setDigitalCompareEventSource(epwmBase,
EPWM_DC_MODULE_A,EPWM_DC_EVENT_1,
EPWM_DC_EVENT_SOURCE_ORIG_SIGNAL);
/*EPWM数字比较事件源同步:EPWM_DC_MODULE_A-DC事件A模块
*EPWM_DC_EVENT_1-DCAEVT1事件
*EPWM_DC_EVENT_INPUT_NOT_SYNCED-采用异步信号输入*/
EPWM_setDigitalCompareEventSyncMode( epwmBase,
EPWM_DC_MODULE_A,EPWM_DC_EVENT_1,
EPWM_DC_EVENT_INPUT_NOT_SYNCED);
/*TZ错误联防信号EPWM_TZ_SIGNAL_DCAEVT1使能*/
EPWM_enableTripZoneSignals(epwmBase, EPWM_TZ_SIGNAL_DCAEVT1);
/*TZ错误联防事件动作配置:
* EPWM_TZ_ACTION_EVENT_TZA-对于EPWMxA
* EPWM_TZ_ACTION_LOW-产生置低动作*/
EPWM_setTripZoneAction(epwmBase,
EPWM_TZ_ACTION_EVENT_TZA,
EPWM_TZ_ACTION_LOW);
/*TZ错误联防事件动作配置:
* EPWM_TZ_ACTION_EVENT_TZB-对于EPWMxB
* EPWM_TZ_ACTION_HIGH-产生置高动作*/
EPWM_setTripZoneAction(epwmBase,
EPWM_TZ_ACTION_EVENT_TZB,
EPWM_TZ_ACTION_HIGH);
/*清除TZ错误联防事件EPWM_TZ_FLAG_DCAEVT1标志*/
EPWM_clearTripZoneFlag(epwmBase, EPWM_TZ_FLAG_DCAEVT1);
/*清除TZ错误联防事件EPWM_TZ_OST_FLAG_DCAEVT1-单次触发标志*/
EPWM_clearOneShotTripZoneFlag(epwmBase, EPWM_TZ_OST_FLAG_DCAEVT1);
/*TZ错误联防事件中断类型:EPWM_TZ_INTERRUPT_OST-单次错误联防中断*/
EPWM_enableTripZoneInterrupt(epwmBase, EPWM_TZ_INTERRUPT_OST);
}
通过XBAR将ADC与PWM信号切断相联动
下载程序进开发板
AI0低于2.9V时EPWM输出5khz 占空比CMPA=70%,CMPB=50%,短接AI0与VCC后,触发联防,为低电平
-
发表了主题帖:
中科昊芯HXS320F28025C的高分辨率脉冲宽度调制器( HRPWM)
HRPWM和普通PWM都是用于控制电机速度、电力信号、灯光亮度等的脉冲宽度调制技术,HRPWM特别适用于需要极高精度和快速响应的应用,如高端电机控制、精密位置控制、高性能开关电源等。中科昊芯HXS320F28025C集成了HRPWM功能,这些集成模块提供了更多的功能、故障保护等。
HRPWM和普通PWM的主要区别在于分辨率、精度、响应时间,这决定了他们的应用场景不同,查阅F280参考手册可以看到官方给出的对比表格
一、理论计算:常用32单片机F1系列TIM8,TIM1挂在APB2上,理论最大频率72Mhz,1/72Mhz 周期时间≈14纳秒,生成100KHZ的PWM波,理论精度在0.3%,中央计数还要对半,可以说是很低了。跟日益增长的精细化控制要求渐行渐远了。目前电力电子/电机领域,高频化趋势明显。
根据手册宣传,当PWM分辨率低于9~10位时,通常需要使用HRPWM,ePWM外设设备用于执行数学上等同于数模转换器的功能DAC,HRPWM基于微边沿定位( MEP) 技术。 MEP逻辑能够通过细分传统PWM发生器的一个粗略系统时钟来非常精细地定位边沿。
二、配置HXS320F28025C的HRPWM
查阅手册,可以发现HRPWM是一个比较复杂的模块,各种陌生寄存器,不同配置模式整整塞了200页左右。根据认知负荷理论,我们先易后难,忽略斩波捕获,安全锁、滤波等配置,先把最简单的程序跑起来再说。
提取关于手册中关于HRTIM有用的片段:
HRTIME系统总框图
HRTIME源时钟框图
HRPWM的MEP由六个扩展寄存器控制。 这些HRPWM寄存器与用于控制PWM操作的16位TBPH、 TBPRD、 CMPA、 CMPBM、 DBREDM和DBFEDM寄存器串联.
打开中科昊芯提供的例程库发现一个比较奇怪的问题,开发板型号确认为HX320F280025CEDC,官方例程库中有CEDB,CEDC,CEDD三种尾标,烧写CEDC中的LED闪烁程序一切正常,开发板对应的LED闪烁,烧写相同文件夹内ADC/EPWM/HRTIME等例程提示失败:
尝试烧写CEDB文件夹内程序,提示禁止烧写,CEDD内程序可以正常烧写但无法运行,真是比较奇怪的BUG,也许是我编译器的配置问题,或者是厂家在打包例程的时候弄错了?
没有办法,那就自己移植一下吧,也能加深对库的理解。
根据外设配置经验,三部走:
①IO口配置
void epwm_gpio(void)
{
/*配置GPIO0为EPWM1A*/
GPIO_setPinConfig(GPIO_0_EPWM1_A);
GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(0, GPIO_QUAL_SYNC);
/*配置GPIO1为EPWM1B*/
GPIO_setPinConfig(GPIO_1_EPWM1_B);
GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(1, GPIO_QUAL_SYNC);
/*配置GPIO2为EPWM2A*/
GPIO_setPinConfig(GPIO_2_EPWM2_A);
GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(2, GPIO_QUAL_SYNC);
/*配置GPIO3为EPWM2B*/
GPIO_setPinConfig(GPIO_3_EPWM2_B);
GPIO_setPadConfig(3, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(3, GPIO_QUAL_SYNC);
/*配置GPIO4为EPWM3A*/
GPIO_setPinConfig(GPIO_4_EPWM3_A);
GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(4, GPIO_QUAL_SYNC);
/*配置GPIO5为EPWM3B*/
GPIO_setPinConfig(GPIO_5_EPWM3_B);
GPIO_setPadConfig(5, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(5, GPIO_QUAL_SYNC);
/*配置GPIO6为EPWM4A*/
GPIO_setPinConfig(GPIO_6_EPWM4_A);
GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(4, GPIO_QUAL_SYNC);
/*配置GPIO7为EPWM4B*/
GPIO_setPinConfig(GPIO_7_EPWM4_B);
GPIO_setPadConfig(7, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(7, GPIO_QUAL_SYNC);
}
把IO0~IO7分别设置为EPWM1~4的AB双通道
②HRTIME配置
void hrpwm_config(uint32_t epwm_base,uint32_t epwm_tbprd,uint32_t epwm_cmpa,
uint32_t epwm_cmpb,uint32_t epwm_tbphs,
uint32_t ET_interruptSource,uint32_t ET_eventCount,
HRPWM_Channel channel,HRPWM_MEPEdgeMode mepEdgeMode_A)
{
/*HRPWM仿真模式:自由运行*/
HRPWM_setEmulationMode(epwm_base, EPWM_EMULATION_FREE_RUN);
/*EPWM1时基分频配置:低速时钟EPWM_CLOCK_DIVIDER_1-1分频,高速时钟EPWM_HSCLOCK_DIVIDER_1-1分频*/
HRPWM_setClockPrescaler(epwm_base, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
/*EPWM周期配置:SYSCLK/CLKDIV/HSPCLKDIV/TBPRD/2=160M/1/1/99/2=800kHz*/
EPWM_setTimeBasePeriod(epwm_base, epwm_tbprd);
/*HRPWM时基初值:TBCTR=0*/
HRPWM_setTimeBaseCounter(epwm_base, 0);
/*HRPWM时基计数模式:向上向下计数*/
HRPWM_setTimeBaseCounterMode(epwm_base, EPWM_COUNTER_MODE_UP_DOWN);
/*HRPWM相位禁止装载:TBPHSHRLOADE=0*/
HRPWM_disablePhaseShiftLoad(epwm_base);
/*高精度HRPWM相移:TBPHSHR=0*/
HRPWM_setPhaseShift(epwm_base, epwm_tbphs);
/*EPWM比较值CMPA配置:CMPA=50-占空比50%*/
EPWM_setCounterCompareValue(epwm_base, EPWM_COUNTER_COMPARE_A, epwm_cmpa);
/*EPWM比较值CMPA装载点配置:在EPWM_COMP_LOAD_ON_CNTR_ZERO_PERIOD-TBCTR=0或TBPRD-零或周期值时装载*/
HRPWM_setCounterCompareShadowLoadMode(epwm_base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO_PERIOD);
/*EPWM比较值CMPB配置:CMPB=50-占空比50%*/
EPWM_setCounterCompareValue(epwm_base, EPWM_COUNTER_COMPARE_B, epwm_cmpb);
/*EPWM比较值CMPB装载点配置:在EPWM_COMP_LOAD_ON_CNTR_ZERO_PERIOD-TBCTR=0或TBPRD-零或周期值时装载*/
HRPWM_setCounterCompareShadowLoadMode(epwm_base, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO_PERIOD);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO-TBCTR=零时
* EPWM_AQ_OUTPUT_NO_CHANGE-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD-TBCTR=周期值时
* EPWM_AQ_OUTPUT_NO_CHANGE-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA-向上计数时TBCTR=CMPA事件时
* EPWM_AQ_OUTPUT_HIGH,-输出置高动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA-向下计数时TBCTR=CMPA事件时
* EPWM_AQ_OUTPUT_LOW,-输出置低动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB-向上计数时TBCTR=CMPB事件时
* EPWM_AQ_OUTPUT_NO_CHANGE,-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB-向下计数时TBCTR=CMPB事件时
* EPWM_AQ_OUTPUT_NO_CHANGE,-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_A-EPWM1A
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO时计数TBCTR=ZERO-零事件时
* EPWM_AQ_OUTPUT_NO_CHANGE,-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_B-EPWM1B
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD时计数TBCTR=PERIOD-周期事件时
* EPWM_AQ_OUTPUT_NO_CHANGE,-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_B-EPWM1B
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA-向上计数TBCTR=CMPA事件时
* EPWM_AQ_OUTPUT_NO_CHANGE,-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_B-EPWM1B
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA-向下计数TBCTR=CMPA事件时
* EPWM_AQ_OUTPUT_NO_CHANGE,-不产生动作*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_B-EPWM1B
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB-向上计数TBCTR=CMPB事件时
* EPWM_AQ_OUTPUT_LOW,-置低*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
/*HRPWM动作配置:EPWM_AQ_OUTPUT_B-EPWM1B
* 在EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB-向下计数TBCTR=CMPB事件时
* EPWM_AQ_OUTPUT_HIGH,-置高*/
HRPWM_setActionQualifierAction(epwm_base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
/*EPWM事件中断使能*/
EPWM_enableInterrupt(epwm_base);
/*EPWM事件中断选择:在CTR=0时触发中断*/
EPWM_setInterruptSource(epwm_base,ET_interruptSource);
/*EPWM事件中断次数选择:每次进中断触发一次,最多可支持15次*/
EPWM_setInterruptEventCount(epwm_base,ET_eventCount);
/*HRPWM使能自动转换:AUTOCONV=1*/
HRPWM_enableAutoConversion(epwm_base);
/*HRPWM MEP微边沿定位选择:HRPWM_CHANNEL_A-通道A
* HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE-双边沿定位*/
HRPWM_setMEPEdgeSelect(epwm_base, channel, mepEdgeMode_A);
/*HRPWM 计数比较装载:HRPWM_CHANNEL_A-通道A
* HRPWM_LOAD_ON_CNTR_ZERO_PERIOD-在CTR=零或周期值时装载影子模式*/
HRPWM_setCounterCompareShadowLoadEvent(epwm_base, channel, HRPWM_LOAD_ON_CNTR_ZERO_PERIOD);
/*HRPWM 使能周期控制:HRPE=1*/
HRPWM_enablePeriodControl(epwm_base);
}
/*HRPWM配置:TBPRD=99-频率800kHz,CMPA=50,CMPB=50-占空比50%
* 相位偏移:TBPHS=0,
* 事件中断:EPWM_INT_TBCTR_ZERO-在CTR=0时触发,1-每周期触发一次中断
* 通道选择:HRPWM_CHANNEL_A-通道A
* MEP微边沿定位:HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE-双边沿定位*/
hrpwm_config(EPWM1_BASE,99,50,50,0,
EPWM_INT_TBCTR_ZERO,1,
HRPWM_CHANNEL_A,HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);
/*HRPWM配置:TBPRD=99-频率800kHz,CMPA=50,CMPB=50-占空比50%
* 相位偏移:TBPHS=0,
* 事件中断:EPWM_INT_TBCTR_PERIOD-在CTR=周期值时触发,1-每周期触发一次中断
* 通道选择:HRPWM_CHANNEL_A-通道A
* MEP微边沿定位:HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE-双边沿定位*/
hrpwm_config(EPWM2_BASE,99,50,50,0,
EPWM_INT_TBCTR_PERIOD,1,
HRPWM_CHANNEL_A,HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);
/*HRPWM配置:TBPRD=99-频率800kHz,CMPA=50,CMPB=50-占空比50%
* 相位偏移:TBPHS=0,
* 事件中断:EPWM_INT_TBCTR_U_CMPA-向上计数时CTR=CMPA时触发,1-每周期触发一次中断
* 通道选择:HRPWM_CHANNEL_A-通道A
* MEP微边沿定位:HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE-双边沿定位*/
hrpwm_config(EPWM3_BASE,99,50,50,0,
EPWM_INT_TBCTR_U_CMPA,1,
HRPWM_CHANNEL_A,HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);
/*HRPWM配置:TBPRD=99-频率800kHz,CMPA=50,CMPB=50-占空比50%
* 相位偏移:TBPHS=0,
* 事件中断:EPWM_INT_TBCTR_D_CMPA-向下计数时CTR=CMPA时触发,1-每周期触发一次中断
* 通道选择:HRPWM_CHANNEL_A-通道A
* MEP微边沿定位:HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE-双边沿定位*/
hrpwm_config(EPWM4_BASE,99,50,50,0,
EPWM_INT_TBCTR_D_CMPA,1,
HRPWM_CHANNEL_A,HRPWM_MEP_CTRL_RISING_AND_FALLING_EDGE);
以上是一些EPWM基本信息,给定800khz频率,50%占空比,中断触发事件,双边沿微定位,接下来是在中断函数中对占空比进行更新
/****对照组①*****/
__interrupt void epwm1ISR(void)
{
epwm1_ctr++;
for(periodFine = 0.2; periodFine < 0.9; periodFine += 0.01)
{
DEVICE_DELAY_US(1000);
float32_t count = ((EPWM_TIMER_TBPRD-1) << 8UL) + (float32_t)(periodFine * 256);
uint32_t compCount = count;
HRPWM_setTimeBasePeriod(EPWM1_BASE, compCount);
}
EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}
/****对照组②*****/
__interrupt void epwm2ISR(void)
{
epwm2_ctr++;
EPWM_clearEventTriggerInterruptFlag(EPWM2_BASE);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
}
EPWM1中断函数内每次循环从0.2自增到0.9,步进0.01,移植完可以正常烧录了。
在家里写的文章,家中只有普源最入门的DS1054Z,达不到高精度的要求,波形讲究着看吧。
[localvideo]5f3e7a95224207ac60280fd2dd5a8159[/localvideo]
- 2024-08-18
-
发表了主题帖:
【中科昊芯HXS320F28025C】电机FOC开环
本帖最后由 jixulifu2 于 2024-8-18 23:36 编辑
Field-Oriented Control (FOC) —— 磁场定向控制
磁场定向控制(Field-Oriented Control,简称FOC)是一种先进的电机控制策略,主要用于交流电机(如感应电机和永磁同步电机)的高性能控制。FOC的主要目的是通过精确控制电机的磁场和转矩,来实现电机的高效和精确控制。
FOC的工作原理
FOC的核心思想是将电机的旋转坐标系(dq坐标系)与电机的磁场方向对齐,从而将电机的多相(通常是三相)电流分解成两个独立的分量:励磁电流(d轴电流)和转矩电流(q轴电流)。这种分解使得电机的控制变得更加直观和简单,因为可以通过单独控制这两个分量来分别控制电机的磁场和转矩。
下面是FOC经典框图
HXS320F280025C是昊芯浮点DSC平台上的最新产品,基于自主研发的H28x内核,32位浮点RISC-V DSP架构,支持三角函数数学单元和CRC扩展指令集,完美适配FOC。该片增加了可配置逻辑模块(CLB),用户可添加自定义逻辑:支持多种通信端口,增强型控制外设,可满足电机驱动/控制、光伏逆变器和数字电源等行业的产品布局;基于FPU浮点处理单元,支持FOC算法、有感/无感角度分析、多电平控制、复杂电力电子拓扑算法以及宽带半导体驱动等应用。
今天我们手撸一个简易FOC开环框架:
思路解析解析:
刨去三环,编码器和3相全桥电路,我们要实现的是输入Ud.Uq,angle,输出ABC桥控制信号,也就是占空比信息。
Ud、Uq:通常称为 dq 坐标系。这个坐标系包括 d 轴(励磁轴)和 q 轴(转矩轴)。Ud 表示 d 轴上的电压分量,Uq 是施加在 q 轴上的电压分量,用于控制转矩电流 Iq。转矩电流 Iq 与电机产生的转矩有关,通过控制 Uq,可以调整电机的转矩。这两个值是我们人为设定的,所以只需要在后面代码中传入参数计算就可以。
Ud、Uq与Uαβ的关系:无刷电机通常由UVW三相组成,为了方便计算,需要把三相中每一项的分量隐射到一个直角坐标系Uα,Uβ中,使用我们最常见的三角函数解一下,如下图示意
公式:
Uα=Udcos(θ)−Uqsin(θ)
Uβ=Udsin(θ)+Uqcos(θ)
Uα 和 Uβ 分别是 αβ 坐标系下的电压分量。
Ud和 Uq分别是 dq 坐标系下的电压分量。
θ 是电机定子磁场角度。
求出Uα和Uβ后传入SVPWM模块
SVPWM介绍:SVPWM的核心是将电机所需的电压表示为一系列空间矢量,并通过选择适当的电压矢量来合成期望的输出电压。这种方法能够更高效地利用逆变器的电压和电流容量,进而提高电机驱动系统的整体效率。
放两张教材里的图吧,详细介绍的话可以单独开一个篇章,有兴趣的小伙伴自行查看吧
接下来是Clark变换:
主要用于将三相静止坐标系下的信号转换到两相静止坐标系下,理解了Clark也就理解了反Park
减少维度:从三个变量减少到两个变量,简化了控制系统的设计。
保持功率不变:Clark变换是等功率变换,即变换前后系统的总功率保持不变。
便于控制:两相坐标系下的信号更容易被控制算法处理,特别是对于矢量控制技术而言
接下来就愉快的手撸代码吧:
延续上一期的工程,新建一个FOC.c和FOC.h
#include "FOC.h"
#include <math.h>
#define PWM_Period
#define _PI 3.14159265359
#define _PI_2 1.57079632679
#define _PI_3 1.0471975512
#define _2PI 6.28318530718
#define _3PI_2 4.71238898038
#define _PI_6 0.52359877559
#define _SQRT3 1.73205080757
float voltage_power_supply;
// 设置PWM
// 输入参数:
// - Uq: q轴电压分量
// - Ud: d轴电压分量
// - angle_el: 电角度
void SetSVPWM(float Uq, float Ud, float angle_el)
{
float Uref;
float U_alpha,U_beta;
float T0,T1,T2;
float Ta,Tb,Tc;
int sector;
//反Park
U_alpha=Ud*cos(angle_el)-Uq*sin(angle_el);
U_beta=Ud*sin(angle_el)+Uq*cos(angle_el);
//计算参考电压矢量的幅值
Uref=_sqrt(U_alpha*U_alpha + U_beta*U_beta) / voltage_power_supply;
//六边形的内切圆(SVPWM最大不失真旋转电压矢量赋值)根号3/3
if(Uref> 0.577)Uref= 0.577;
if(Uref<-0.577)Uref=-0.577;
//判断参考电压矢量所在扇区:
angle_el = Angle_deal(angle_el+_PI_2);
sector = (angle_el / _PI_3) + 1;
//计算两个相邻电压矢量作用时间
T1 = _SQRT3*sin(sector*_PI_3 - angle_el) * Uref;
T2 = _SQRT3*sin(angle_el - (sector-1.0)*_PI_3) * Uref;
T0 = 1 - T1 - T2;
switch(sector)
{
case 1:
Ta = T1 + T2 + T0/2;
Tb = T2 + T0/2;
Tc = T0/2;
break;
case 2:
Ta = T1 + T0/2;
Tb = T1 + T2 + T0/2;
Tc = T0/2;
break;
case 3:
Ta = T0/2;
Tb = T1 + T2 + T0/2;
Tc = T2 + T0/2;
break;
case 4:
Ta = T0/2;
Tb = T1+ T0/2;
Tc = T1 + T2 + T0/2;
break;
case 5:
Ta = T2 + T0/2;
Tb = T0/2;
Tc = T1 + T2 + T0/2;
break;
case 6:
Ta = T1 + T2 + T0/2;
Tb = T0/2;
Tc = T1 + T0/2;
break;
default: // 错误状态
Ta = 0;
Tb = 0;
Tc = 0;
}
//输出PWM,配置占空比
EPWM_setCounterCompareValue(epwm1Info.epwmModule, EPWM_COUNTER_COMPARE_A, Ta*PWM_Period);
EPWM_setCounterCompareValue(epwm2Info.epwmModule, EPWM_COUNTER_COMPARE_A, Tb*PWM_Period);
EPWM_setCounterCompareValue(epwm3Info.epwmModule, EPWM_COUNTER_COMPARE_A, Tc*PWM_Period);
}
//将输入的角度 angle 归一化到 [0, 2π) 区间内。
float Angle_deal(float angle)
{
float a = fmod(angle, _2PI);
return a >= 0 ? a : (a + _2PI);
}
代码中并没有角度获得方式,可以在主循环while(1)里模拟一个自增的开环角度,当然也可以来自编码器、霍尔或者无传感器算法估算的转子位置。
受限于手头并没有实物,我们就不做演示了。
- 2024-08-10
-
发表了主题帖:
【中科昊芯HXS320F28025C】PWM实现;死区设置。
EPWM模块
PWM是一种脉宽调制技术,广泛应用于电机控制、LED亮度调节、音频放大等领域。PWM的基本原理是通过改变脉冲信号的宽度来调节输出功率,从而实现对负载的有效控制。大部分MCU都内置了PWM功能(如STM32,ARDUINO等),可以直接通过专用的定时器或外围设备来生成PWM信号。这些MCU的PWM功能通常只能提供较为一般的功能。中科昊芯HXS320F28025C内置了增强型脉宽调制器(ePWM),相比市面常见的MCU,功能更加强,配置更灵活,安全保护更完善。更适合越来越复杂的电力电子与电机控制。
中科昊芯HXS320F28025C的增强型脉宽调制器(ePWM)有以下几个子模块:
•时基子模块 Time-Base
•计数器比较子模块Counter Compare
•动作限定子模块Action Qualifier
•死区发生器子模块Dead-Band Generator
•PWM斩波器(PC)子模块 PWM Chopper
•错误联防子模块Trip Zone
•事件触发子模块Event Trigger
•数字比较子模块Digital Compare
每个ePWM模块都支持以下功能:
•带周期和频率控制的专用16位时基计数器
•两个PWM输出(EPWMxA和EPWMxB),可配置为:
–两个独立的PWM输出,单边操作
–两个独立的PWM输出,双边对称模式
–一个独立的PWM输出,双边不对称模式
•通过软件对PWM信号进行异步超驰控制。
•对于其他ePWM模块的可编程的相位控制(滞后或超前)。
•逐周期地进行硬件锁定(同步)的相位关系。
•具有独立的上升沿和下降沿延迟控制的死区功能。
•在错误联防情况下,可编程的逐周期错误联防和单次错误联防。
•错误联防条件下,可强制PWM输出高、低或高阻状态逻辑电平。
•所有事件均可触发CPU中断和ADC转换开始(SOC)
•可编程的事件预分频可最大程度地减少中断时的CPU开销。
•通过高频载波信号进行PWM斩波,用于脉冲变压器栅极驱动
内部框图如下:
更多关于中科昊芯HXS320F28025C的EPWM的信息,可以自行查阅datasheet。
PWM信号由一系列周期性的脉冲组成,每个脉冲都有固定的周期T,脉冲的宽度(即高电平持续的时间)可以根据需要进行调节。脉冲的宽度与周期的比例称为占空比(Duty Cycle),占空比决定了输出信号的平均电压值。例如,如果脉冲宽度为周期的一半,则占空比为50%,输出信号的平均电压为电源电压的一半。我们配置输出一个1khz,占空比50%的PWM信号。
F28025C主频160Mhz,预分频16,高速分频10,160Mhz/16/10 = 1Mhz.
设置时基周期,500, 1M/(500*2)=1KHz = 1ms一个周期
占空比设置为50%
EPWM1设置在IO0.0和0.1上输出互补信号
/*设置时钟分频 时钟分频/16,高速时钟分频/10,160M/16/10=1M*/
EPWM_setClockPrescaler(myEPWM1_BASE, EPWM_CLOCK_DIVIDER_16, EPWM_HSCLOCK_DIVIDER_10);
/*设置时基周期,500, 1M/(500*2)=1KHz*/
EPWM_setTimeBasePeriod(myEPWM1_BASE, 500);
EPWM_setTimeBaseCounter(myEPWM1_BASE, 0);
/*设置时基计数模式,上下计数*/
EPWM_setTimeBaseCounterMode(myEPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
EPWM_disablePhaseShiftLoad(myEPWM1_BASE);
EPWM_setPhaseShift(myEPWM1_BASE, 0);
/*设置计数器比较值,COMPARE_A,500*/
EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_A, 250);
EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
/*设置计数器比较值,COMPARE_B,1500*/
EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_B, 250);
EPWM_setCounterCompareShadowLoadMode(myEPWM1_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
/*ePWM1A,输出引脚置低,时基计数器等于0*/
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
/*ePWM1A,输出引脚置高,时基计数器上升时等于CMPA*/
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
/*ePWM1A,输出引脚置低,时基计数器下降时等于CMPA*/
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
/*ePWM1B,输出引脚置低,时基计数器等于0*/
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
/*ePWM1B,输出引脚置高,时基计数器上升时等于CMPA*/
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
/*ePWM1B,输出引脚置低,时基计数器下降时等于CMPA*/
EPWM_setActionQualifierAction(myEPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
更改GPIO功能与开启时钟代码:
GPIO_setPinConfig(GPIO_0_EPWM1_A);
GPIO_setPinConfig(GPIO_1_EPWM1_B);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
同时开启一个板载LED灯闪烁,可以观察程序是否在运行。
GPIO_setPinConfig(GPIO_31_GPIO31);
GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(31, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(31, GPIO_QUAL_SYNC);
GPIO_writePin(31,1);
for(;;)
{
GPIO_togglePin(31);
for(number = 0; number < 500; number ++)
DEVICE_DELAY_US(1000);
}
程序写好后点击DOWNLOAD,可以看到开发板板载红灯闪烁,证明程序已经正常运行,接上示波器查看IO00和IO01波形。
可以看到正常输出1khz的占空比50%的波形。
死区的概念:
简单解释:通常,大功率电机、变频器,末端都是由大功率管、IGBT等原件组成的
H桥或3湘桥,每个桥的上半桥和下半桥是绝对不能相同的,但高速的PWM驱动信号在达到功率元件的控制基时,往往会由于各种各样的原因产生延迟的效果,造成某个半桥原件在应该关断时没有关断,造成功率元件烧毁
死区就是在上半桥关断后,延迟一段时间在打开下半桥或在下半桥关断后,延迟一段时间再打开上半桥,从而避免功率元件烧毁,这段延迟时间就是死区
中科昊芯HXS320F28025C自带死区产生模块
/*设置死区延时极性,死区下降沿,极性反向*/
EPWM_setDeadBandDelayPolarity(myEPWM1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
/*设置死区延时模式,死区上升沿延时,开启*/
EPWM_setDeadBandDelayMode(myEPWM1_BASE, EPWM_DB_RED, true);
/*设置死区上升沿延时数,*/
EPWM_setRisingEdgeDelayCount(myEPWM1_BASE, 100);
/*设置死区延时模式,死区下降沿延时,开启*/
EPWM_setDeadBandDelayMode(myEPWM1_BASE, EPWM_DB_FED, true);
/*设置死区下降沿延时数,*/
EPWM_setFallingEdgeDelayCount(myEPWM1_BASE, 100);
再次查看波形
图中红线框内的时间差即为死区时间,可以有效防止MOS管频繁开关导致的损坏。
- 2024-07-14
-
发表了主题帖:
【中科昊芯HXS320F28025C】系统初始化函数学习和熟悉库函数风格
本帖最后由 jixulifu2 于 2024-7-14 16:39 编辑
上一章点灯调试串口的过程中,跳过了系统初始化部分。今天就来一起过一下吧。
0x00: Device_init()中的函数:
//
// Disable the watchdog
//
SysCtl_disableWatchdog();
//
// Call Device_cal function when run using debugger
// This function is called as part of the Boot code. The function is called
// in the Device_init function since during debug time resets, the boot code
// will not be executed and the gel script will reinitialize all the
// registers and the calibrated values will be lost.
// Sysctl_deviceCal is a wrapper function for PMUTrims_cal OscTrims_cal
//
SysCtl_deviceCal();
//
// Call Flash Initialization to setup flash waitstates. This function must
// reside in RAM.
//
Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
//
// Set up PLL control and clock dividers
//
SysCtl_setClock(DEVICE_SETCLOCK_CFG);
//
// Make sure the LSPCLK divider is set to the default (divide by 4)
//
SysCtl_setLowSpeedClock(SYSCTL_LSPCLK_PRESCALE_4);
//
// These asserts will check that the #defines for the clock rates in
// device.h match the actual rates that have been configured. If they do
// not match, check that the calculations of DEVICE_SYSCLK_FREQ and
// DEVICE_LSPCLK_FREQ are accurate. Some examples will not perform as
// expected if these are not correct.
//
ASSERT(SysCtl_getClock(DEVICE_OSCSRC_FREQ) == DEVICE_SYSCLK_FREQ);
ASSERT(SysCtl_getLowSpeedClock(DEVICE_OSCSRC_FREQ) == DEVICE_LSPCLK_FREQ);
//
// Turn on all peripherals
//
Device_enableAllPeripherals();
//
// Lock VREGCTL Register
// The register VREGCTL is not supported in this device. It is locked to
// prevent any writes to this register
//
ASysCtl_lockVREG();
static inline void
SysCtl_disableWatchdog(void)
{
EALLOW;
//
// Set the disable bit.
//
HWREG(WD_BASE + SYSCTL_O_WDCR) = (HWREG(WD_BASE + SYSCTL_O_WDCR) & ~0x80)
| (SYSCTL_WD_CHKBITS | SYSCTL_WDCR_WDDIS);
EDIS;
}
使用静态+内联修饰函数,确保代码只提供接口,不能修改。内联修饰优化效率。
EALLOW;EDIS;是宏定义的汇编代码。
跳转定义后发现除了常用的NOP还有EINT;和DINT;
#define NOP asm volatile("nop")
#define EALLOW asm("csrsi 0x7C1, 0x01") // eallow register id is 0x7C1 ,enable write spieacl register
#define EDIS asm("csrci 0x7C1, 0x01") // disable
//#define ESTOP0 asm(" ESTOP0") //if in debug ,set 1 dsp stop,not in debug, just a nop
//#define ESTOP0 asm(" ebreak"); //send debug call
#define EINT asm("csrsi mstatus, 0x8")
#define DINT asm("csrci mstatus, 0x8")
EALLOW;EDIS;注释写的很清楚,分别是开启写特殊功能寄存器功能和关闭写特殊功能寄存器。
在官方参考手册中,有如下解释:
3.1.2 EALLOW 保护
系统中的一些寄存器通过 EALLOW 保护机制来防止出现虚假的 CPU 写操作。 它使用
特殊的 CPU 指令 EALLOW 和 EDIS 来启用和禁用对受保护寄存器的访问。 当前保护状态
由 CPU ST1 寄存器中的 EALLOW 位给出, 如表 3-1。
寄存器保护在启动时默认启用。 当受保护时, CPU 对受保护寄存器的所有写操作都
被忽略。 只允许 CPU 读、 JTAG 读和 JTAG 写。 如果通过执行 EALLOW 指令禁用了保护,
则允许 CPU 自由地写入受保护的寄存器。 在修改寄存器之后, 可以通过执行 EDIS 指令
清除 EALLOW 位来再次保护它们。
对时钟配置和外设时钟启用寄存器的写入可能会被禁用, 直到下一次通过写入特
殊锁寄存器进行复位
表 3-1 访问受 allow 保护的寄存器
EALLOW 位 CPU 写 CPU 读 JTAG 写 JTAG 读
0 Ignored Allowed Allowed Allowed
1 Allowed Allowed Allowed Allowed
(1) EALLOW 位被 JTAG 端口覆盖, 允许在代码调试期间完全访问受保护的寄存器 IDE
™ 接口。
DINT和EINT没有注释,查询参考手册里发现如下解释:
和 PIE 一样, CPU 为它的每个中断提供标志并使能寄存器位。 有一个使能寄存器
(IER)和一个标志寄存器(IFR), 它们都是内部 CPU 寄存器。 还有一个全局中断掩码,
由 Mstatus 寄存器中 MIE 位控制。 可以使用 CPU 的 SETC 和 CLRC 指令设置和清除此掩
码。 在 C 代码中, DINT 和 EINT 宏可以用于此目的。(不同)
可以发现DINT和EINT是开关全局中断的汇编
参考手册中3.5.4.3介绍禁用中断章节的内容中有实际流程设计DINT和EINT:
1.全局禁用中断( DINT)。
2.清除 PIEIER bit。
3.等待 5 个周期, 以确保任何传播中断已到达 CPU IFR 寄存器。
4.清除中断 PIE 组的 CPU IFR 位。
5.清除中断的 PIE 组的 PIEACK 位。
6.全局使能中断( EINT)。
可以使用 CPU IER 寄存器禁用中断组。 这不会导致竞争状况, 因此不需要特殊程
序。
看完汇编继续回来。disablewatchdog中除了汇编只有一句代码。
跳转HWREG
#define HWREG(x) \
(*((volatile uint32_t *)((uintptr_t)(x))))
#define HWREG_BP(x) \
(*((volatile uint32_t *)((uintptr_t)(x))))
使用volatile修饰的uint32_t类型的指针,直接操作硬件地址,是一种更底层但是效率极高的用法。
HWREG(WD_BASE + SYSCTL_O_WDCR) = (HWREG(WD_BASE + SYSCTL_O_WDCR) & ~0x80)| (SYSCTL_WD_CHKBITS | SYSCTL_WDCR_WDDIS);
传入HWREG函数的是WD的基地址加O_WDCR的偏移地址
#define WD_BASE 0x00038E00U
#define SYSCTL_O_WDCR 0x50U // Watchdog Control Register
把SYSCTL_O_WDCR实际地址上的0x80位清零并且与上SYSCTL_WD_CHKBITS和SYSCTL_WDCR_WDDIS
static inline void
SysCtl_deviceCal(void)
{
//
// Call the PMUTrims_cal OscTrims_cal function
//
(* PMUTrims_cal)();
(* OscTrims_cal)();
}
使用两个函数指针调用了宏定义分别对电源管理和时钟进行校准。
//
// Call Flash Initialization to setup flash waitstates. This function must
// reside in RAM.
//
Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
看函数名就知道是配置关于flash的内容
//*****************************************************************************
//
// Flash_initModule
//
//*****************************************************************************
void CODE_SECTION("ramfuncs")
Flash_initModule(uint32_t ctrlBase, uint32_t eccBase, uint16_t waitstates)
{
//
// Check the arguments.
//
ASSERT(Flash_isCtrlBaseValid(ctrlBase));
ASSERT(Flash_isECCBaseValid(eccBase));
ASSERT(waitstates <= 0xFU);
//
// Set the bank fallback power mode to active.
//
Flash_setBankPowerMode(ctrlBase, FLASH_BANK, FLASH_BANK_PWR_ACTIVE);
//
// Disable cache and prefetch mechanism before changing wait states
//
Flash_disableCache(ctrlBase);
Flash_disablePrefetch(ctrlBase);
//
// Set waitstates according to frequency.
//
Flash_setWaitstates(ctrlBase, waitstates);
//
// Enable cache and prefetch mechanism to improve performance of code
// executed from flash.
//
Flash_enableCache(ctrlBase);
Flash_enablePrefetch(ctrlBase);
//
// At reset, ECC is enabled. If it is disabled by application software and
// if application again wants to enable ECC.
//
Flash_enableECC(eccBase);
//
// Force a pipeline flush to ensure that the write to the last register
// configured occurs before returning.
//
FLASH_DELAY_CONFIG;
}
修饰函数名称中有CODE_SECTION("ramfuncs")实际为#define CODE_SECTION(v) __attribute__((section(v)))的宏定义
表明这段代码定义再ram区固定块中。
通过断言判断传入参数的合理性,
设置后备电源模式为主动后备模式
禁用缓存和预取机制,然后根据频率设置等待状态,接着启用缓存和预取机制以提高从闪存执行的代码的性能。启动错误校验。
配置完成后通过flash_delay_config宏定义延迟,等待配置生效
#define FLASH_DELAY_CONFIG asm volatile(".align 2;RPTI 10,4;NOP")
时钟配置比较复杂,我们后面再看,接下来的
void Device_enableAllPeripherals(void)
{
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DMA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CPUBGCRC);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HRPWM);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ERAD);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM3);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM4);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM5);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM6);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM7);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM8);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ECAP1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ECAP2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ECAP3);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HRCAP);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EQEP2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SCIA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SPIB);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_I2CA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_I2CB);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_I2S);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CANA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCC);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CMPSS1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CMPSS2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CMPSS3);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CMPSS4);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_FSITXA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_FSIRXA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_LINA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_LINB);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_PMBUSA);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DCC0);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_DCC1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CLB1);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CLB2);
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HICA);
}
使能了所有外设的时钟
static inline void ASysCtl_lockVREG(void)
{
EALLOW;
//
// Write a 1 to the lock bit in the LOCK register.
//
HWREG(ANALOGSUBSYS_BASE + ASYSCTL_O_LOCK) |= ASYSCTL_LOCK_VREGCTL;
EDIS;
}
设置了ADCLOCK寄存器的LOCK位
DEVICE_INITGPIO()解锁了所有IO口
void Device_initGPIO(void)
{
//
// Disable pin locks.
//
GPIO_unlockPortConfig(GPIO_PORT_A, 0xFFFFFFFF);
GPIO_unlockPortConfig(GPIO_PORT_B, 0xFFFFFFFF);
GPIO_unlockPortConfig(GPIO_PORT_H, 0xFFFFFFFF);
}
void
Interrupt_initModule(void)
{
//
// Disable and clear all interrupts at the CPU
//
(void)Interrupt_disableGlobal();
IER = 0x0000U;
IFR = 0x0000U;
//
// Clear all PIEIER registers
//
HWREG(PIECTRL_BASE + PIE_O_IER1) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER2) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER3) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER4) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER5) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER6) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER7) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER8) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER9) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER10) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER11) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IER12) = 0U;
//
// Clear all PIEIFR registers
//
HWREG(PIECTRL_BASE + PIE_O_IFR1) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR2) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR3) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR4) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR5) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR6) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR7) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR8) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR9) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR10) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR11) = 0U;
HWREG(PIECTRL_BASE + PIE_O_IFR12) = 0U;
//
// Enable vector fetching from PIE block
//
HWREG(PIECTRL_BASE + PIE_O_CTRL) |= PIE_CTRL_ENPIE;
}
//*****************************************************************************
//
// Interrupt_initVectorTable
//
//*****************************************************************************
void
Interrupt_initVectorTable(void)
{
uint32_t i;
EALLOW;
//
// We skip the first three locations because they are initialized by Boot
// ROM with boot variables.
//
for(i = 3U; i < 224U; i++)
{
HWREG(PIEVECTTABLE_BASE + (4U * i)) =
(uint32_t)Interrupt_defaultHandler;
}
//
// NMI and ITRAP get their own handlers.
//
HWREG(PIEVECTTABLE_BASE + ((INT_NMI >> 16U) * 4U)) =
(uint32_t)Interrupt_nmiHandler;
EDIS;
}
中断全部清零,中断向量表也全部清零。
- 2024-07-09
-
发表了主题帖:
【中科昊芯】国产DSP初体验之环境搭建与点灯
本帖最后由 lugl4313820 于 2024-7-19 08:32 编辑
1.实物开箱:
包装精美,布局合理,功能齐全,丝印清晰。油墨为深红色,和某德开发板颇为相近。
2.板载硬件
DSP:HXS320F28025C
--主频:160Mhz
--增强型外设:ePWM、HRPWM、eCAP、HRCAP、eQEP、ADC、CLB
--32BIT*3 定时器
--LQFP-64
HX-link 110V隔离调试器
CAN收发器、FSI、EQEP、
兼容Boosterpack扩展包
3.开发环境
Haawking IDE
--基于eclipse深度定制,是市面上众多MCU厂商的青睐之选。ST的CubeIDE、TruStudio、NXP的S32DS、TI的CCS都是基于此IDE。上手难度不会很高,资料众多,易于学习。
4.创建工程
第一次打开进入welcom界面
--
--可以选择新建工程或者下载例程
点击新建工程芯片选择HSX320F280025C-EDC
输入Project name
选择程序运行在flash中
新建的工程如下图:
Device_init()中包含了时钟配置和断言,使能外设,选择程序运行在FLASH等功能,
我们暂时不需要去管它。
----
在工程文件中找到外设驱动lib:
haawking-drivers - haawking-dsc280025_edc-board - inc
打开GPIO.C和GPIO.H文件。
粗看下来
GPIO_setDirectionMode(uint32_t pin, GPIO_Direction pinIO)
GPIO_setPinConfig(uint32_t pinConfig)
这两个函数跟输出配置有关。
打开开发板原理图,查看LED对应的端口为GPIO31、GOIO34
初始化两个引脚,配置为输出模式,默认不加上拉,用户手册上有toggle翻转寄存器,在.h里写好的函数
直接调用外加延时函数。
切换到haawking,点击bilid,没有报错,点击download下载到开发板上。
两个灯会亮了,但是没有闪烁。重新查看一遍代码,发现是想当然了。延时以us计算的。把他当成ms用了。
写一个for循环执行1000次,再次下载,小灯就闪烁起来啦!
我们平常用的串口在32单片机上叫UART,HXS280上名字是SCI。会有一些寄存器的配置,为了节省时间我们直接移植官方历程。
打开官方库中的SCI_LOOPBACK工程,可以看到关于SCI的配置都在board.c和board.h里,我们在工程里新建.C和.H文件,把它们复制过来
在主函数里初始化配置,根据SCI发送函数写一个字符串发送helloworld
间隔打印到串口。
编译烧录一气呵成,打开串口助手,可以看到COM35已经不停接收到开发板打印出来的字符串啦。
点完灯,调完串口,就算是对板子有一个初步的了解了。接下来让我们探究更多的外设吧!
- 2024-07-05
-
加入了学习《DIY作品演示》,观看 【FM33LG0系列开发板测评】07.LCD & 段码显示软件实现框架
-
回复了主题帖:
Vllink/JLINK/STLINK 下载速度测试
flyaqiao 发表于 2024-7-5 09:50
为啥我的VLLINK 5M及以上都识别不了芯片了.你们还能测试到10M
有线无线,V1和V2都是这样
STM32H750的 ...
5M的下载速度怎么样?日常使用会感觉到慢吗?
-
回复了主题帖:
Vllink/JLINK/STLINK 下载速度测试
flyaqiao 发表于 2024-7-5 09:50
为啥我的VLLINK 5M及以上都识别不了芯片了.你们还能测试到10M
有线无线,V1和V2都是这样
STM32H750的 ...
更新固件看看呢。我两台笔记本都能识别到V2,台式机不能识别。不清楚什么原因
-
发表了主题帖:
Vllink/JLINK/STLINK 下载速度测试
本帖最后由 jixulifu2 于 2024-7-5 01:05 编辑
环境:
1. 电脑系统:Windows7 64bit
2.MDK:5.39
3.测试DEMO编译完成后:
Program Size: Code=115630 RO-data=28662 RW-data=292 ZI-data=33752092
bin文件:142kb
hex文件:398kb
axf文件:1396kb
测试成员:
1.Vllink 无线模式
2.Vllink 有线模式
3.JLINK-V9 “国产”版
4.ST-linkV2
5.PWLINK-LITE
特别说明:
1.无线环境为中低干扰
2.台式机始终识别不到Vllink的CMSIS-DAPV2 所以Vllink 数据均基于CMSIS-DAP V1模式
下载速度:
1.Vllink 有线模式 10MHZ
下载用时:7s
2.Vllink 无线模式 10MHZ
下载用时:11s
3.JLINK-V9 50MHZ
下载用时:8s
4.ST-LINK V2 10MHZ
下载用时:9s
5.PW-LINK LITE
HID模式 下载用时:8s
WINUSB模式 下载用时:14s
总结:在基于没有调通DAP-V2的情况下,VVLINK2依然取得了一秒领先的成绩。我猜想这主要归功于这颗高达240MHZ的主控,在PW-LINK的身上可以显而易见地发现DAP-V2对下载速度会有巨大提升。可惜的是笔者通过更新固件,升级KEIL版本等方法,并没有如愿体验到满血模式的VVLINK。测试工程涵盖了七寸LCD驱动,MJPEG,Audio,Vedio,fatfs等功能。已经足够模拟大部分工作环境。VVLINK无线模式也仅落后常规下载器三秒左右。相较于便利性的提升,这3秒的时间是完成可以接受的。
- 2024-07-04
-
回复了主题帖:
【高速无线调试器】2、无线调试初体验-随机一块开发板
常见泽1 发表于 2024-7-2 12:55
对于CMSIS-DAP v2来说,本调试器需要5.36版本(keil)以
————
我用的5 ...
我是5.36,但是没有V2选项,不知道为什么?
- 2024-07-03
-
回复了主题帖:
测评入围名单: 中科昊芯HXS320F28025C,基于RISC-V的DSP
个人信息无误,确认可以完成测评分享计划
- 2024-07-01
-
回复了主题帖:
【Vllink Basic2无线调试器评测】
秦天qintian0303 发表于 2024-7-1 10:10
具体原因就是USB扩展口的问题?都在高速运行导致不识别了?
具体原因没有找出来。可能跟usb前面板的hub不兼容吧。
- 2024-06-30
-
发表了主题帖:
【Vllink Basic2无线调试器评测】
本帖最后由 jixulifu2 于 2024-6-30 15:02 编辑
Vllink Basic2无线烧录器评测
1.开箱
【实物图】
Vllink Basic2 简介:
Vllink Basic2是le062出品的高速无线调试器无干扰第二代,有线、无线调试场合均适用。无线调试速度可达130KB/s室内10m内可穿墙,室外无遮挡可传输50m;支持SWD、JTAG、UART-CDC;CMSIS-DAP V1/V2双免驱协议。
技术优势:
-USB2.0高速,跑V1 HID协议也不是龟速
-WiFi6 5.8G,默认165信道,此信道99%的无线路由器不会用,干扰少
-集成电平转换芯片,参考电平范围:1.2V-5.5V
-内置数字电压源:可通过VRef脚输出:1.8V/2.5V/3.3V/4.0V,限流200mA
主控采用爱科微的AIC8800M
RAM容量:992 KB (4M PSRAM)
Flash容量:2 MB
240MHz Cortex-M4 Dual
Core480MHz DSP
2.4G/5G Wi-Fi6BT
5.0 EDR/BLE 蓝牙双模
USB HS 2.0 OTG PHY
1x 60MHz SPI,1x I2C,3x UART,SDIO,I2S
2.环境安装
Vllink Basic2采用免驱方案,理论上是插入即用的,但是人生处处是惊喜(惊吓),此处留个坑,文末再讲。
不出意外的话,如下所示:
如果是WIN10以下的系统,可能需要自装驱动,参考官网链接:Windows7 驱动安装 — Vllogic 文档。
3.下载与仿真
出厂自带一主一从无线模式,双击按键所有指示灯闪烁表面正在切换模式,直到AP,STA指示灯全灭为有线模式。
根据接口定义连使用自带杜邦线连接目标板,对比标准jtag口引脚是顺的,不用被拧成麻花,这点好评!
需要注意的是Vref要接到VCC(optional)上才读的到芯片。
接下来进入仿真测试环节
测试环境:MDK v5.39
测试芯片:STM32F429IGT6
编译环境:AC5
建立测试工程项目过程略过,直接进入设置,仿真设备选择CMSIS-DAP,如下所示:
配置好下载器设置后重新编译工程,点击下载,可以看到Erase Done. Programming Done.Verify OK. 表明下载成功。
点击DEBUG按钮,进入仿真模式,全速运行,可以正常查看变量数据,暂停可以看到堆栈指针变化。
至此有线下载仿真结束。
接下来,先将调试器的数据线从计算机断开连接,此时,通过开发板的5V电源供电。为了切换至无线客户端(STA)模式,双击调试器上的按钮进行模式转换,此时STA指示灯,开始闪烁,表示设备正处于未连接到无线接入点(AP)的状态。
使用数据线将AP端与电脑相连。两个调试器便迅速配对完成,AP,STA灯进入长亮状态。打开手机wifi,能看到wifi名称
点击下载按钮。程序也是顺利下载进开发板里跑了起来。
[localvideo]a374366851aaa8e006c6a9957e88b685[/localvideo]
进入调试模式,打满断点,不断点击运行。能看到X的VALUE不断自增,开发板的幻灯片一张一张变换。
我是调试接线,裁剪图片,写文章同时进行的,从第一次连接上wifi到此时此刻,一共接近30分钟,反复烧写,退出进入仿真模式,都是稳如老狗,没有发生断触丢包。
今天只是开胃小菜,接下来还会进行
-极限距离烧写调试测试
-穿墙烧写调试测试
-强干扰下的调试测试
-还有st-link,jlink,pwlink同台竞技对比烧写速度
4.番外
上文中Vllink Basic2采用免驱方案,理论上是插入即用的,但是人生处处是惊喜(惊吓)
为什么是惊吓呢?我习惯通过前端面板的3个USB接口配合一根连接到机箱后部的USB延长线来使用我的PWLink和JLink调试器。我给Vllink Basic2通过前面板USB口上电后keil里查看不到设备,设备管理器里没有任何反应,音响传出叮咚叮咚反复断联重连的声音,反插 ,正插,换口,换机箱后延长线都不奏效。我心想不会是被我搞坏了吧,立刻打开笔记本尝试。一次成功。悬着的心放下来。排除了Vllink的问题,接下来开始找台式机的问题。首先想到的是会不会被我前面板USB口上的蓝牙模块和2.4G手柄模块干扰了。全部拔下,无果。会不会是前面板不兼容呢?后面板大概率不会不兼容,随即反复在延长线上尝试正反插,都没有效果,梅雨天气又闷又热,心中很是烦躁。会不会是平常调试的时候把后面板的这个USB口烧掉了呢?跑到后面把USB耳机拔下,把Vllink通过A-C的线直插这个口上,叮咚一声后便不再响了。心中大喜。果然正常连上了。擦了擦汗终于可以愉快的调试了。吃一堑长一智,以后碰到连不上的设备应该直接去后USB口试。
- 2024-06-24
-
回复了主题帖:
测评入围名单: 高速无线调试器(WiFi6免干扰),追加了4个
个人信息无误,确认可以完成测评分享计划