我使用是的是DSPIC33EP64GS502,使用ADC0,1,2,3(对应4个专用ADC),以及ADC4(共用ADC),5路ADC都 使用通用软件触发,使用ADCON3Lbits.CNVCHSEL和 ADCON3Lbits.CNVRTCH配合。实现单独触发一个ADC采样。在中断中处理,并清除标志位。测试发现,ADC0及ADC4的中断标志为无法被清除,ADC1,2,3正常被清除。
代码如下:
void adc_init(void)
{
//ADC输入引脚初始化
// AN0
ANSELAbits.ANSA0=1;//使用模拟输入 RA0
TRISAbits.TRISA0=1;//配置为输入
// AN1
ANSELAbits.ANSA1=1;//使用模拟输入 RA1
TRISAbits.TRISA1=1;//配置为输入
//an2
ANSELAbits.ANSA2=1;//使用模拟输入 RA2
TRISAbits.TRISA2=1;//配置为输入
//an3
ANSELBbits.ANSB0=1;//使用模拟输入 Rb0
TRISBbits.TRISB0=1;//配置为输入
//an4
ANSELBbits.ANSB9=1;//使用模拟输入 Rb9
TRISBbits.TRISB9=1;//配置为输入
//ADC 专用内核输入选择
ADCON4Hbits.C0CHS=0;//ADC0 输入连接至AN0
ADCON4Hbits.C1CHS=0;//ADC1 输入连接至AN1
ADCON4Hbits.C2CHS=0;//AN2
ADCON4Hbits.C3CHS=0;//AN3
//ADC时钟选择
ADCON3Hbits.CLKSEL=0b01;//时钟视设置为系统时钟*2
ADCON3Hbits.CLKDIV=0;//1分频
//配置ADC内核时钟
ADCON2Lbits.SHRADCS=0;//2个内核源时钟周期
ADCORE0Hbits.ADCS=0;//ADC0 2个内核源时钟周期
ADCORE1Hbits.ADCS=0;//ADC1 2个内核源时钟周期
ADCORE2Hbits.ADCS=0;//ADC2
ADCORE3Hbits.ADCS=0;//ADC3
//选择ADC基准
ADCON3Lbits.REFSEL=0;//AVSS,AGND作为基准
//选择 ADC 分辨率
ADCON1Hbits.SHRRES=0b11;//共用 12位分辨率
ADCORE0Hbits.RES=0b11;//ADC0 12位分辨率
ADCORE1Hbits.RES=0b11;//ADC1 12位分辨率
ADCORE2Hbits.RES=0b11;//ADC2
ADCORE3Hbits.RES=0b11;//ADC3
//设置输出格式
ADCON1Hbits.FORM=0;//小数部分输出整数
//选择单端输入配置和无符号输出格式
ADMOD0Lbits.DIFF0=0;//单端输入模式
ADMOD0Lbits.SIGN0=0;//通道输出数据无符号
ADMOD0Lbits.DIFF1=0;//单端输入模式
ADMOD0Lbits.SIGN1=0;//通道输出数据无符号
ADMOD0Lbits.SIGN2=0;//通道输出数据无符号
//选择采样时间
ADCON2Hbits.SHRSAMC=0;//共用ADC内核采样时间 2 TADCORE
ADCORE0Lbits.SAMC=0;//ADC0 内核采样时间 2 TADCORE
ADCORE1Lbits.SAMC=0;//ADC1 内核采样时间 2 TADCORE
ADCORE2Lbits.SAMC=0;
ADCORE3Lbits.SAMC=0;
//启用并校准模块
EnableAndCalibrate();
//滤波器设置
ADFL0CONbits.FLEN=1;//使能滤波器
ADFL0CONbits.MODE=3;//过采样模式
ADFL0CONbits.OVRSAM=0b111;//14位数据,12 2 格式保存
ADFL0CONbits.FLCHSEL=0B0000;//an0数据输入过采样滤波器
ADFL0CONbits.IE=1;//产生滤波器中断
_ADFLTR0IF=0;//清除滤波器中断标志 _ADFLTR0IE
_ADFLTR0IE=0;//为滤波器启用中断 _ADFLTR0IF
// 配置并启用ADC中断。
ADIELbits.IE0 = 1; // 为AN0启用中断
ADIELbits.IE1 = 1; // 为AN1启用中断
ADIELbits.IE2 = 1; // 为AN2启用中断
ADIELbits.IE3 = 1; // 为AN3启用中断
ADIELbits.IE4 = 1; // 为AN4启用中断
_ADCAN0IF = 0; // 清除AN0的中断标志
_ADCAN0IE = 1; // 为AN0用中断
_ADCAN1IF = 0;
_ADCAN1IE = 1;
_ADCAN2IF = 0;
_ADCAN2IE = 1;
_ADCAN3IF = 0;
_ADCAN3IE = 1;
_ADCAN4IF = 0;
_ADCAN4IE = 1;
// 将所有输入的同一触发源同时设置为采样信号。
ADTRIG0Lbits.TRGSRC0 = 1; // 通用软件触发 2 for AN0
ADTRIG0Lbits.TRGSRC1 = 1; // 通用软件触发 2 for AN1
ADTRIG0Hbits.TRGSRC2 = 1; // 通用软件触发 for AN2
ADTRIG0Hbits.TRGSRC3 = 1; // 通用软件触发 for AN3
ADTRIG1Lbits.TRGSRC4 = 1; // 通用软件触发 for AN4
//通过 SWCTRG 位来触发所有选着通道
//CNVRTCH 软件单独通道转换触发为 CNVCHSEL<5:0>位指定的模拟输入产生单个触发信号
}
void adc_trigger(uint8 ch)//ADC 软件触发ADC CH通道采样
{
switch(ch)
{
case 0:{ ADCON3Lbits.CNVCHSEL=0;break;}//选择通道
case 1:{ ADCON3Lbits.CNVCHSEL=1;break;}//选择通道
case 2:{ ADCON3Lbits.CNVCHSEL=2;break;}//选择通道
case 3:{ ADCON3Lbits.CNVCHSEL=3;break;}//选择通道
case 4:{ ADCON3Lbits.CNVCHSEL=4;break;}//选择通道
default: break;
}
ADCON3Lbits.CNVRTCH=1;//单独触发选择通道
}
//温度1
void __attribute__((__interrupt__, no_auto_psv)) _ADCAN0Interrupt(void) //预计用时1300nS
{
ch1_data.count_a1++;
if(ch1_data.count_a1>15)
{
ch1_data.count_a1=0;
ch1_data.data_ready=1;
}
ch1_data.temp_buf[ch1_data.count_a1] =ADCBUF0;
led=1;
pid_control(ch1_data.temp_buf[ch1_data.count_a1],1058,pid1);//980uS
led=0;
_ADCAN0IE = 0;//这里有个问题没有被查到,标志位不能正常被清零,所以在这里关闭中断,再其他地方打开
_ADCAN0IF = 0;//清除中断标志位
}
//温度2
void __attribute__((__interrupt__, no_auto_psv)) _ADCAN1Interrupt(void)
{
ch2_data.count_a1++;
if(ch2_data.count_a1>15)
{
ch2_data.count_a1=0;
ch2_data.data_ready=1;
}
ch2_data.temp_buf[ch2_data.count_a1] =ADCBUF1;
_ADCAN1IF = 0;//清除中断标志位
}
//温度5
void __attribute__((__interrupt__, no_auto_psv)) _ADCAN4Interrupt(void)
{
//ch4_data.temp_buf[ch4_data.count_a1] =ADCBUF4;
_ADCAN4IF = 0;//清除中断标志位
_ADCAN4IF = 0;//清除中断标志位
_ADCAN4IF = 0;//清除中断标志位
_ADCAN4IF = 0;//清除中断标志位
}
|