概述
Matlab生成dsp程序——官方例程学习
- 写在下面的话
- ADC-PWM例子学习
- 一、基本功能
- 二、生成代码分析
- 三、总结
写在下面的话
还是很建议大家多去学习官方例程的,真的能够收获到很多很多东西的!例程和ccs程序我也会打包上传的!
官方链接:MW官方例程
打包程序+模型链接:模型程序
ADC-PWM例子学习
一、基本功能
ADC采集到的模拟电压控制PWM波形的占空比(周期不发生改变)。当处理器收到ADC中断(ADCINT)时,触发中断服务程序(ISR)并执行子系统(ADC-PWM子系统)。ADC-PWM子系统由ADC与EPWM模块组成,该模块驱动PWM模块的占空比输入端口。PWM模块配置为触发ADC模块的转换开始(SOC)。
- 1.结算器Slover
I、 这个计算的步长,设置会在对应程序中生成一个变量modelBaseRate,之后设置的Timer0会每0.4s进入一次中断。
float modelBaseRate = 0.4;
float systemClock = 200;
……
ConfigCpuTimer(&CpuTimer0, systemClock, baseRate *1000000);//baseRate=modelBaseRate
二、生成代码分析
生成四个变量:
volatile int IsrOverrun = 0;
static boolean_T OverrunFlag = 0;
volatile boolean_T stopRequested = false;
volatile boolean_T runModel = false;
//三个布尔型变量,一个int形
进入主函数之后生成两个浮点型变量:
int main(void)
{
float modelBaseRate = 0.4;
//这个是求解器设置的步长
float systemClock = 200;
//CPU晶振频率,与Clocking中的参数相互对应
c2000_flash_init();
//将Flash有关程序拷贝到RAM执行(Init_Flash、Flashoff程序都存放在Flash中)
init_board();
//初始化各个部件(GPIO、时钟等)
#ifdef MW_EXEC_PROFILER_ON
config_profilerTimer();
#endif
//目前猜测是用来调试使用,Simulink环境也支持调试
/*接下下个代码块部分*/
下面先看一个结构体:
c2807x_2837xx_adcpwmasynctes_M 结构体:(因为前面都是文件名这里简记为_M结构体)
struct tag_RTM_c2807x_2837xx_adcpwma_T {
const char_T *errorStatus;
};
rtmSetErrorStatus(c2807x_2837xx_adcpwmasynctes_M, 0);
//给_M结构体中的errorStatus标志赋值为0 c2807x_2837xx_adcpwmasynctest_ert_initialize();
//初始化函数
/*再看一个结构体*/
c2807x_2837xx_adcpwmasynctest_B 结构体:(因为前面都是文件名这里简记为_B结构体)
typedef struct {
uint16_T ADC;
/* '<S1>/ADC' */
} B_c2807x_2837xx_adcpwmasyncte_T;
//注释中给的是模块信号结构体
(void) memset(((void *) &c2807x_2837xx_adcpwmasynctest_B), 0,
sizeof(B_c2807x_2837xx_adcpwmasyncte_T));
//给_B结构体赋值为0
void c2807x_2837xx_adcpwmasynctest_ert_initialize(void)//根据Simulink中设置进行初始化设置()[这里是ADC和ePWM]
{
/* Registration code */
/* initialize error status */
rtmSetErrorStatus(c2807x_2837xx_adcpwmasynctes_M, (NULL));
//给_M结构体中的errorStatus指向空(代表未操作过?)
/* block I/O */
(void) memset(((void *) &c2807x_2837xx_adcpwmasynctest_B), 0,
sizeof(B_c2807x_2837xx_adcpwmasyncte_T));
//给_B结构体赋值为0
/* Start for S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' incorporates:
*
SubSystem: '<Root>/ADC-PWM Subsystem'
*/
/* Start for function-call system: '<Root>/ADC-PWM Subsystem' */
/* Start for S-Function (c2802xadc): '<S1>/ADC' */
if (MW_adcAInitFlag == 0) {
InitAdcA();
//ADCA、12位、单端
MW_adcAInitFlag = 1;
}
//利用标志控制ADC只初始化一次
config_ADCA_SOC0 ();
//SOC0-ADCIN0、epwm1(soca)触发
//EOC0触发ADCINT1(不触发SOC0)、转换完成后产生中断
/* Start for S-Function (c2802xpwm): '<S1>/ePWM' */
EALLOW;
CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
/*** Initialize ePWM1 modules ***/
{
/*
// Time Base Control Register
EPwm1Regs.TBCTL.bit.CTRMODE
= 2;
// Counter Mode
EPwm1Regs.TBCTL.bit.SYNCOSEL
= 3;
// Sync Output Select
EPwm1Regs.TBCTL.bit.PRDLD
= 0;
// Shadow select
EPwm1Regs.TBCTL.bit.PHSEN
= 0;
// Phase Load Enable
EPwm1Regs.TBCTL.bit.PHSDIR
= 0;
// Phase Direction Bit
EPwm1Regs.TBCTL.bit.HSPCLKDIV
= 0;
// High Speed TBCLK Pre-scaler
EPwm1Regs.TBCTL.bit.CLKDIV
= 0;
// Time Base Clock Pre-scaler
EPwm1Regs.TBCTL.bit.SWFSYNC
= 0;
// Software Force Sync Pulse
*/
EPwm1Regs.TBCTL.all = (EPwm1Regs.TBCTL.all & ~0x3FFF) | 0x32;
//up-down模式、不使能同步信号输出
/*-- Setup Time-Base (TB) Submodule --*/
EPwm1Regs.TBPRD = 10000;
// Time Base Period Register
/* // Time-Base Phase Register
EPwm1Regs.TBPHS.bit.TBPHS
= 0;
// Phase offset register
*/
EPwm1Regs.TBPHS.all = (EPwm1Regs.TBPHS.all & ~0xFFFF0000) | 0x0;
// Time Base Counter Register
EPwm1Regs.TBCTR = 0x0000;
/* Clear counter*/
/*-- Setup Counter_Compare (CC) Submodule --*/
/* // Counter Compare Control Register
EPwm1Regs.CMPCTL.bit.SHDWAMODE
= 0;
// Compare A Register Block Operating Mode
EPwm1Regs.CMPCTL.bit.SHDWBMODE
= 0;
// Compare B Register Block Operating Mode
EPwm1Regs.CMPCTL.bit.LOADAMODE
= 0;
// Active Compare A Load
EPwm1Regs.CMPCTL.bit.LOADBMODE
= 0;
// Active Compare B Load
*/
EPwm1Regs.CMPCTL.all = (EPwm1Regs.CMPCTL.all & ~0x5F) | 0x0; //通过shadow写入
/* EPwm1Regs.CMPCTL2.bit.SHDWCMODE
= 0;
// Compare C Register Block Operating Mode
EPwm1Regs.CMPCTL2.bit.SHDWDMODE
= 0;
// Compare D Register Block Operating Mode
*/
EPwm1Regs.CMPCTL2.all = (EPwm1Regs.CMPCTL2.all & ~0x50) | 0x0;
EPwm1Regs.CMPA.bit.CMPA = 5000;
// Counter Compare A Register
EPwm1Regs.CMPB.bit.CMPB = 0;
// Counter Compare B Register
EPwm1Regs.CMPC = 0;
// Counter Compare C Register
EPwm1Regs.CMPD = 0;
// Counter Compare D Register
/*-- Setup Action-Qualifier (AQ) Submodule --*/
EPwm1Regs.AQCTLA.all = 96;
// Action Qualifier Control Register For Output A
注意是96十进制(0x60)
// =CMPA(up)时置高,=prd(down)时置低
EPwm1Regs.AQCTLB.all = 0;
// Action Qualifier Control Register For Output B
/* // Action Qualifier Software Force Register
EPwm1Regs.AQSFRC.bit.RLDCSF
= 0;
// Reload from Shadow Options
*/
EPwm1Regs.AQSFRC.all = (EPwm1Regs.AQSFRC.all & ~0xC0) | 0x0;
//(在等于0时加载)
/* // Action Qualifier Continuous S/W Force Register
EPwm1Regs.AQCSFRC.bit.CSFA
= 0;
// Continuous Software Force on output A
EPwm1Regs.AQCSFRC.bit.CSFB
= 0;
// Continuous Software Force on output B
*/
EPwm1Regs.AQCSFRC.all = (EPwm1Regs.AQCSFRC.all & ~0xF) | 0x0;
/*-- Setup Dead-Band Generator (DB) Submodule --*/
/* // Dead-Band Generator Control Register
EPwm1Regs.DBCTL.bit.OUT_MODE
= 0;
// Dead Band Output Mode Control
EPwm1Regs.DBCTL.bit.IN_MODE
= 0;
// Dead Band Input Select Mode Control
EPwm1Regs.DBCTL.bit.POLSEL
= 0;
// Polarity Select Control
EPwm1Regs.DBCTL.bit.HALFCYCLE
= 0;
// Half Cycle Clocking Enable
*/
EPwm1Regs.DBCTL.all = (EPwm1Regs.DBCTL.all & ~0x803F) | 0x0;
EPwm1Regs.DBRED.bit.DBRED = 0;
// Dead-Band Generator Rising Edge Delay Count Register
EPwm1Regs.DBFED.bit.DBFED = 0;
// Dead-Band Generator Falling Edge Delay Count Register
/*-- Setup Event-Trigger (ET) Submodule --*/
/* // Event Trigger Selection and Pre-Scale Register
EPwm1Regs.ETSEL.bit.SOCAEN
= 1;
// Start of Conversion A Enable
EPwm1Regs.ETSEL.bit.SOCASELCMP = 0;
EPwm1Regs.ETSEL.bit.SOCASEL
= 2 ;
// Start of Conversion A Select
EPwm1Regs.ETPS.bit.SOCAPRD
= 1;
// EPWM1SOCA Period Select
EPwm1Regs.ETSEL.bit.SOCBEN
= 0;
// Start of Conversion B Enable
EPwm1Regs.ETSEL.bit.SOCBSELCMP = 0;
EPwm1Regs.ETSEL.bit.SOCBSEL
= 1;
// Start of Conversion A Select
EPwm1Regs.ETPS.bit.SOCBPRD
= 1;
// EPWM1SOCB Period Select
EPwm1Regs.ETSEL.bit.INTEN
= 0;
// EPWM1INTn Enable
EPwm1Regs.ETSEL.bit.INTSELCMP = 0;
EPwm1Regs.ETSEL.bit.INTSEL
= 1;
// Start of Conversion A Select
EPwm1Regs.ETPS.bit.INTPRD
= 1;
// EPWM1INTn Period Select
*/
EPwm1Regs.ETSEL.all = (EPwm1Regs.ETSEL.all & ~0xFF7F) | 0x1A01;
EPwm1Regs.ETPS.all = (EPwm1Regs.ETPS.all & ~0x3303) | 0x1101;
/*-- Setup PWM-Chopper (PC) Submodule --*/
/* // PWM Chopper Control Register
EPwm1Regs.PCCTL.bit.CHPEN
= 0;
// PWM chopping enable
EPwm1Regs.PCCTL.bit.CHPFREQ
= 0;
// Chopping clock frequency
EPwm1Regs.PCCTL.bit.OSHTWTH
= 0;
// One-shot pulse width
EPwm1Regs.PCCTL.bit.CHPDUTY
= 0;
// Chopping clock Duty cycle
*/
EPwm1Regs.PCCTL.all = (EPwm1Regs.PCCTL.all & ~0x7FF) | 0x0;
/*-- Set up Trip-Zone (TZ) Submodule --*/
EALLOW;
EPwm1Regs.TZSEL.all = 0;
// Trip Zone Select Register
/* // Trip Zone Control Register
EPwm1Regs.TZCTL.bit.TZA
= 3;
// TZ1 to TZ6 Trip Action On EPWM1A
EPwm1Regs.TZCTL.bit.TZB
= 3;
// TZ1 to TZ6 Trip Action On EPWM1B
EPwm1Regs.TZCTL.bit.DCAEVT1
= 3;
// EPWM1A action on DCAEVT1
EPwm1Regs.TZCTL.bit.DCAEVT2
= 3;
// EPWM1A action on DCAEVT2
EPwm1Regs.TZCTL.bit.DCBEVT1
= 3;
// EPWM1B action on DCBEVT1
EPwm1Regs.TZCTL.bit.DCBEVT2
= 3;
// EPWM1B action on DCBEVT2
*/
EPwm1Regs.TZCTL.all = (EPwm1Regs.TZCTL.all & ~0xFFF) | 0xFFF;
/* // Trip Zone Enable Interrupt Register
EPwm1Regs.TZEINT.bit.OST
= 0;
// Trip Zones One Shot Int Enable
EPwm1Regs.TZEINT.bit.CBC
= 0;
// Trip Zones Cycle By Cycle Int Enable
EPwm1Regs.TZEINT.bit.DCAEVT1
= 0;
// Digital Compare A Event 1 Int Enable
EPwm1Regs.TZEINT.bit.DCAEVT2
= 0;
// Digital Compare A Event 2 Int Enable
EPwm1Regs.TZEINT.bit.DCBEVT1
= 0;
// Digital Compare B Event 1 Int Enable
EPwm1Regs.TZEINT.bit.DCBEVT2
= 0;
// Digital Compare B Event 2 Int Enable
*/
EPwm1Regs.TZEINT.all = (EPwm1Regs.TZEINT.all & ~0x7E) | 0x0;
/* // Digital Compare A Control Register
EPwm1Regs.DCACTL.bit.EVT1SYNCE
= 0;
// DCAEVT1 SYNC Enable
EPwm1Regs.DCACTL.bit.EVT1SOCE
= 1;
// DCAEVT1 SOC Enable
EPwm1Regs.DCACTL.bit.EVT1FRCSYNCSEL
= 0;
// DCAEVT1 Force Sync Signal
EPwm1Regs.DCACTL.bit.EVT1SRCSEL
= 0;
// DCAEVT1 Source Signal
EPwm1Regs.DCACTL.bit.EVT2FRCSYNCSEL
= 0;
// DCAEVT2 Force Sync Signal
EPwm1Regs.DCACTL.bit.EVT2SRCSEL
= 0;
// DCAEVT2 Source Signal
*/
EPwm1Regs.DCACTL.all = (EPwm1Regs.DCACTL.all & ~0x30F) | 0x4;
/* // Digital Compare B Control Register
EPwm1Regs.DCBCTL.bit.EVT1SYNCE
= 0;
// DCBEVT1 SYNC Enable
EPwm1Regs.DCBCTL.bit.EVT1SOCE
= 0;
// DCBEVT1 SOC Enable
EPwm1Regs.DCBCTL.bit.EVT1FRCSYNCSEL
= 0;
// DCBEVT1 Force Sync Signal
EPwm1Regs.DCBCTL.bit.EVT1SRCSEL
= 0;
// DCBEVT1 Source Signal
EPwm1Regs.DCBCTL.bit.EVT2FRCSYNCSEL
= 0;
// DCBEVT2 Force Sync Signal
EPwm1Regs.DCBCTL.bit.EVT2SRCSEL
= 0;
// DCBEVT2 Source Signal
*/
EPwm1Regs.DCBCTL.all = (EPwm1Regs.DCBCTL.all & ~0x30F) | 0x0;
/* // Digital Compare Trip Select Register
EPwm1Regs.DCTRIPSEL.bit.DCAHCOMPSEL
= 0;
// Digital Compare A High COMP Input Select
EPwm1Regs.DCTRIPSEL.bit.DCALCOMPSEL
= 1;
// Digital Compare A Low COMP Input Select
EPwm1Regs.DCTRIPSEL.bit.DCBHCOMPSEL
= 0;
// Digital Compare B High COMP Input Select
EPwm1Regs.DCTRIPSEL.bit.DCBLCOMPSEL
= 1;
// Digital Compare B Low COMP Input Select
*/
EPwm1Regs.DCTRIPSEL.all = (EPwm1Regs.DCTRIPSEL.all & ~ 0xFFFF) | 0x1010;
/* // Trip Zone Digital Comparator Select Register
EPwm1Regs.TZDCSEL.bit.DCAEVT1
= 0;
// Digital Compare Output A Event 1
EPwm1Regs.TZDCSEL.bit.DCAEVT2
= 0;
// Digital Compare Output A Event 2
EPwm1Regs.TZDCSEL.bit.DCBEVT1
= 0;
// Digital Compare Output B Event 1
EPwm1Regs.TZDCSEL.bit.DCBEVT2
= 0;
// Digital Compare Output B Event 2
*/
EPwm1Regs.TZDCSEL.all = (EPwm1Regs.TZDCSEL.all & ~0xFFF) | 0x0;
/* // Digital Compare Filter Control Register
EPwm1Regs.DCFCTL.bit.BLANKE
= 0;
// Blanking Enable/Disable
EPwm1Regs.DCFCTL.bit.PULSESEL
= 1;
// Pulse Select for Blanking & Capture Alignment
EPwm1Regs.DCFCTL.bit.BLANKINV
= 0;
// Blanking Window Inversion
EPwm1Regs.DCFCTL.bit.SRCSEL
= 0;
// Filter Block Signal Source Select
*/
EPwm1Regs.DCFCTL.all = (EPwm1Regs.DCFCTL.all & ~0x3F) | 0x10;
EPwm1Regs.DCFOFFSET = 0;
// Digital Compare Filter Offset Register
EPwm1Regs.DCFWINDOW = 0;
// Digital Compare Filter Window Register
/* // Digital Compare Capture Control Register
EPwm1Regs.DCCAPCTL.bit.CAPE
= 0;
// Counter Capture Enable
*/
EPwm1Regs.DCCAPCTL.all = (EPwm1Regs.DCCAPCTL.all & ~0x1) | 0x0;
/* // HRPWM Configuration Register
EPwm1Regs.HRCNFG.bit.SWAPAB
= 0;
// Swap EPWMA and EPWMB Outputs Bit
EPwm1Regs.HRCNFG.bit.SELOUTB
= 0;
// EPWMB Output Selection Bit
*/
EPwm1Regs.HRCNFG.all = (EPwm1Regs.HRCNFG.all & ~0xA0) | 0x0;
/* Update the Link Registers with the link value for all the Compare values and TBPRD */
/* No error is thrown if the ePWM register exists in the model or not */
EPwm1Regs.EPWMXLINK.bit.TBPRDLINK = 0;
EPwm1Regs.EPWMXLINK.bit.CMPALINK = 0;
EPwm1Regs.EPWMXLINK.bit.CMPBLINK = 0;
EPwm1Regs.EPWMXLINK.bit.CMPCLINK = 0;
EPwm1Regs.EPWMXLINK.bit.CMPDLINK = 0;
EDIS;
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
}
/* End of Start for S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */
}
/*接上面的主函数*/
rtmSetErrorStatus(c2807x_2837xx_adcpwmasynctes_M, 0);
//_M结构体中的错误标志赋值为0
c2807x_2837xx_adcpwmasynctest_ert_initialize();
//_M结构体赋值为NULL,_B结构体(只有一个ADC)赋值为0
configureTimer0(modelBaseRate, systemClock);
//开启Timer0中断(中断时长为步长),中断函数:TINT0_isr()
runModel =
rtmGetErrorStatus(c2807x_2837xx_adcpwmasynctes_M) == (NULL); //检测_M中错误标志是否是NULL
enableTimer0Interrupt();
//开启Timer0中断
enable_interrupts();
//开ADC中断,ADC中断函数为ADCA1_INT_isr()
globalInterruptEnable();
//开全局中断
while (runModel)
{
stopRequested = !(
rtmGetErrorStatus(c2807x_2837xx_adcpwmasynctes_M) == (NULL));
//stopRequested是一个标志,一直检测_M结构
中的错误标志是否发送了改变
}
/*Terminate mode*/
c2807x_2837xx_adcpwmasynctest_ert_terminate(); //空函数与设置中的Custom Code可能有关,以后进行测试一下
globalInterruptDisable();
//关中断
return 0;
}/*主函数完毕*/
主函数主要是完成了:
-
1.Timer0初始化为0.4s(求解器的步长)进入一次中断
-
2.初始化了ADC和ePWM模块(按照Simulink中的有关设置)
-
3.在主循环中一直在,获取一个标志位stopRequested ,推测可能是一个重要的函数运行/停止的标志
下面着重看一下两个中断函数:1.**Timer0中断 **[TINT0_isr()](这个中断并不是我们设置的,是系统求解器自动生成的一个中。可能与系统运行密切相关)。2.**ADC中断 **[ADCA1_INT_isr()],这个中断可能是完成我们需要的操作(把ADC采集的结果传送到ePWM的CMPA中,进而改变占空比)。
如上图所示,自动生成了以上四个文件,Timer0中断函数就在红框所示文件内。
interrupt void TINT0_isr(void)
{
//#define PIEMASK0
64
//#define IFRMASK
1
#ifdef PIEMASK0
//再MW_c28xx_pie.h文件中进行了相关的声明
volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;//PIE1中1.7是Timer0中断;1.1是ADC中断
#endif
/* #ifdef PIEMASK1
volatile unsigned int PIEIER2_stack_save
= PieCtrlRegs.PIEIER2.all;
#endif
#ifdef PIEMASK2
volatile unsigned int PIEIER3_stack_save
= PieCtrlRegs.PIEIER3.all;
#endif
#ifdef PIEMASK3
volatile unsigned int PIEIER4_stack_save
= PieCtrlRegs.PIEIER4.all;
#endif
#ifdef PIEMASK4
volatile unsigned int PIEIER5_stack_save
= PieCtrlRegs.PIEIER5.all;
#endif
#ifdef PIEMASK5
volatile unsigned int PIEIER6_stack_save
= PieCtrlRegs.PIEIER6.all;
#endif
#ifdef PIEMASK6
volatile unsigned int PIEIER7_stack_save
= PieCtrlRegs.PIEIER7.all;
#endif
#ifdef PIEMASK7
volatile unsigned int PIEIER8_stack_save
= PieCtrlRegs.PIEIER8.all;
#endif
#ifdef PIEMASK8
volatile unsigned int PIEIER9_stack_save
= PieCtrlRegs.PIEIER9.all;
#endif
#ifdef PIEMASK9
volatile unsigned int PIEIER10_stack_save = PieCtrlRegs.PIEIER10.all;
#endif
#ifdef PIEMASK10
volatile unsigned int PIEIER11_stack_save = PieCtrlRegs.PIEIER11.all;
#endif
#ifdef PIEMASK11
volatile unsigned int PIEIER12_stack_save = PieCtrlRegs.PIEIER12.all;
#endif*/
//这一段并不是注释掉了,表示文件中没有宏定义,目前没有起作用
#ifdef PIEMASK0
PieCtrlRegs.PIEIER1.all &= ~PIEMASK0;
/* disable group1 lower/equal priority interrupts */
#endif
#ifdef PIEMASK1
PieCtrlRegs.PIEIER2.all &= ~PIEMASK1;
/* disable group2 lower/equal priority interrupts */
#endif
#ifdef PIEMASK2
PieCtrlRegs.PIEIER3.all &= ~PIEMASK2;
/* disable group3 lower/equal priority interrupts */
#endif
#ifdef PIEMASK3
PieCtrlRegs.PIEIER4.all &= ~PIEMASK3;
/* disable group4 lower/equal priority interrupts */
#endif
#ifdef PIEMASK4
PieCtrlRegs.PIEIER5.all &= ~PIEMASK4;
/* disable group5 lower/equal priority interrupts */
#endif
#ifdef PIEMASK5
PieCtrlRegs.PIEIER6.all &= ~PIEMASK5;
/* disable group6 lower/equal priority interrupts */
#endif
#ifdef PIEMASK6
PieCtrlRegs.PIEIER7.all &= ~PIEMASK6;
/* disable group7 lower/equal priority interrupts */
#endif
#ifdef PIEMASK7
PieCtrlRegs.PIEIER8.all &= ~PIEMASK7;
/* disable group8 lower/equal priority interrupts */
#endif
#ifdef PIEMASK8
PieCtrlRegs.PIEIER9.all &= ~PIEMASK8;
/* disable group9 lower/equal priority interrupts */
#endif
#ifdef PIEMASK9
PieCtrlRegs.PIEIER10.all &= ~PIEMASK9;
/* disable group10 lower/equal priority interrupts */
#endif
#ifdef PIEMASK10
PieCtrlRegs.PIEIER11.all &= ~PIEMASK10;
/* disable group11 lower/equal priority interrupts */
#endif
#ifdef PIEMASK11
PieCtrlRegs.PIEIER12.all &= ~PIEMASK11;
/* disable group12 lower/equal priority interrupts */
#endif
#ifdef PIEMASK12
IER &= ~(M_INT13);
#endif
#ifdef PIEMASK13
IER &= ~(M_INT14);
#endif
asm(" RPT #5 || NOP");
/* wait 5 cycles */
//等待五个周期
IFR &= ~IFRMASK;
/* eventually disable lower/equal priority pending interrupts */
PieCtrlRegs.PIEACK.all = IFRMASK;
/* ACK to allow other interrupts from the same group to fire */
IER |= 1;
EINT;
/* global interrupt enable */
rt_OneStep();
DINT;
/* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR */
#ifdef PIEMASK0
PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK1
PieCtrlRegs.PIEIER2.all = PIEIER2_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK2
PieCtrlRegs.PIEIER3.all = PIEIER3_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK3
PieCtrlRegs.PIEIER4.all = PIEIER4_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK4
PieCtrlRegs.PIEIER5.all = PIEIER5_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK5
PieCtrlRegs.PIEIER6.all = PIEIER6_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK6
PieCtrlRegs.PIEIER7.all = PIEIER7_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK7
PieCtrlRegs.PIEIER8.all = PIEIER8_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK8
PieCtrlRegs.PIEIER9.all = PIEIER9_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK9
PieCtrlRegs.PIEIER10.all= PIEIER10_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK10
PieCtrlRegs.PIEIER11.all= PIEIER11_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK11
PieCtrlRegs.PIEIER12.all= PIEIER12_stack_save;/*restore PIEIER register that was modified */
#endif
#ifdef PIEMASK12
IER |= M_INT13;
#endif
#ifdef PIEMASK13
IER |= M_INT14;
#endif
}
- 1.建立一个堆栈PIEIER1_stack_save保存了PIE1的状态,
然后是这段代码:PieCtrlRegs.PIEIER1.all &= ~PIEMASK0;(PIEMASK0等于64,即:0100 0000)
~PIEMASK0为:1011 1111,与上PIE1之后可以发现,是将1.7(Timer0中断)位进行置零;就是关Timer0中断。
-
2.然后等待5个周期,将IFR最低位置为0,清除INT1的标志位。
-
3.将ACK1置为1,禁止同级中断响应。
-
4.将IER最低位置为1,应答。
-
5.开启全局中断。
然后进入函数 **rt_OneStep();**本程序中为空函数。[推测跟步长有关的函数将在此函数里面执行,比如GPIO翻转实验中的内容]
- 6.DINT,关闭全局中断。将PIE恢复为进入时候的状态,即重新开启Timer0中断。
其实感觉真正自己写的话,不用那么复杂。这里可能是Mathwork为了编写程序模块化写程序,进行了一定的固定设置。
下面看一下ADC中断函数()[ADCA1_INT_isr()]
interrupt void ADCA1_INT_isr(void)
{
isr_int1pie1_task_fcn();
EALLOW;
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
//清除ADC的标志位
EDIS;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
//应答
}
主要的函数内容都在**isr_int1pie1_task_fcn()**函数中:
void isr_int1pie1_task_fcn(void)
{
/* Call the system: <Root>/ADC-PWM Subsystem */
{
/* S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */
/* Output and update for function-call system: '<Root>/ADC-PWM Subsystem' */
{
/* local block i/o variables */
uint16_T rtb_Gain;
/* S-Function (c2802xadc): '<S1>/ADC' */
{
/*
Internal Reference Voltage : Fixed scale 0 to 3.3 V range.
*/
/*
External Reference Voltage : Allowable ranges of VREFHI(ADCINA0) = 3.3 and VREFLO(tied to ground) = 0
*/
c2807x_2837xx_adcpwmasynctest_B.ADC = (AdcaResultRegs.ADCRESULT0); //读取ADC采集结果
}
/* Gain: '<S1>/Gain' */
rtb_Gain = (uint16_T)(((uint32_T)c2807x_2837xx_adcpwmasynctest_P.Gain_Gain
* c2807x_2837xx_adcpwmasynctest_B.ADC) >> 13U);
//40960>>13*(ADC的采样结果)=5*(ADCresult)
/* S-Function (c2802xpwm): '<S1>/ePWM' */
/*-- Update CMPA value for ePWM1 --*/
{
EPwm1Regs.CMPA.bit.CMPA = (uint16_T)(rtb_Gain);
//将这个值赋给epwm的CMPA
}
}
/* End of Outputs for S-Function (c28xisr_c2000): '<Root>/C28x Hardware Interrupt' */
}
}
这里有点意思,因为Simulink中这里使用的是一个Function Call模块,可以猜想,里面含有其他的模块,可能也在这一部分。
最后看一下MW生成的这些文件都有哪些功能:
红框内的都是MW生成的文件,其他的都是库文件。
-
1.c2807x_2837xx_adcpwmasynctest_ert_data.c,(_data前面都是文件名,所以简记为:data文件),文件中存储了会使用到的一些参数,如这一次的常数5)
-
2.c2807x_2837xx_adcpwmasynctest_ert.c,这文件里面有ADC中断执行的isr_int1pie1_task_fcn函数。**c2807x_2837xx_adcpwmasynctest_ert_step()**函数,**c2807x_2837xx_adcpwmasynctest_ert_initialize()**函数,**c2807x_2837xx_adcpwmasynctest_ert_terminate()**函数。
可以看出是与模型相关的一些函数。
-
3.c2837xDBoard_Realtime_Support.c,一些板子的支持函数,通用性的功能函数。
-
4.c2837xDSchedulerTimer0.c,就是跟求解器步长相关的函数,如果加入积分模块很有可能就在这里运算。
-
5.MW_c28xGPIO.c,存放初始化GPIO和设置相关GPIO的函数。
-
6.MW_c28x_adc.c,存放ADC初始化和配置ADC的函数。
-
7.MW_c28x_board.c,存放初始化时钟和一些配置的相关函数(如外设属于CPU1还是CPU2等等)。
-
8.MW_c28x_csl.c,存放开启中断,以及中断函数如ADCA1_INT_isr)。
-
9.MW_c28x_pwm.c,配置开启PWM,需要使用的GPIO。
-
10.profiler_Support.c,感觉与调试相关。
下面尝试一下,如果不开启ADC中断,将ADC结果乘5赋值给CMPA将在哪部分完成!
结果是失败了,目测是跟这个模块关系非常大。
弄明白了,这个是通过CPU中断号和PIE中断号进行服务的中断函数,具体对应关系需要查看帮助文档。
这里给的CPU和PIE号都是1,而且这两个号码还能在模块中配置为向量,看来能够多个中断里面都使用一个函数体。
三、总结
总的来说,整个生成的程序有严格的框架,主要是步长会默认占用一个Timer0的中断,不知道这个能否进行改动。再就是其他的东西都与模型有严格的对照,非常建议第一次学习的时候,将模型和程序进行对照学习,收获会非常非常大的。环境搭建的步骤,我也已经上传了,有需要的可以看我的博文。
最后
以上就是复杂早晨为你收集整理的Matlab生成dsp程序——官方例程学习写在下面的话ADC-PWM例子学习的全部内容,希望文章能够帮你解决Matlab生成dsp程序——官方例程学习写在下面的话ADC-PWM例子学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复