打印

ADC 中断标志无法复位

[复制链接]
627|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
DSPIC33EP64GS502,使用ADC0,1,2,3(对应4个专用ADC),以及ADC4(共用ADC),5路ADC都 使用通用软件触发,使用ADCON3Lbits.CNVCHSEL和 ADCON3Lbits.CNVRTCH配合。实现单独触发一个ADC采样。在中断中处理,并清除标志位。测试发现,ADC0及ADC4的中断标志为无法被清除,ADC1,2,3正常被清除。

使用特权

评论回复
沙发
chenjunt|  楼主 | 2020-9-10 19:41 | 只看该作者

什么意思?不是很明白你说的什么,能再解释一下这个现象吗

使用特权

评论回复
板凳
chenjunt|  楼主 | 2020-9-10 19:45 | 只看该作者

使用特权

评论回复
地板
wangzsa| | 2020-9-10 19:48 | 只看该作者

楼主程序可以公开吗?贴程序看下吧,这么说看不出什么原因

使用特权

评论回复
5
chenjunt|  楼主 | 2020-9-10 19:53 | 只看该作者
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;//清除中断标志位
}

使用特权

评论回复
6
happy_10| | 2020-9-10 19:56 | 只看该作者
有个疑问, 你需要采样5路ADC, 这5路ADC是依次触发采样?

使用特权

评论回复
7
tian111| | 2020-9-10 20:00 | 只看该作者
为啥不用MCC生成代码?

使用特权

评论回复
8
chenjunt|  楼主 | 2020-9-10 20:04 | 只看该作者
恩,需要五路ADC,分别控制4路温度,和一路保护。

使用特权

评论回复
9
chenjunt|  楼主 | 2020-9-10 20:08 | 只看该作者
控制周期是50mS,会再一个10mS定时器中断中,触发ADC采样,保证控制周期都是一定的。

使用特权

评论回复
10
chenjunt|  楼主 | 2020-9-10 20:11 | 只看该作者
MCC还没适应,所以还是自己再配置寄存器。

使用特权

评论回复
11
pangb| | 2020-9-10 20:18 | 只看该作者
单独建立一个工程试试

使用特权

评论回复
12
lium| | 2020-9-10 20:22 | 只看该作者
用比较软件, 看一下是哪里不一样吧...

使用特权

评论回复
13
chenjunt|  楼主 | 2020-9-10 20:25 | 只看该作者
不一样的太多了, 感觉配置那里,自己没用的就不会管, 用MCC 的话,会生成很多,没有的也会进行配置。   

使用特权

评论回复
14
happy_10| | 2020-9-10 20:27 | 只看该作者
MCC生成的话,会把所有寄存器配置一遍,防止其他寄存器干扰到配置的工况

使用特权

评论回复
15
tian111| | 2020-9-10 20:31 | 只看该作者
慢慢适应新工具啊,自己手工配置容易遗漏。

使用特权

评论回复
16
chenjunt|  楼主 | 2020-9-10 20:38 | 只看该作者
嗯嗯,目前正在熟悉

使用特权

评论回复
17
renyaq| | 2020-9-10 20:41 | 只看该作者
没有关闭或者清理中断标识?

使用特权

评论回复
18
chenjunt|  楼主 | 2020-9-10 20:44 | 只看该作者

嗯,我再好好缕一缕吧,有了好消息及时通知大家

使用特权

评论回复
19
zjgchenzhen| | 2020-9-11 09:15 | 只看该作者
采样时间算了吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

718

主题

7868

帖子

5

粉丝