我是靠谱客的博主 危机紫菜,最近开发中收集的这篇文章主要介绍Matlab生成dsp程序——官方例程学习(2),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Matlab生成dsp程序——官方例程学习(2)

    • 一、主要功能
    • 二、CAN总线
    • 三、2837x关于CAN说明
    • 四、生成程序
    • 五、总结

    这次学习的是官方例程中的Asynchronous Scheduling,emm因为我也是一边学习一边记录,所以现在也没办法解释整个框架的结构啥的。后面我会一步一步看,慢慢分析的。
例子官网链接:官网例程链接
模型程序链接:模型+程序

一、主要功能

   定时器或ePWM模块用于配置定时器中断。定时器中断是根据定时器周期触发的,当收到消息时会触发eCAN消息接收中断。硬件中断块(图中的蓝色模块)触发定时器中断以及eCAN消息接收中断的中断服务程序(ISR)。ISR依次调用连接到硬件中断模块输出端口的功能调用子系统。
    前两个子系统的输出是自由运行的计数器。计数器的总和用于控制F2812的PWMB或F2808 / F28335的ePWM2的占空比。PWM波形占空比从0到100%线性增加。
    第三个子系统包含一个eCAN接收模块,其消息输出控制PWM模块的占空比(F2812为PWMA或F2808 / F28335为ePWM1)。占空比从0到100%不等,因为从eCAN发送模块接收到eCAN消息。

注意:启用eCAN_A 的回环模式自发自收)可以在内部连接eCAN_A发送器和接收器,以避免在发送器和接收器之间进行外部连接。要禁用eCAN_A 的回环模式,发送器和接收器必须在外部连接在一起____________以上部分来自官方说明

在这里插入图片描述

  因为CAN的知识有点遗忘,这里补一下课。

二、CAN总线

    帧种类:1.数据帧2.遥控帧3.错误帧4.过载帧5.间隔帧

1.数据帧:用于发送单元向接收单元传送数据的帧。

2.遥控帧:用于接收单元向具有相同ID的发送单元请求数据的帧。

3.错误帧:用于当检测出错误时,向其他单元通知错误的帧。

4.过载帧:用于接收单元通知其尚未做好接收准备的帧。

5.间隔帧:用于数据帧及遥控帧与前面的帧分离开来的帧。

    其中,数据帧遥控帧标准格式(11个标识符[ID])与扩展格式(29个标识符[ID])两种格式。因为实际中使用的数据帧过程最多,这里着重看看数据帧。

数据段一共由七个段组成:①帧起始②仲裁段③控制段④数据段(最多传送8个字节)⑤CRC段⑥ACK段⑦帧结束

**帧起始:**一个显性电平表示帧起始

仲裁段:

I、标准格式:11位基本ID+RTR(远程请求位[0:数据帧,1:远程帧])

II、扩展格式:11位基本ID+SRR(替代远程请求位[设置为1])+IDE(标识符选择位[0:标准标识符,1:扩展标识符])+18位扩展ID +RTR(远程请求位[0:数据帧,1:远程帧])

控制段

I、标准格式:IDE(标识符选择位[0:标准标识符,1:扩展标识符])+r0(保留位)+DLC(数据长度/字节)

II、扩展格式:r0(保留位)+r1(保留位)+DLC(数据长度/字节)

**数据段:**8个字节,两种帧格式完全一样。

**CRC段:**15个CRC+一位CRC界定符

**ACK段:**ACK槽+ACK界定符(发送单元:发送2个隐性位,接收单元:接收正确消息-ACK槽发送显性)

**帧结束:**七个位隐性位组成

仲裁手段:1.总线空闲时,最先发送的单元具有优先级2.多个单元同时发送时,连续输出显性电平(逻辑0)多的单元(从ID位进行比较,直到RTR与SRR等位),具有最高优先级。

波特率设置:1位分为4个段(同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)、相位缓冲段2(PBS2)),每个段分为若干个Tq,这称为位时序。位时间=1/波特率

  • 1.同步段(SS):1Tq,多个单元进行同步工作的段。
  • 2.传播时间段(PTS):1~8Tq,用于吸收网络上的物理延迟的段。
  • 3.相位缓冲段1(PBS1)与相位缓冲段2(PBS2):可对同步端进行补偿(1-8Tq,2-8Tq)[STM32中PTS+PBS1合称BS1]
  • 4.再同步补偿宽度(SJW):1-4Tq

三、2837x关于CAN说明

1.操作模式

  • 初始化模式(Initialization

    i、可以通过软件(将CAN_CTL寄存器中的Init位置1)、硬件复位或者总线断开进入。当Init置1时,传送停止,输出一直为高。

    ii、进入初始化状态后,可以配置波特率与哪些message—box被使用等信息,清除Init位可以结束初始化模式

  • CAN传输模式(正常工作模式)[**CAN Message Transfer (Normal Operation) **]

    i、初始化完成后,当Init重新回到0时,便会自动进入此模式。若消息通过过滤则会保存到RAM中。

  • 禁用自动重发模式[Disabled Automatic Retransmission ]

    i、默认状态下,此模式开启,可以通过CAN Control register 中的DAR位进行关闭。

  • 自动总线开启模式[Auto-Bus-On]

    i、当开启此功能,可以通过复位Init位,使总线重新开启。

    ii、通过使能ABO位,自动总线开启功能将开启。

  • 测试模式[Test Modes]

在这里插入图片描述

    i、上图可以看出测试模式的进入寄存器位设置,其中CAN Control register 中的Test bit必须设置为1,才能使能CAN_TEST模式。

  • 静默模式(总线监听模式)[Silent Mode]

    i、通过CAN_TEST寄存器中的Silent位进行使能,只接收消息。发送端一直发送隐性(1)电平。

    在这里插入图片描述

  • 回环模式[Loopback Mode]

    i、数据将从发送给外部,但是外部信息无法进入内核。其发送的消息直接用内核的TX传送到RX。相当于禁止了外部消息的接收。

    在这里插入图片描述

  • 外部回环模式[**External Loopback Mode **]

    i、同回环模式不同的是,外部回环连接到了CAN_TX管脚,可以测试I/O管脚的功能。通过控制ExL等于1开启此模式。

在这里插入图片描述

  • 回环模式与静默模式一起开启[Loopback Combined with Silent Mode]

    i、设置LBack和Silent可以进入此模式。

在这里插入图片描述

2.时钟来源:i、外部时钟。ii、系统时钟。iii、GPIO辅助时钟

3.中断功能:通过设置IE0与IE1可以使能CAN0INT与CAN1INT。CAN模块可以响应三种中断:i、消息中断。ii、状态改变中断。iii、错误中断。中断源通过Int0lD/Int1lD进行区分。消息中断的优先级与消息邮箱编号有关,1有最高优先级。中断需要在CAN_GLB_INT_EN register 中启用,处理中断时,必须先清除消息或者状态改变标志,然后进行应答。(via CAN_GLB_INT_CLR and PIEACK

消息中断:IntPND, TxIE and RxIE (Interrupt Multiplexer register )可以触发CAN0INT与CAN1INT
状态改变中断:RxOk, TxOk, and LEC (Error and Status register )可以触发CAN0INT[需要使能SIE位]
错误中断:PER, BOff and EWarn 可以触发CAN0INT[需要使能EIE位]

在这里插入图片描述

在这里插入图片描述

四、生成程序

程序框架相对于第一个程序没有很大的变化,

#include "c2807x_2837xx_asyncscheduling_ert.h"
#include "rtwtypes.h"

volatile int IsrOverrun = 0;
static boolean_T OverrunFlag = 0;
void rt_OneStep(void)
{
  /* Check for overrun. Protect OverrunFlag against preemption */
  if (OverrunFlag++) {
    IsrOverrun = 1;
    OverrunFlag--;
    return;
  }

  enableTimer0Interrupt();
  c2807x_2837xx_asyncscheduling_ert_step();

  /* Get model outputs here */
  disableTimer0Interrupt();
  OverrunFlag--;
}

volatile boolean_T stopRequested = false;
volatile boolean_T runModel = false;
int main(void)
{
  float modelBaseRate = 0.001;
  float systemClock = 200;

  /* Initialize variables */
  stopRequested = false;
  runModel = false;
  c2000_flash_init();
  init_board();

#ifdef MW_EXEC_PROFILER_ON

  config_profilerTimer();

#endif

  ;
  rtmSetErrorStatus(c2807x_2837xx_asyncschedulin_M, 0);
  c2807x_2837xx_asyncscheduling_ert_initialize();
  configureTimer0(modelBaseRate, systemClock);
  runModel =
    rtmGetErrorStatus(c2807x_2837xx_asyncschedulin_M) == (NULL);
  enableTimer0Interrupt();
  enable_interrupts();                  //开启ePWM3/4以及CAN接收中断
  globalInterruptEnable();
  while (runModel) {
    stopRequested = !(
                      rtmGetErrorStatus(c2807x_2837xx_asyncschedulin_M) == (NULL));
  }

  /* Disable rt_OneStep() here */

  /* Terminate model */
  c2807x_2837xx_asyncscheduling_ert_terminate();
  globalInterruptDisable();
  return 0;
}

/*
 * File trailer for generated code.
 *
 * [EOF]
 */

仍旧是在主函数完成硬件的初始化:c2807x_2837xx_asyncscheduling_ert_initialize(),

设置Timer0作为步长的解算器:configureTimer0(modelBaseRate, systemClock)

每经过一次步长进入Timer0中断函数进行执行:rt_OneStep()

**c2807x_2837xx_asyncscheduling_ert_initialize()**中完成有关外设的初始化

1.CAN接收的初始化(1.使能接收中断2.使能mailbox1作为接收邮箱)

	tCANMsgObject sRXCANMessage;
    unsigned char ucRXMsgData[8]= { 0, 0, 0, 0, 0, 0, 0, 0 };

    sRXCANMessage.ui32MsgID = 455;     // CAN message ID
    sRXCANMessage.ui32MsgIDMask = 0;   // no mask needed for TX
    sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
    sRXCANMessage.ui32MsgLen = sizeof(ucRXMsgData);// size of message is 4
    sRXCANMessage.pucMsgData = ucRXMsgData;// ptr to message content

    // Setup the message object being used to receive messages
    CANMessageSet(CANA_BASE, 1, &sRXCANMessage, MSG_OBJ_TYPE_RX);

2.ePWM1模块初始化接收eCAN传送来的信息改变占空比。

3.ePWM2模块初始化接收ePWM3和ePWM4送来的信息改变占空比。

4.存储有关的参数进入系统结构体中,参数都是模块的参数。

Timer0中断函数中

1.开启TIimer0中断(PIE1.7)、开启ePWM3、ePWM4中断。(PIE3.3、PIE3.4)

2.执行**c2807x_2837xx_asyncscheduling_ert_step()**函数:

1)因为程序中存在一个缓冲模块,这里通过一个数组进行缓存。Rate Transfer模块左侧是100k每秒改变一次的数值,右侧的add模块为1K做一次加法。程序中采用了一个数组进行缓存数据。
2)将两个缓存的模块输出直接进行相加后,赋值给ePWM2的CMPA模块
3)eCAN传送的数据的完成自加1后返回(为下一次传送+1数据做准备)

还有三个中断函数内容没有看,分别是ePWM3/4中断和eCANA接收中断:(这三个中断服务函数都在MW_c28xx_csl
.c文件中)。

ePWM3的中断函数:**EPWM3_INT_isr()**函数:

void isr_int3pie3_task_fcn(void)
{
  /* Call the system: <Root>/Function-Call Subsystem */
  {
    /* S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */

    /* Output and update for function-call system: '<Root>/Function-Call Subsystem' */
    {
      uint16_T rtb_FixPtSum1;

      /* UnitDelay: '<S7>/Output' */
      c2807x_2837xx_asyncscheduling_B.Output_f =
        c2807x_2837xx_asyncschedulin_DW.Output_DSTATE_g;

      /* Sum: '<S8>/FixPt Sum1' incorporates:
       *  Constant: '<S8>/FixPt Constant'
       */
      rtb_FixPtSum1 = (c2807x_2837xx_asyncscheduling_B.Output_f +
                       c2807x_2837xx_asyncscheduling_P.FixPtConstant_Value) &
        8191U;                                                 //8191=0x1FFF;

      /* Switch: '<S9>/FixPt Switch' */
      if (rtb_FixPtSum1 > c2807x_2837xx_asyncscheduling_P.WrapToZero_Threshold)
      {
        /* Update for UnitDelay: '<S7>/Output' incorporates:
         *  Constant: '<S9>/Constant'
         */
        c2807x_2837xx_asyncschedulin_DW.Output_DSTATE_g =
          c2807x_2837xx_asyncscheduling_P.Constant_Value;
      } else {
        /* Update for UnitDelay: '<S7>/Output' */
        c2807x_2837xx_asyncschedulin_DW.Output_DSTATE_g = rtb_FixPtSum1;
      }

      /* End of Switch: '<S9>/FixPt Switch' */
    }

    /* End of Outputs for S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */

    /* Update for RateTransition: '<Root>/Rate Transition' */
    c2807x_2837xx_asyncschedulin_DW.RateTransition_Buffer[c2807x_2837xx_asyncschedulin_DW.RateTransition_ActiveBufIdx
      == 0] = c2807x_2837xx_asyncscheduling_B.Output_f;
    c2807x_2837xx_asyncschedulin_DW.RateTransition_ActiveBufIdx =
      (c2807x_2837xx_asyncschedulin_DW.RateTransition_ActiveBufIdx == 0);//让缓冲地址在0-1之间循环
  }
}

生成的每个数字每进入一次中断自加1(0-8191之间循环),然后更新缓冲模块。

ePWM4的中断函数:**EPWM4_INT_isr()**函数:与ePWM3生成函数雷同,但是运行范围在0-16383之间。

void isr_int3pie4_task_fcn(void)
{
  /* Call the system: <Root>/Function-Call Subsystem1 */
  {
    /* S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */

    /* Output and update for function-call system: '<Root>/Function-Call Subsystem1' */
    {
      uint16_T rtb_FixPtSum1;

      /* UnitDelay: '<S10>/Output' */
      c2807x_2837xx_asyncscheduling_B.Output_i =
        c2807x_2837xx_asyncschedulin_DW.Output_DSTATE_n;

      /* Sum: '<S11>/FixPt Sum1' incorporates:
       *  Constant: '<S11>/FixPt Constant'
       */
      rtb_FixPtSum1 = (c2807x_2837xx_asyncscheduling_B.Output_i +
                       c2807x_2837xx_asyncscheduling_P.FixPtConstant_Value_i) &
        16383U;

      /* Switch: '<S12>/FixPt Switch' */
      if (rtb_FixPtSum1 > c2807x_2837xx_asyncscheduling_P.WrapToZero_Threshold_e)
      {
        /* Update for UnitDelay: '<S10>/Output' incorporates:
         *  Constant: '<S12>/Constant'
         */
        c2807x_2837xx_asyncschedulin_DW.Output_DSTATE_n =
          c2807x_2837xx_asyncscheduling_P.Constant_Value_p;
      } else {
        /* Update for UnitDelay: '<S10>/Output' */
        c2807x_2837xx_asyncschedulin_DW.Output_DSTATE_n = rtb_FixPtSum1;
      }

      /* End of Switch: '<S12>/FixPt Switch' */
    }

    /* End of Outputs for S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */

    /* Update for RateTransition: '<Root>/Rate Transition1' */
    c2807x_2837xx_asyncschedulin_DW.RateTransition1_Buffer[c2807x_2837xx_asyncschedulin_DW.RateTransition1_ActiveBufIdx
      == 0] = c2807x_2837xx_asyncscheduling_B.Output_i;
    c2807x_2837xx_asyncschedulin_DW.RateTransition1_ActiveBufIdx =
      (c2807x_2837xx_asyncschedulin_DW.RateTransition1_ActiveBufIdx == 0);
  }
}

CAN接收中断函数:CANA0_INT_isr()

void isr_int9pie5_task_fcn(void)
{
  /* Call the system: <Root>/Function-Call Subsystem2 */
  {
    /* S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */

    /* Output and update for function-call system: '<Root>/Function-Call Subsystem2' */

    /* S-Function (c280xcanrcv): '<S3>/eCAN Receive' */
    {
      tCANMsgObject sRXCANMessage;
      unsigned char ucRXMsgData[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

      sRXCANMessage.ui32MsgID = 455;   // CAN message ID
      sRXCANMessage.ui32MsgIDMask = 0; // no mask needed for TX
      sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
      sRXCANMessage.ui32MsgLen = sizeof(ucRXMsgData);// size of message
      sRXCANMessage.pucMsgData = ucRXMsgData;// ptr to message content

      // Get the receive message
      CANMessageGet(CANA_BASE, 1, &sRXCANMessage, false);
      if (sRXCANMessage.ui32MsgLen > 0) {
        c2807x_2837xx_asyncscheduling_B.eCANReceive_o2[0] = ucRXMsgData[0] |
          (ucRXMsgData[1] << 8);
        c2807x_2837xx_asyncscheduling_B.eCANReceive_o2[1] = ucRXMsgData[2] |
          (ucRXMsgData[3] << 8);
        c2807x_2837xx_asyncscheduling_B.eCANReceive_o2[2] = ucRXMsgData[4] |
          (ucRXMsgData[5] << 8);
        c2807x_2837xx_asyncscheduling_B.eCANReceive_o2[3] = ucRXMsgData[6] |
          (ucRXMsgData[7] << 8);

        /* -- Call CAN RX Fcn-Call_0 -- */
      }
    }

    /* S-Function (c2802xpwm): '<S3>/ePWM1' */

    /*-- Update CMPA value for ePWM1 --*/
    {
      EPwm1Regs.CMPA.bit.CMPA = (uint16_T)
        (c2807x_2837xx_asyncscheduling_B.eCANReceive_o2[0]);
    }

    /* End of Outputs for S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */
  }
}

  CAN接收中断实现了读取CAN的数据内容,然后进行拼接(CAN接收是按8位进行接收,CMPA是16位寄存器,所以两个8位数据进行拼接变成Uint16)赋给CMPA。

五、总结

  可以发现,Simulink生成的函数,框架结构非常严格,可能这就是代码生成的特点把。基本上框架搭好之后,对每个部分重新填充便是一个新的功能函数,代码移植效率也很高。但是机器还是有缺点的,程序可读性没有那么高。再就是报错的时候一脸懵逼,代码生成的报错都是一堆一堆,有点找不到头绪。这两个例子大致是明白了代码工作的情况,下一步准备再多看几个例子多熟悉一下各个库器件。

最后

以上就是危机紫菜为你收集整理的Matlab生成dsp程序——官方例程学习(2)的全部内容,希望文章能够帮你解决Matlab生成dsp程序——官方例程学习(2)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部