-------- 主要功能: 用PWM波触发中断,3路ADC ---------
1. 定时中断0,驱动48口LED闪烁,低电平有效;
2. A0口采集脉搏信号,A1和A2口分别采集不同频率的方波
3. 在IO2和IO4口上产生125Hz,占空比为50%的方波
4. 采用1500Hz频率进行采样。
5. 将IO2与ADC1口连接,IO4与ADC2口连接,脉搏传感器的s端与ADC0连接,-端与33脚连接,+与3V3连接
************* end *******************/
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
interrupt void AdcIsr(void); //ADC中断服务子函数声明
interrupt void cpu_timer0_isr(void); //定时器0中断服务子函数声明
void InitMyGpio(); //GPIO48口初始化函数声明,LED闪烁
void InitEPWM(); //EPWM2初始化函数声明
void InitMyAdc(void); //ADC初始化函数声明
#define startCpuTimer0() CpuTimer0Regs.TCR.bit.TSS=0 //定时器0启动指令宏定义
#define BUF_SIZE 1024 // 信号缓存区长度
#define TimerPeriod 1000 //定时器1000us=1ms
// ADC时钟初始参数设置,对SYSCLKOUT分频后形成HSPCLK,用于ADC
#if (CPU_FRQ_150MHZ) // Default - 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
#define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2) = 25.0 MHz
#endif
float SampleTable0[BUF_SIZE];//存储脉搏信号
float SampleTable1[BUF_SIZE];//IO2信号
float SampleTable2[BUF_SIZE];//IO4信号
Uint16 SampleDone=0;
void main(void)
{
Uint16 i;
//-----1.系统和中断向量表初始化
InitSysCtrl();
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
//-----2.中断服务地址重新映射
//2.1 中断映射
EALLOW;
PieVectTable.TINT0 = &cpu_timer0_isr;//定时器0中断映射
PieVectTable.ADCINT = &AdcIsr;//ADC中断映射
//PieVectTable.XINT13 = &cpu_timer1_isr;
//PieVectTable.TINT2 = &cpu_timer2_isr;
EDIS;
//-----3.在PIE级和CPU级,开全局中断
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;//使能ADC中断(INT1.6)
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;//定时器0中断(INT1.6)
IER |= M_INT1;
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
//------4.ADC初始化
//4.1.ADC初始时钟设置
//EALLOW;
//SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
//EDIS;
//4.2使能AD时钟、完成AD校准及上电,该程序可见TI例程DSP2833x_Adc.c文件
InitAdc();
//4.3 详细配置ADC
InitMyAdc();
//------5.GPIO初始化
InitMyGpio(); //配置GPIO48为IOs输出功能,GPIO2为PWM模式
//------6.定时器初始化及启动
//6.1 定时器初始化
InitCpuTimers(); // For this example, only initialize the Cpu Timers
//6.2 定时器定时周期初始化
#if (CPU_FRQ_150MHZ)
// Configure CPU-Timer 0, 1, and 2 to interrupt every 1000 usecond:
// 150MHz CPU Freq, 1 second Period (in uSeconds)
ConfigCpuTimer(&CpuTimer0, 150, TimerPeriod);
//ConfigCpuTimer(&CpuTimer1, 150, 1000000);
//ConfigCpuTimer(&CpuTimer2, 150, 1000000);
#endif
#if (CPU_FRQ_100MHZ)
// Configure CPU-Timer 0, 1, and 2 to interrupt every 100 usecond:
// 100MHz CPU Freq, 1 second Period (in uSeconds)
ConfigCpuTimer(&CpuTimer0, 100, TimerPeriod)
//ConfigCpuTimer(&CpuTimer1, 100, 1000000);
//ConfigCpuTimer(&CpuTimer2, 100, 1000000);
#endif
//6.3 启动定时器
startCpuTimer0();
//------7.初始化PWM2模块
InitEPWM(); //配置ePWM2模块
//------8.清空缓存区
for (i=0; i<BUF_SIZE; i++)
{
SampleTable0[i] = 0;
SampleTable1[i] = 0;
SampleTable2[i] = 0;
}
while(1)
{
if (SampleDone==1)
{ for ( i=0; i<BUF_SIZE-1; i++)
{
SampleTable0[i] = SampleTable0[i+1];
SampleTable1[i] = SampleTable1[i+1];
SampleTable2[i] = SampleTable2[i+1];
}
SampleDone=0;
}
}
}
interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++; //中断计数器,用于计算中断的响应次数
if(CpuTimer0.InterruptCount==500) //每个1sLED闪烁一次
{
GpioDataRegs.GPBTOGGLE.bit.GPIO48 = 1;
CpuTimer0.InterruptCount=0;
}
// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
CpuTimer0Regs.TCR.bit.TIF=1;//清除中断标志位
CpuTimer0Regs.TCR.bit.TRB=1;//重新装载初值
}
void InitMyGpio()
{
EALLOW;
// 配置GPIO48为普通IO口输出功能
GpioCtrlRegs.GPBMUX2.all=0x00000000; //功能选择寄存器 普通IO使用,GPIO48属于GPBMUX2
GpioCtrlRegs.GPBDIR.all=0xFFFFFFFF; //设置为输出模式
//配置GPIO2为EPWM2a功能
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0; //使能上拉
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; //作为EPWM2a功能
//配置GPIO4为EPWM3a功能
GpioCtrlRegs.GPAPUD.bit.GPIO4 = 0; //使能上拉
GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1; //作为EPWM3a功能
EDIS;
}
void InitEPWM()
{
EPwm2Regs.TBCTL.bit.CTRMODE = 0; //连续增计数模式
EPwm2Regs.TBCTL.bit.HSPCLKDIV = 3; //配置高速时钟/6分频;=2*k,k=1-7,k=0时1分频
EPwm2Regs.TBCTL.bit.CLKDIV = 2; //对输入时钟/4分频,2的k次方,k=0-7
EPwm2Regs.AQCTLA.bit.ZRO = 2; //计数值为0时,EPWM2a输出高电平
EPwm2Regs.AQCTLA.bit.CAU = 1; //计数值为比较值时,EPWM2a输出低电平
EPwm2Regs.TBPRD = 49999; //配置周期值,信号频率为150M / (6*4)/ (TBPRD+1) = 125Hz
EPwm2Regs.CMPA.half.CMPA = (EPwm2Regs.TBPRD+1)/2;//配置比较值
EPwm3Regs.TBCTL.bit.CTRMODE = 0; //连续增计数模式
EPwm3Regs.TBCTL.bit.HSPCLKDIV = 3; //配置高速时钟/6分频
EPwm3Regs.TBCTL.bit.CLKDIV = 2; //对输入时钟/4分频
EPwm3Regs.AQCTLA.bit.ZRO = 2; //计数值为0时,EPWM3a输出高电平
EPwm3Regs.AQCTLA.bit.CAU = 1; //计数值为比较值时,EPWM3a输出低电平
EPwm3Regs.TBPRD = 49999; //配置周期值,信号频率为150M / (6*4)/ (TBPRD+1) = 125Hz
EPwm3Regs.CMPA.half.CMPA= (EPwm2Regs.TBPRD+1)/2;//配置比较值
}
void InitMyAdc(void)
{
AdcRegs.ADCTRL1.bit.CPS = 1; //内核时钟/2分频=75MHz
AdcRegs.ADCTRL3.bit.ADCCLKPS = 1; //AdcClk = 75MHz/(2*(1+1))=18.75Mhz
AdcRegs.ADCMAXCONV.all = 0x0003; // SEQ1中有3个转换
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x00; // Setup ADCINA0 as 1st SEQ1 conv.
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x01; // Setup ADCINA1 as 2nd SEQ1 conv.
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x02; // Setup ADCINA2 as 3nd SEQ1 conv.
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x03; // Setup ADCINA3 as 4st SEQ1 conv.
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // 允许ePWM触发SEQ1转换
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 允许SEQ1中断
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0; //在每个SEQ1转换结束后产生中断
// 配置ePWM1触发ADC
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能ePWMa触发AD转换
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // 选择当计数值递增至CMPA作为触发事件
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // 在第一个触发事件后即产生触发脉冲
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // 增计数模式
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; //HSPCLKDIV选择2分频
EPwm1Regs.TBCTL.bit.CLKDIV = 0; //CLKDIV选择不分频
EPwm1Regs.TBPRD = 49999; //设置周期值,采样频率为150M / (1*2)/ (TBPRD+1) = 1500Hz
EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD /2; // 设置比较值
}
interrupt void AdcIsr(void)
{
SampleDone=1;
SampleTable0[BUF_SIZE-1] = 3.0*(AdcRegs.ADCRESULT0 >>4)/4095;
SampleTable1[BUF_SIZE-1] = 3.0*(AdcRegs.ADCRESULT1 >>4)/4095;
SampleTable2[BUF_SIZE-1] = 3.0*(AdcRegs.ADCRESULT2 >>4)/4095;
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位排序器至CONV00
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // 清除SEQ1中断标志位
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 应答PIE分组中断
}