解决HRPWM的SFO.V8移植的问题

#include "driverlib.h"
#include "device.h"
#include "SFO_V8.h"

自己建立的工程,配置HRPWM,工程包含以上头文件和SFO_v8_fpu_lib_build_c28.lib

编译时报错

unresolved symbol _EPwm1Regs, first referenced in ../SFO_v8_fpu_lib_build_c28.lib<SFO_v7_fpu_lib_build_c28.obj> 

1.要定义!!!

volatile struct EPWM_REGS *ePWM[PWM_CH] ={ &EPwm1Regs, &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs,
&EPwm5Regs, &EPwm6Regs, &EPwm7Regs, &EPwm8Regs};

2.要在下面的两个位置分别添加lib文件和lib文件所在的路径

3.记得添加#include "SFO_V8.h"头文件,没有的话在c2000ware中添加(用于移植出一个单独的文件,TI的文件是一大坨)

贴一份代码吧(取自己需要的部分)



#include"F28x_Project.h"
#include "driverlib.h"
#include "device.h"
#include "LED.h"
#include "Timer0.h"
#include "SFO_V8.h"
#define EPWM_TIMER_TBPRD            100UL


void initEPWM1();
void error(void);
volatile uint32_t ePWM[] =
    {0, EPWM1_BASE, EPWM2_BASE, EPWM3_BASE, EPWM4_BASE};
//
// Globals
//

float32_t dutyFine = 0.12345;
uint16_t status;

int MEP_ScaleFactor; // Global variable used by the SFO library
                     // Result can be used for all HRPWM channels
                     // This variable is also copied to HRMSTEP
                     // register by SFO() function.





void main(void)
 {

    Device_init();//初始化时钟和外设
    Device_initGPIO();
    Interrupt_initModule();
    Interrupt_initVectorTable();

    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    initEPWM1();
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    EINT;
    ERTM;
    while(status == SFO_INCOMPLETE)
            {
                status = SFO();
                if(status == SFO_ERROR)
                {
                    error();   // SFO function returns 2 if an error occurs & # of MEP
                }              // steps/coarse step exceeds maximum of 255.
            }
    //EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 30U);//设置比较值,CompareA和CompareB各位1000


    float32_t count = (65.7 * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
    uint32_t compCount = (count);
    HRPWM_setCounterCompareValue(ePWM[1], HRPWM_COUNTER_COMPARE_A, compCount);
    //HRPWM_setHiResCounterCompareValueOnly(ePWM[1], HRPWM_COUNTER_COMPARE_A, 0x1B);
    while(1)
    {
        status = SFO(); // in background, MEP calibration module
                                     // continuously updates MEP_ScaleFactor

                     if (status == SFO_ERROR)
                     {
                         error();   // SFO function returns 2 if an error occurs & #
                                    // of MEP steps/coarse step
                     }              // exceeds maximum of 255.
//        for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 99.9; dutyFine += 0.01)
//        {
//
//
//           float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100;
//           uint32_t compCount = (count);
//           HRPWM_setCounterCompareValue(ePWM[1], HRPWM_COUNTER_COMPARE_A, compCount);
//           HRPWM_setCounterCompareValue(ePWM[1], HRPWM_COUNTER_COMPARE_B, compCount);



      }
    }



void initEPWM1()
{
    GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);//设置GPIO0和GPIO1为PWM输出
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setQualificationMode(GPIO_0_EPWM1A, GPIO_QUAL_SYNC);
    GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_1_EPWM1B);
    GPIO_setQualificationMode(GPIO_1_EPWM1B, GPIO_QUAL_SYNC);

    EPWM_setTimeBasePeriod(EPWM1_BASE, EPWM_TIMER_TBPRD-1U);//设置周期,计数到99 100M/1M = 100 产生1Mhz的方波
//    EPWM_setPhaseShift(EPWM1_BASE, 0U);
//    EPWM_setTimeBaseCounter(EPWM1_BASE,0U);//设置计数从零开始

    EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 0U);//设置比较值,CompareA和CompareB各位1000
    EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, 0U);

//    EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);//设置计数为增减计数
//    EPWM_disablePhaseShiftLoad(EPWM1_BASE);//禁止相位重载
//    EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);//配置PWM时钟。EPWM_CLOCK_DIVIDER_1=0,EPWM_HSCLOCK_DIVIDER_1=0
    //PWM时钟周期为100MHz/2^0
//    EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,
//                                             EPWM_COUNTER_COMPARE_A,
//                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);//设置影子寄存器,在计数为0是载入
//    EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE,
//                                             EPWM_COUNTER_COMPARE_B,
//                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    //设置动作模式
//    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
//    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
//    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
//    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    //TB模块
    HRPWM_setEmulationMode(EPWM1_BASE,EPWM_EMULATION_FREE_RUN);
    HRPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
    HRPWM_setTimeBaseCounter(EPWM1_BASE, 0);
    HRPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
    HRPWM_disablePhaseShiftLoad(EPWM1_BASE);
    HRPWM_setPhaseShift(EPWM1_BASE, 0);
    HRPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_DISABLED);
    HRPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    HRPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    //AQ模块
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    HRPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);


    HRPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM1_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO);
    HRPWM_disableRisingEdgeDelayCountShadowLoadMode(EPWM1_BASE);
    HRPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO);
    HRPWM_disableFallingEdgeDelayCountShadowLoadMode(EPWM1_BASE);
    //使能自动转化模式
    HRPWM_enableAutoConversion(EPWM1_BASE);
    HRPWM_setMEPEdgeSelect(EPWM1_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE);
    HRPWM_setHiResCounterCompareValueOnly(EPWM1_BASE, HRPWM_COUNTER_COMPARE_A, 50);
    HRPWM_setMEPEdgeSelect(EPWM1_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_FALLING_EDGE);
    HRPWM_setHiResCounterCompareValueOnly(EPWM1_BASE, HRPWM_COUNTER_COMPARE_B, 50);
}

void error (void)
{
    ESTOP0;         // Stop here and handle error
}

在文章的最后,我还发现了TI留了一份文档下面分别是英文中文的

The SFO library implements Scale Factor Optimization routine to drive the micro-edge positioner (MEP) calibration
module to run SFO diagnostics and determine the appropriate MEP scale factor (number of MEP steps per coarse EPWMCLK
step) for a device at any given time. Both driverlib & bit-field based libs are added in COFF & EABI format for
legacy reasons.

FILES INCLUDED:
1. SFO lib Bit-field implementation in COFF format  - SFO_v8_fpu_lib_build_c28_coff.lib
2. SFO lib Bit-field implementation in EABI format  - SFO_v8_fpu_lib_build_c28_eabi.lib
3. Index lib for Bit-field based SFO lib            - SFO_v8_fpu_lib_build_c28.lib
4. SFO lib Driverlib implementation in COFF format  - SFO_v8_fpu_lib_build_c28_driverlib_coff.lib
5. SFO lib Driverlib implementation in EABI format  - SFO_v8_fpu_lib_build_c28_driverlib_eabi.lib
6. Index lib for Driverlib based SFO lib            - SFO_v8_fpu_lib_build_c28_driverlib.lib

INDEX LIBRARY USAGE
User can link to either Bit-field or Driverlib based Index SFO library in
their example wherein, based on the example build configuration(eabi or coff)
appropriate library will be linked.

SOFTWARE USAGE DETAILS FOR DRIVERLIB BASED SFO LIB
1. Add "Include" Files:
   Include sfo_v8.h header file in application code apart for the other device
   specific files.
   E.g. #include "sfo_v8.h"
   
2. Variable Declarations:
   The application needs to declare below variables to provide EPWM instance
   addresses used in SFO lib and to capture calibration status & output.  
   E.g. uint16_t status = SFO_INCOMPLETE;
        uint32_t MEP_ScaleFactor = 0; //scale factor value
        volatile uint32_t ePWM[(PWM_CH + 1)] = {0, EPWM1_BASE, EPWM2_BASE};
        
3. MEP_ScaleFactor Initialization:
   Prior to using the MEP_ScaleFactor variable in application code, SFO() should
   be called to drive the MEP calibration module to calculate an initial
   MEP_ScaleFactor value.
   E.g.
   while(status == SFO_INCOMPLETE)
    {
        status = SFO();
        if(status == SFO_ERROR)
        {
            //
            // SFO function returns 2 if an error occurs & # of MEP
            // steps/coarse step exceeds maximum of 255.
            //
            error();
        }
    }
    
4. Application Code
   While the application is running, fluctuations in both device temperature and supply voltage may be
   expected. To be sure that optimal Scale Factors are used for each ePWM module, the SFO function
   should be re-run periodically as part of a slower back-ground loop. Some examples of this are shown
   here. E.g.
   void main ()
   {
    int status;
    // User code
    // ePWM1, 2, 3, 4 are running in HRPWM mode
    // The status variable returns 1 once a new MEP_ScaleFactor has been
    // calculated by the MEP Calibration Module running SFO
    // diagnostics.
    status = SFO();
    if(status == SFO_ERROR)
    {
     //
     // SFO function returns 2 if an error occurs & # of
     // MEP steps/coarse step exceeds maximum of 255.
     //
     error();
    }
   }
   

SOFTWARE USAGE DETAILS FOR BIT-FIELD BASED SFO LIB
1. Add "Include" Files:
   Include sfo_v8.h header file in application code apart for the other device
   specific files.
   E.g. #include "sfo_v8.h"
   
2. Variable Declarations:
   The application needs to declare below variables to provide EPWM instance
   addresses used in SFO lib and to capture calibration status & output.  
   E.g. Uint16 status = SFO_INCOMPLETE; 
        int MEP_ScaleFactor = 0; //scale factor value
        volatile struct EPWM_REGS *ePWM[] = {0, &EPwm1Regs, &EPwm2Regs};
        
3. MEP_ScaleFactor Initialization:
   Refer to Driverlib section
   
4. Application Code
   Refer to Driverlib section

大概翻译一下(用gpt偷懒了)

### SFO库简介

SFO(Scale Factor Optimization)库用于驱动微边缘定位器(MEP)校准模块运行SFO诊断,并确定设备在任何给定时间的适当MEP比例因子(每个粗EPWMCLK步骤的MEP步骤数)。该库提供了Driverlib和位字段两种实现方式,并以COFF和EABI格式提供,以支持遗留系统。

### 包含的文件

1. **位字段实现的COFF格式库** - `SFO_v8_fpu_lib_build_c28_coff.lib`
2. **位字段实现的EABI格式库** - `SFO_v8_fpu_lib_build_c28_eabi.lib`
3. **位字段SFO库的索引库** - `SFO_v8_fpu_lib_build_c28.lib`
4. **Driverlib实现的COFF格式库** - `SFO_v8_fpu_lib_build_c28_driverlib_coff.lib`
5. **Driverlib实现的EABI格式库** - `SFO_v8_fpu_lib_build_c28_driverlib_eabi.lib`
6. **Driverlib SFO库的索引库** - `SFO_v8_fpu_lib_build_c28_driverlib.lib`

### 索引库使用方法

用户可以在示例中链接到位字段或Driverlib的索引SFO库,根据示例的构建配置(eabi或coff),适当的库将被链接。

### Driverlib基础的SFO库软件使用详情

1. **添加“包含”文件**:
   在应用程序代码中包含`sfo_v8.h`头文件。
   ```c
   #include "sfo_v8.h"
   ```

2. **变量声明**:
   应用程序需要声明以下变量,以提供SFO库使用的EPWM实例地址,并捕获校准状态和输出。
   ```c
   uint16_t status = SFO_INCOMPLETE;
   uint32_t MEP_ScaleFactor = 0; // 比例因子值
   volatile uint32_t ePWM[(PWM_CH + 1)] = {0, EPWM1_BASE, EPWM2_BASE};
   ```

3. **MEP比例因子初始化**:
   在应用程序代码中使用MEP_ScaleFactor变量之前,应调用SFO()以驱动MEP校准模块来计算初始的MEP_ScaleFactor值。
   ```c
   while(status == SFO_INCOMPLETE)
   {
       status = SFO();
       if(status == SFO_ERROR)
       {
           // 如果发生错误,SFO函数返回2,并且每个粗步骤的MEP步数超过最大值255。
           error();
       }
   }
   ```

4. **应用程序代码**:
   当应用程序运行时,设备温度和电源电压可能会波动。为了确保每个ePWM模块使用最佳比例因子,应该定期在较慢的后台循环中重新运行SFO函数。
   ```c
   void main ()
   {
       int status;
       // 用户代码
       // ePWM1、2、3、4以HRPWM模式运行
       // 当MEP校准模块运行SFO诊断并计算出新的MEP比例因子后,status变量返回1。
       status = SFO();
       if(status == SFO_ERROR)
       {
           // 如果发生错误,SFO函数返回2,并且每个粗步骤的MEP步数超过最大值255。
           error();
       }
   }
   ```

### 位字段基础的SFO库软件使用详情

1. **添加“包含”文件**:
   在应用程序代码中包含`sfo_v8.h`头文件。
   ```c
   #include "sfo_v8.h"
   ```

2. **变量声明**:
   应用程序需要声明以下变量,以提供SFO库使用的EPWM实例地址,并捕获校准状态和输出。
   ```c
   Uint16 status = SFO_INCOMPLETE;
   int MEP_ScaleFactor = 0; // 比例因子值
   volatile struct EPWM_REGS *ePWM[] = {0, &EPwm1Regs, &EPwm2Regs};
   ```

3. **MEP比例因子初始化**:
   参考Driverlib部分的说明。

4. **应用程序代码**:
   参考Driverlib部分的说明。

### 总结

通过使用SFO库,可以确保PWM信号的高分辨率精度,并适应设备运行时的温度和电压变化。根据不同的实现方式(Driverlib或位字段)和构建格式(COFF或EABI),选择适当的库并进行相应配置,可以实现对MEP比例因子的优化和校准。

参考文献:解锁C2000 DSP新技能:HRPWM高精度PWM - 知乎 (zhihu.com)

                  对高精度PWM(HRPWM)的理解-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值