//main函数
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
#include "epwm.h"
#include "adc.h"
void EPWM_init();
void EPWM_Configure(void);
void ADC_Configure();
__interrupt void adc_isr(void);
__interrupt void timer1_isr(void);
//Uint16 LoopCount;
void main()
{
//步骤1。初始化系统控制:锁相锁、看门狗、使能外围时钟此功能在DSP2833x_SysCtrl.c文件中找到。
InitSysCtrl();
// EALLOW;
// #if (CPU_FRQ_150MHZ) //默认- 150MHz SYSCLKOUT
// // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
// #define ADC_MODCLK 0x3 //将ADC的工作频率设置为25MHz,等同于上一条语句
// #endif
// #if (CPU_FRQ_100MHZ)
// // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2) = 25.0 MHz
// #define ADC_MODCLK 0x2
// #endif
// EDIS;
// 定义ADCCLK时钟频率(小于或等于25MHz)
// 假设InitSysCtrl()将SYSCLKOUT设置为150 MHz
// EALLOW;
// SysCtrlRegs.HISPCP.all = ADC_MODCLK;
// EDIS;
//步骤2。初始化GPIO:
InitGpio();
//步骤3。清除所有中断并初始化PIE向量表:禁用CPU中断
DINT;
//将PIE控制寄存器初始化为其默认状态。默认状态是禁用所有PIE中断并清除标志。
InitPieCtrl();
//禁用CPU中断并清除所有CPU中断标志:
IER = 0x0000;
IFR = 0x0000;
//用指向shell中断服务例程(ISR)的指针初始化PIE向量表。
InitPieVectTable();
//本例中使用的中断被重新映射到该文件中的ISR函数。
EALLOW; // 写保护
PieVectTable.ADCINT = &adc_isr; //设置ADCINT中断服务程序的入口地址为adc_isr
PieVectTable.EPWM1_INT = &timer1_isr; //设置EPWM1_INT中断服务程序的入口地址为timer1_isr
EDIS; // 禁用写保护
//步骤4。初始化所有设备外设:
InitAdc(); //Adc初始化
EPWM_init(); //EPWM初始化
//第5步。自定义,启用中断:
//在PIE中启用SEQ1INT
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; //中断向量表第1列
IER |= M_INT1; // 开启CPU中断1,第一行
//在PIE中启用EPWM1_INT
IER|=M_INT3; //使能CPU中断3(中断向量表第三行)
PieCtrlRegs.PIEIER3.bit.INTx1 = 1; //EPWM1中断(中断向量表第1位,即第一列)
EINT; // 启用全局中断INTM
ERTM; // 启用全局实时中断DBGM
// LoopCount = 0;
// //ADC配置
// AdcRegs.ADCMAXCONV.all = 0x0001; // 在SEQ1上设置2个转换器
// AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // 设置ADCINA3为第一个SEQ1转换。
// AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x2; // 设置ADCINA2为第二个SEQ1转换器。
//
// //启用SOCA从ePWM启动SEQ1
// AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
// AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能SEQ1中断(每个EOS)
//假设在InitSysCtrl()中已经启用了ePWM1时钟。
// EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能ADC启动脉冲EPWMxSOCA
// EPwm1Regs.ETSEL.bit.SOCASEL = 4; // TBCTR=CMPA且计数器处于递增状态时产生
// EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 每发生一次事件,产生一次ADC信号
// EPwm1Regs.CMPA.half.CMPA = 0x0080; // 设置比较值A
// EPwm1Regs.TBPRD = 0xFFFF; // 设置ePWM1的周期
// EPwm1Regs.TBCTL.bit.CTRMODE = 0; // count up and start
EPWM_Configure();
ADC_Configure();
// 等待ADC中断
for(;;)
{
}
}
////ADC
//ADC相关参数
#define ADC_MODCLK 0x3 //HSPCLK = SYSCLKOUT/2 * ADC_MODCLK2 = 150/(2 * 3) = 25MHz
#define ADC_CKPS 0x0 //ADC时钟 = HSPCLK/1 = 25.5MHz/(1) = 25.0MHz
#define ADC_SHCLK 0x1 //采样保持器宽度 = 2ADC时钟周期
#define BUF_SIZE 16 //缓存大小
#define OFFSET 0
float SampleTable[BUF_SIZE]; //保存采样结果
void ADC_Configure()
{
Uint16 i;
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK;
ADC_cal();//调用 ADC_cal 汇编程序,它是 TI 提供的 ADC 校准程序,直接使用即可
EDIS;
AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK; //设置采集窗口大小;这个位场控制Soc脉冲的宽度,这反过来决定了采样开关关闭的持续时间。SOC脉冲的宽度为(ACQ_PS + 1)ADCLK周期。
AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS; //ADC时钟分频器;对F28x外设时钟 HSPCLK进行2×ADCLKPS[3:0]的分额,分频后的时钟再进行ADCTRL1[7]+1分频从而产生ADC的内核时钟ADCCLK
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; //级联方式
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; //顺序采样
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; //对ADC序列发生器进行赋值,就是设定ADC采样通道的采样顺序(例:第一次采样D0通道)
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; //例:第二次采样D1通道
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4;
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5;
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6;
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7;
AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x8;
AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x9;
AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xA;
AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0xB;
AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0xC;
AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0XD;
AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0xE;
AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0xF;
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; //连续转换模式
AdcRegs.ADCTRL1.bit.SEQ_OVRD = 1;
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0xF; //设置最大采样通道数,上面是16个通道,所以设置为F(若是一个通道则赋值0,两个通道则赋值1)
DINT;
for(i=0;i<BUF_SIZE;i++)
{
SampleTable[i] = 0;
}
//启用SOCA从ePWM启动SEQ1
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 使能SEQ1中断(每个EOS)
}
// Adc中断
__interrupt void adc_isr(void)
{
Uint16 array_index = 0;
Uint16 j;
for(j=0;j<(BUF_SIZE/16);j++)
{
while(AdcRegs.ADCST.bit.INT_SEQ1 == 0){} //等待,直到转换完成,然后读取结果
LED1_ON;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT0)>>4)*3.0/4095.0 - OFFSET; //OFFSET为偏置,通常为0
SampleTable[array_index++] = ((AdcRegs.ADCRESULT1)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT2)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT3)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT4)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT5)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT6)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT7)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT8)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT9)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT10)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT11)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT12)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT13)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT14)>>4)*3.0/4095.0 - OFFSET;
SampleTable[array_index++] = ((AdcRegs.ADCRESULT15)>>4)*3.0/4095.0 - OFFSET;
LED1_OFF;
// 为下一个ADC序列重新初始化
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 重置SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; //清除标志位
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 向PIE确认中断
return;
}
}
////EPWM
unsigned int i;
void EPWM_init()
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; //GPIO0 = PWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; //GPIO1 = PWM1B
EDIS;
//PWM1A.PWM1B
EPwm1Regs.TBPRD = 0xFFFF; //设置EPWM1周期寄存器
EPwm1Regs.TBPHS.half.TBPHS = 0x0000; //相位为0
EPwm1Regs.TBCTR = 0x0000; //清除计数器
//设置比较寄存器
EPwm1Regs.CMPA.half.CMPA = 0xFFFF; //设置比较寄存器A
EPwm1Regs.CMPB = 0xFFFF; //设置比较寄存器B
//设置计数模式
EPwm1Regs.TBCTL.bit.CTRMODE = 2; //增减计数模式
EPwm1Regs.TBCTL.bit.PHSEN = 0; //禁止相位功能
EPwm1Regs.TBCTL.bit.PRDLD = 0; //使用映射功能
EPwm1Regs.TBCTL.bit.SYNCOSEL = 1; //选择同步信号为CTR=0;
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; //TBCLK = SYSCLKOUT/2 = 75MHz
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;
//设置映射模式
EPwm1Regs.CMPCTL.bit.SHDWAMODE = 0; //CMPA采用映射模式
EPwm1Regs.CMPCTL.bit.SHDWBMODE = 0; //CMPB采用映射模式
EPwm1Regs.CMPCTL.bit.LOADAMODE = 0; //CTR=0时加载CMPA
EPwm1Regs.CMPCTL.bit.LOADBMODE = 0; //CTR=0时加载CMPB
//设置死区模式
EPwm1Regs.DBCTL.bit.OUT_MODE = 0x3; //使能上升沿和下降沿延时
EPwm1Regs.DBCTL.bit.POLSEL = 0x2; //ePWMxA不翻转,ePWMxB翻转
EPwm1Regs.DBCTL.bit.IN_MODE = 0x2; //ePWMxA是上升沿延时输入源,ePWMxB是下降沿延时输入源
//设置EPWM中断
// EPwm1Regs.ETSEL.bit.INTSEL = 1; //中断事件 TBCTR=0x0000
// EPwm1Regs.ETSEL.bit.INTEN = 1; //使能EPWM1中断
// EPwm1Regs.ETPS.bit.INTPRD = 1; //开关频率10KHz,对应中断频率10KHz
// EPwm1Regs.ETCLR.bit.INT = 1; //清除中断标志
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能ADC启动脉冲EPWMxSOCA
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // TBCTR=CMPA且计数器处于递增状态时产生
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 每发生一次事件,产生一次ADC信号
//设置引脚动作
//当CTR=CMPA并减计数时,EPWMA输出低电平;当CTR=CMPA且增计数时,EPWMA输出高电平
EPwm1Regs.AQCTLA.all = 0x0060;
//当CTR=CMPB并减计数时,EPWMB输出低电平;当CTR=CMPA且增计数时,EPWMB输出高电平
EPwm1Regs.AQCTLB.all = 0x0060;
}
void EPWM_Configure(void) //EPWM配置
{
EALLOW;
EPwm1Regs.TBPRD = 37500; //频率为10KHz
EPwm1Regs.TBPHS.half.TBPHS = 0x0000;
EPwm1Regs.DBRED = 75 * 0.6; //上升沿死区为300ns 每增加0.1,死区增加50ns
EPwm1Regs.DBFED = 75 * 0.6; //下降沿死区为300ns
EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD * 0.5; //占空比为50%
EDIS;
}
__interrupt void timer1_isr(void) //周期为0.1ms
{
i++;
if(i > 10000)i = 0; //1s
EPwm1Regs.ETCLR.bit.INT = 1; //清除中断标志位
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;//相应同组中断
}


