📄 svpwm.c
字号:
/*******************************************************************************************
文件: SvPwm.c 空间矢量脉宽调制
标题: 通过事件管理产生PWM
条件: 本程序需要DSP281x V1.00头文件支持,另外需配置成"boot to H0"操作方式。
除了boot方式引脚配置外,无需其他硬件配置方式。
说明: 该程序设置EV定时器(TIMER1, TIMER2, TIMER3 and TIMER4),用于产生T1PWM,
T2PWM, T3PWM, T4PWM and PWM1-PWM12波形。可通过示波器观察这些波形。
在以下几个方面对TI提供的驱动源码进行了硬件和软件的增强:
(1) 增加了LED数码管显示的硬件接口。以便将EvPwm发生的次数反映在LED数码管上。
(2) 在更新EvPwm时,增加了受GPIO A控制的16个Led发光二极管的闪烁显示。
(3) 增加了320*240液晶屏及与之配套的软件。
*******************************************************************************************/
#include "DSP281x_Device.h" // DSP281x 头文件包含文件
#include "DSP281x_Examples.h" // DSP281x 示例包含文件
//**********************************************//
#include "float.h"
#include "math.h"
float ualfa[200],ubeta[200]; // 存储电压矢量Uout的(α,β)坐标轴分量Ualfa,
// Ubeta的数组
Uint16 sector[200]; // 定义存储扇区数的数组
#define PI2 2*3.1415926 // 定义2π的值
#define DETA PI2/200 // 定义相邻两个Uout之间的电度角的差值
#define INIA 3.1415926/180 // 定义Uout的初始电度角
//Uint16 TP=3000;
static int TP=3000; // 周期寄存器的值,其值(1200)等于SVPWM调制周期T的
// 一半,因为在该程序中2π电度角内Uout的点数一
// 定,故改变此值可以改变输出的三相正弦交流电压的频
//float KP=0.7; // 率
static float KP=0.7; // 定义Uout的标么值,KP的值在0和1之间,改变此
// 值可以改变逆变桥输出电压的幅值
static int receive[5]; // 串口通讯数据接收数组
//static int transfer[7]; // 串口通讯数据发送数组
//Uint16 receive[5];
void calu();
void SECTOR();
void scib_fifo_init();
void interrupt uarttr();
interrupt void scibRxFifoIsr(void);
int anticlk[6]={0x1666,0x3666,0x2666,0x6666,0x4666,0x5666}; // 逆时针旋转的6个基本矢量
//**********************************************//
// 本文件建立的函数原型声明。
void init_eva(void); // EVA配置T1PWM, T2PWM, PWM1-PWM6 ,初始化定时器
void init_evb(void); // EVB配置T3PWM, T4PWM, PWM7-PWM12 ,初始化定时器
void delay(); // 延时函数
interrupt void adc_isr(void);
void OscillographTable(); // 制作示波器表格
void VoltageCurve();
void AdcResultCopy();
Uint16 *Xaddr=(Uint16 *)0x13f000;
Uint16 Xram_pointer=0;
// 本例的全局变量
// 外部函数声明。由Bc7281.c 文件建立
void LedD_Display(void);
// 将模数转换值以10进制形式,在Led第4,3,2,1位数码管上进行显示
void LedH_Display(void);
// 将模数转换值以16进制两个字节形式,在Led第8,7,6,5位数码管上进行显示
// 本例中的全局计数器
Uint16 count=0,i;
void main(void)
{
int i,k=0,cmp1,cmp2;
float x,y,z;
// 步骤1 系统控制初始化: 锁相环(PLL),看门狗(WatchDog)及外设时钟
// (PeripheralClocks)初始化。该函数在DSP281x_SysCtrl.c文件中建立。
InitSysCtrl();
// 步骤2.初始化GPIO:
// 这个函数例举怎样将GPIO设置成其默认状态,该函数由DSP281x_Gpio.c文件建立。
// InitGpio(); // 本例跳过这个函数
lcd_init();
clearscr1(); // 第一显示缓冲区(0x0000-0x29ff)清零
clearscr2(); // 第二显示缓冲区(0x2a00-0x53ff)清零
clearscr3(); // 第三显示缓冲区(0x5400-0x7dff)清零
OscillographTable();
// 对于这个检测仅初始化GPAMUX和GPBMUX
EALLOW; //允许访问受保护的空间
GpioMuxRegs.GPAMUX.all = 0x00FF; // 使能EVA PWM 1-6 脚
GpioMuxRegs.GPBMUX.all = 0x00FF; // 使能EVB PWM 7-12 脚
EDIS; //禁止访问受保护的空间
EALLOW; // 允许访问受保护的寄存器
GpioMuxRegs.GPAMUX.all=0x0000; // 将A端口设置成IO方式
GpioMuxRegs.GPADIR.all=0xffff; // 将GPIO A所有15个端口配置成数字量输出
EDIS; // 禁止访问受保护的寄存器
GpioDataRegs.GPADAT.all=0xAAAA; // 间隔一个点亮LED发光二极管。
// 步骤3 关所有中断并初始化PWM矢量表
DINT; // 关CPU中断
InitPieCtrl(); // 初始化PIE控制寄存器为默认状态。该状态关所有PIE中断并清除所
// 有标识。该函数在DSP281x_PieCtrl.c文件中建立。
IER = 0x0000; // 关CPU中断并清CPU中断标识。
IFR = 0x0000;
InitPieVectTable();
// 初始化PIE向量表,该向量表指出中断服务程序(ISR)的构架。即使在本范例中
// 没有用到中断,仍旧组装整张表。它在程序调试时是很有用的。ISR程序构架由
// DSP281x_DefaultIsr.c文件建立
// InitPieVectTable()函数由DSP281x_PieVect.c文件建立
//##################
// 本例用到的中断重新映射到由本文件建立的ISR函数中。
//******************************************************************************************
// 关于 "PieVectTable.ADCINT = &adc_isr;" 指令的说明
// 1. adc_isr 是一个ADC模块中断服务程序(ISR)。
// 2. 这个中断程序与中断扩展(PIE)向量表第1组INT1第6个中断向量ADCINT(ADC)对应。
// 3. 为了使这个程序响应对应的中断,还需作如下配置:
//
// PieCtrlRegs.PIECRTL.bit.ENPIE = 1;
// 使能PIE向量表。这条指令包含在上面调用的InitPieVectTable()函数中。
//
// IER |= M_INT1; // 使能PIE向量表第1组CPU INT1中断
// PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断
// EINT; // 允许可屏蔽中断(清INTM位)
//
// 这几条指令在本程序的后续指令中可以找到。这样,在发生ADCINT中断的情况下,将
// 执行adc_isr()中断服务程序。
// "PieVectTable.ADCINT = &adc_isr;" 指令实际上就是通知编译器,在发生ADCINT
// 中断的情况下,将执行adc_isr()中断服务程序。adc_isr头上的"&"为取地址运算符。
//******************************************************************************************
EALLOW; // 允许访问受保护的寄存器
PieVectTable.ADCINT = &adc_isr;
EDIS; // 禁止访问受保护的寄存器
EALLOW;
PieVectTable.RXBINT = &scibRxFifoIsr;
EDIS;
// 步骤4. 初始化器件所有外围设备:
//这个函数由DSP281x_InitPeripherals.c文件建立。
// InitPeripherals(); // 本例不需要
InitAdc(); // 初始化ADC模块
PieCtrlRegs.PIEIER9.bit.INTx3=1; // 使能PIE 第9组 INT3(RXBINT)中断
// Step 5. User specific code, enable interrupts:
// 步骤5. 用户代码,中断使能:
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // 使能PIE向量表第一组第6个ADCINT中断
IER |= (M_INT1 | M_INT9 ); // M_INT1=0x0001, 意为使能包含ADC转换的第1组中断
// M_INT9=0x0100, 意为使能包含SCI-B的第9组中断
EINT; // 允许可屏蔽中断(清INTM位)
ERTM; // ERTM指令在外围设备头文件(DSP281x_Device.h)中有定义:
// #define ERTM asm(" clrc DBGM")。即清除DBGM位,作用为使能全局实时中断
//******************************************************************************************
// 关于输入通道选择序列控制寄存器注解:
//
// ADCCHSELSEQ1-ADCCHSELSEQ4 为4个16位ADC输入通道选择序列控制寄存器,从ADCCHSELSEQ1
// 最低位开始,每一个4位值CONVnn(0<=nn<15)可以选择16个模拟输入通道(A通道或是B通道)中
// 的任何一路。每一个ADCCHSELSEQn(1<=n<=4)管理4个固定的CONVnn,其对应关系见下面注释.
// 输入通道选择个数必须与ADC最大转换通道(数)寄存器(ADCMAXCONV)的配置相匹配.
//
// ADCCHSELSEQ1[3:0] =CONV00, ADCCHSELSEQ3[3:0] =CONV08,
// ADCCHSELSEQ1[7:4] =CONV01, ADCCHSELSEQ3[7:4] =CONV09,
// ADCCHSELSEQ1[11:8] =CONV02, ADCCHSELSEQ3[11:8] =CONV10,
// ADCCHSELSEQ1[15:12]=CONV03, ADCCHSELSEQ3[15:12]=CONV11,
// ADCCHSELSEQ2[3:0] =CONV04, ADCCHSELSEQ4[3:0] =CONV12,
// ADCCHSELSEQ2[7:4] =CONV05, ADCCHSELSEQ4[7:4] =CONV13,
// ADCCHSELSEQ2[11:8] =CONV06, ADCCHSELSEQ4[11:8] =CONV14,
// ADCCHSELSEQ2[15:12]=CONV07, ADCCHSELSEQ4[15:12]=CONV15,
//
// 注意:
// 每一个4位值CONVnn可以选择ADC的16个模拟输入通道中的任何一路。下面16个CONVnn
// 全部选择ADCINA7引脚,第8通道。系统的每一次序列化(16次)采样都针对同一个通道进行。
// 程序规定一个完整的采样由16个序列化采样组成,即在一个采样点上完成256次采样。256个
// 采样数据通过模数转换结果寄存器直接顺序存入起始地址为0x0013f000的外存空间。
//
//******************************************************************************************
AdcRegs.ADCMAXCONV.all = 0x000f; // 配置SEQ1模式16通道
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0x7; // 选择ADCINA7引脚,第8通道。
AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; // 使能EVASOC 启动SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能SEQ1 中断 (在每一个EOS时)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 连续采样方式配置
// SMODE_SEL: 采样方式选择位。
// 当SMODE_SEL=0, 连续采样方式; 当SMODE_SEL=1, 并发采样方式。
// 所谓连续采样方式是指:一旦启动转换,则转换按照当前CONVxx决定的顺序
// 进行,xx 4位值的最高位确定是A引脚还是B引脚,低3位确定A引脚或B引脚
// 的偏移量,采样结果依次存入结果寄存器。在并发采样方式下,xx 最高位
// 被舍弃,系统根据低3位的偏移量先进行对应A引脚的采样再进行对应B引脚
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -