打印
[PIC®/AVR®/dsPIC®产品]

dsPIC33FJ128MC506的ADC中断问题

[复制链接]
1643|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tylene|  楼主 | 2016-7-12 15:54 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
看书上的程序,一直没有看到有ADC的中断,在AD采样程序中,有对DMA0的中断使能,但是没有对ADC的中断使能。
1、对于AD1CON2的SMPI
                                                                                       
这里的中断是什么含义呢?(个人理解,对于有DMA的单片机,是不是只有地址的递增速率这一概念而没有中断了呢?不知道这样对不对)。
2、在DMA0的中断程序执行中(应该是由HALF确定,当数据传输一半或者传输完成产生中断),ADC是否还在采样?程序上只见到ADC的使能置为1,没有看到手动程序关闭ADC,那么是不是就是ADC一直在采样?在DMA0中断程序的时候也执行?还是说DMA0中断的优先级更高,这个时候不响应ADC?
3、AD1CON1的SSRC位,设置为由定时器3比较结束采样并启动转换,这个算是中断吗?相当于定时器的中断?

不知道我能否清楚表达自己的问题,本人小白,刚开始学习PIC单片机,希望大家帮帮忙~~这里附上手册上的采样示例(不同时扫描采样)。

#if defined(__dsPIC33F__)
#include "p33fxxxx.h"
#elif defined(__PIC24H__)
#include "p24hxxxx.h"
#endif
void ProcessADCSamples(unsigned int * AdcBuffer);
/*==========================================================================================
ADC Initialization for Channel Scan
===========================================================================================*/
void initAdc1(void)
{
AD1CON1bits.FORM = 3; // Data Output Format:Signed Fraction (Q15 format)
AD1CON1bits.SSRC = 2; // Sample Clock Source:GP Timer starts conversion
AD1CON1bits.ASAM = 1; // ADC Sample Control:Sampling begins immediately after conversion
AD1CON1bits.AD12B = 0; // 10-bit ADC operation
AD1CON1bits.SIMSAM = 0; // Samples multiple channels individually in sequence
AD1CON2bits.BUFM = 0;
AD1CON2bits.CSCNA = 1; // Scan Input Selections for CH0+ during Sample A bit
AD1CON2bits.CHPS = 0; // Converts CH0
AD1CON3bits.ADRC = 0; // ADC Clock is derived from Systems Clock
AD1CON3bits.ADCS = 63; // ADC Conversion Clock
//AD1CHS0:A/D Input Select Register
AD1CHS0bits.CH0SA = 0; // MUXA +ve input selection (AIN0) for CH0
AD1CHS0bits.CH0NA = 0; // MUXA -ve input selection (Vref-) for CH0

//AD1CHS123:A/D Input Select Register
AD1CHS123bits.CH123SA = 0; // MUXA +ve input selection (AIN0) for CH1
AD1CHS123bits.CH123NA = 0; // MUXA -ve input selection (Vref-) for CH1
//AD1CSSH/AD1CSSL:A/D Input Scan Selection Register
AD1CSSH = 0x0000;
AD1CSSL = 0x000F; // Scan AIN0, AIN1, AIN2, AIN3 inputs
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode
AD1CON2bits.SMPI = 3; // 4 ADC buffers
AD1CON4bits.DMABL = 3; // Each buffer contains 8 words
IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
AD1CON1bits.ADON = 1; // Turn on the A/D converter
}
/*======================================================================================
Timer 3 is setup to time-out every 125 microseconds (8Khz Rate).As a result, the module
will stop sampling and trigger a conversion on every Timer3 time-out, i.e., Ts=125us.
=======================================================================================*/
void initTmr3()
{
TMR3 = 0x0000;
PR3 = 4999; // Trigger ADC1 every 125usec
IFS0bits.T3IF = 0; // Clear Timer 3 interrupt
IEC0bits.T3IE = 0; // Disable Timer 3 interrupt
T3CONbits.TON = 1; //Start Timer 3
}
// Linker will allocate these buffers from the bottom of DMA RAM.
struct
{
unsigned int Adc1Ch0[8];
unsigned int Adc1Ch1[8];
unsigned int Adc1Ch2[8];
unsigned int Adc1Ch3[8];
} BufferA __attribute__((space(dma)));
struct
{
unsigned int Adc1Ch0[8];
unsigned int Adc1Ch1[8];
unsigned int Adc1Ch2[8];
unsigned int Adc1Ch3[8];
} BufferB __attribute__((space(dma)));;

// DMA0 configuration
// Direction:Read from peripheral address 0-x300 (ADC1BUF0) and write to DMA RAM
// AMODE:Peripheral Indirect Addressing Mode
// MODE:Continuous, Ping-Pong Mode
// IRQ:ADC Interrupt

void initDma0(void)
{
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
DMA0PAD = 0x0300; // Point DMA to ADC1BUF0
DMA0CNT = 31; // 32 DMA request (4 buffers, each with 8 words)
DMA0REQ = 13; // Select ADC1 as DMA Request source
DMA0STA = __builtin_dmaoffset(&BufferA);
DMA0STB = __builtin_dmaoffset(&BufferB);
IFS0bits.DMA0IF = 0; //Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; //Set the DMA interrupt enable bit
DMA0CONbits.CHEN=1; // Enable DMA
}
/*========================================================================================
_DMA0Interrupt():ISR name is chosen from the device linker script.
========================================================================================*/
unsigned int DmaBuffer = 0;
void __attribute__((__interrupt__)) _DMA0Interrupt(void)
{
if(DmaBuffer == 0)
{
ProcessADCSamples(BufferA.Adc1Ch0);
ProcessADCSamples(BufferA.Adc1Ch1);
ProcessADCSamples(BufferA.Adc1Ch2);
ProcessADCSamples(BufferA.Adc1Ch3);
}
else
{
ProcessADCSamples(BufferB.Adc1Ch0);
ProcessADCSamples(BufferB.Adc1Ch1);
ProcessADCSamples(BufferB.Adc1Ch2);
ProcessADCSamples(BufferB.Adc1Ch3);
}
DmaBuffer ^= 1;
IFS0bits.DMA0IF = 0; //Clear the DMA0 Interrupt Flag
}
void ProcessADCSamples(unsigned int * AdcBuffer)
{
/* Do something with ADC Samples */
}
沙发
JY-DX-JY| | 2016-7-12 18:03 | 只看该作者
1.肯定有中断
2.应该还在采样。
3.不是中断。

使用特权

评论回复
板凳
tylene|  楼主 | 2016-7-13 08:31 | 只看该作者
JY-DX-JY 发表于 2016-7-12 18:03
1.肯定有中断
2.应该还在采样。
3.不是中断。

额……回答的有些简略了,我还是不大懂。我现在的想法是,用定时器,设计一段时间内就是采样,然后另一端时间用来处理数据,并传输。相隔固定时间执行这一过程,不知道这样能实现吗?

使用特权

评论回复
地板
JY-DX-JY| | 2016-7-13 08:33 | 只看该作者
可以实现

使用特权

评论回复
5
tylene|  楼主 | 2016-7-13 09:03 | 只看该作者

还想问一下:void __attribute__((__interrupt__)) _DMA0Interrupt(void)这个DMA0的中断,是执行到哪里的时候会跳到这个中断啊?

使用特权

评论回复
6
JY-DX-JY| | 2016-7-13 09:50 | 只看该作者
中断函数结束的时候

使用特权

评论回复
7
tylene|  楼主 | 2016-7-13 14:53 | 只看该作者
JY-DX-JY 发表于 2016-7-13 09:50
中断函数结束的时候

中断函数结束的时候?我不太理解,感觉不对啊

使用特权

评论回复
8
JY-DX-JY| | 2016-7-13 15:27 | 只看该作者
怎么不对啦

使用特权

评论回复
9
tylene|  楼主 | 2016-7-13 20:31 | 只看该作者

我是问什么时候跳入中断,你说中断函数结束的时候,难道一直在中断程序循环吗?

使用特权

评论回复
10
JY-DX-JY| | 2016-7-13 20:36 | 只看该作者
tylene 发表于 2016-7-13 20:31
我是问什么时候跳入中断,你说中断函数结束的时候,难道一直在中断程序循环吗? ...

不好意思,看错了。看你的配置了。
比如,你把SMPI设成15,采样16次就进入中断了

使用特权

评论回复
11
tylene|  楼主 | 2016-7-14 08:30 | 只看该作者
JY-DX-JY 发表于 2016-7-13 20:36
不好意思,看错了。看你的配置了。
比如,你把SMPI设成15,采样16次就进入中断了
...

好的,谢谢

使用特权

评论回复
12
LexLu| | 2016-7-21 09:03 | 只看该作者
例子很明显,采用DMA通道使用乒乓模式传输ADC采样数据,这时SMPI的作用是选择·DMA RAM缓冲区指针递增的频率,在需要连续A/D采样时,A/D模块中断发生后,通过DMA通道,直接将采样结果从ADCxBUF0直接输出到DMA RAM区中用户自定义的缓冲区,而不需要软件处理,从而降低了软件开销。由此看来,实际上用到的Timer3中断、ADC中断都是和用户无关的,用户只需要关注DMA通道的中断,处理DMA缓冲区里的ADC数值即可。

使用特权

评论回复
13
idqiye| | 2016-11-28 14:34 | 只看该作者
JY-DX-JY 发表于 2016-7-13 20:36
不好意思,看错了。看你的配置了。
比如,你把SMPI设成15,采样16次就进入中断了
...

想问你一下,这个SMPI和adc的中断有关系没有?ADC1Interrupt

使用特权

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

本版积分规则

8

主题

26

帖子

1

粉丝