jixulifu2

  • 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α​=Ud​cos(θ)−Uq​sin(θ) 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个

    个人信息无误,确认可以完成测评分享计划

最近访客

< 1/2 >

统计信息

已有48人来访过

  • 芯积分:64
  • 好友:--
  • 主题:6
  • 回复:6

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言