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进入一次中断。
1
2
3
4
5float modelBaseRate = 0.4; float systemClock = 200; …… ConfigCpuTimer(&CpuTimer0, systemClock, baseRate *1000000);//baseRate=modelBaseRate
二、生成代码分析
生成四个变量:
1
2
3
4
5
6volatile int IsrOverrun = 0; static boolean_T OverrunFlag = 0; volatile boolean_T stopRequested = false; volatile boolean_T runModel = false; //三个布尔型变量,一个int形
进入主函数之后生成两个浮点型变量:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16int 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环境也支持调试 /*接下下个代码块部分*/
下面先看一个结构体:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18c2807x_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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366void 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' */ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/*接上面的主函数*/ 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中断函数就在红框所示文件内。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165interrupt 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()]
1
2
3
4
5
6
7
8
9
10
11interrupt 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()**函数中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34void 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程序——官方例程学习写在下面内容请搜索靠谱客的其他文章。
发表评论 取消回复