打印
[AVR单片机]

AVR单片机之ATXMEGA系列的ADC研究

[复制链接]
1233|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Liuweixing|  楼主 | 2023-2-13 11:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  AVR单片机之ATXMEGA系列的ADC研究
本文中的源代码采用CodeVision3.12编辑编译。采用的MCU 型号是Atxmega128A3U。实际使用测试运行正常。
1、关于ADCAADCB的输入引脚问题
输入引脚用于单端和差动输入,内部输入直接内部连接设备。如果设备含有两个ADC,端口A引脚用于ADCAADC0-ADC7,也可用于ADCBADC8-ADC15,端口B的引脚用于ADCBADC0-ADC7,也可用于ADCAADC8-ADC15。所有输入引脚可作为同相输入,输入引脚ADC0-ADC3可作为不带增益时的反相输入,输入引脚ADC4-ADC7可作为带增益时的反相输入。注意:ADCAADCB的输入引脚ADC0-ADC15的定义位置是不同的。当使用差动输入时,ADC必须设置位signed模式(有符号模式)。
难怪ADCB没有结果。原来不能用。
Table 33-1. Port A - alternate functions.
PORTA  
PIN #
INTERRUPT
ADCAPOS/GAINPOS
ADCB POS
ADCA
NEG
ADCA
GAINNEG
ACA
POS
ACA
NEG
ACA
OUT
DACA
  REFA
GND
93
AVCC
94
PA0
95
SYNC
ADC0
ADC8
ADC0
AC0
AC0
AREF
PA1
96
SYNC
ADC1
ADC9
ADC1
AC1
AC1
PA2
97
SYNC/ASYNC
ADC2
ADC10
ADC2
AC2
DAC0
PA3
98
SYNC
ADC3
ADC11
ADC3
AC3
AC3
DAC1
PA4
99
SYNC
ADC4
ADC12
ADC4
AC4
PA5
100
SYNC
ADC5
ADC13
ADC5
AC5
AC5
PA6
1
SYNC
ADC6
ADC14
ADC6
AC6
AC1OUT
PA7
2
SYNC
ADC7
ADC15
ADC7
AC7
AC0OUT
Table 33-2. Port B - alternate functions.
PORTB
PIN#
INTERRUPT
ADCAPOS
ADCBPOS/
GAINPOS
ADCB
NEG
ADCB
GAIN
NEG
ACB
POS
ACB
NEG
ACB
OUT
REFB
JTAG
GND
3
AVCC
4
PB0
5
SYNC
ADC8
ADC0
ADC0
AC0
AC0
AREF
PB1
6
SYNC
ADC9
ADC1
ADC1
AC1
AC1
PB2
7
SYNC/ASYNC
ADC10
ADC2
ADC2
AC2
DAC0
PB3
8
SYNC
ADC11
ADC3
ADC3
AC3
AC3
DAC1
PB4
9
SYNC
ADC12
ADC4
ADC4
AC4
TMS
PB5
10
SYNC
ADC13
ADC5
ADC5
AC5
AC5
TDI
PB6
11
SYNC
ADC14
ADC6
ADC6
AC6
AC1OUT
TCK
PB7
12
SYNC
ADC15
ADC7
ADC7
AC7
AC0OUT
TDO
2、ADC转换的触发方式方法
ADC转换如果采用自由运行模式free-running, 通道sweep,并且每个通道转换完成产生中断,在中断处理程序中处理转换结果。那么中断次数会非常多,严重影响程序正常运行。经过分析后,决定采用软件启动ADC转换,启动指令的发出由TCF0定时器溢出中断程序发出,TCF0溢出频率400Hz,每中断一次启动一次一个ADC通道的转换,8次中断完成ADCA四个通道和ADCB四个通道的启动。这个中断程序只负责启动ADC转换。
void tcf0_init(void)
{
unsigned char s;
// Note: The correct PORTF direction for the Compare Channels
// outputs is configured in the ports_init function.
// Save interrupts enabled/disabled state
s=SREG;
// Disable interrupts
#asm("cli")
// Disable and reset the timer/counter just to be sure
tc0_disable(&TCF0);
// Clock source: ClkPer/2
TCF0.CTRLA=TC_CLKSEL_DIV2_gc;                 //设置定时器时钟16MHz
// Mode: Normal Operation, Overflow Int./Event on TOP
// Compare/Capture on channel A: Off
// Compare/Capture on channel B: Off
// Compare/Capture on channel C: Off
// Compare/Capture on channel D: Off
TCF0.CTRLB=(0<<TC0_CCDEN_bp) | (0<<TC0_CCCEN_bp) | (0<<TC0_CCBEN_bp) | (0<<TC0_CCAEN_bp) |
        TC_WGMODE_NORMAL_gc;
// Capture event source: None
// Capture event action: None
TCF0.CTRLD=TC_EVACT_OFF_gc | TC_EVSEL_OFF_gc;
// Set Timer/Counter in Normal mode
TCF0.CTRLE=TC_BYTEM_NORMAL_gc;
// Overflow interrupt: Low Level
// Error interrupt: Disabled
TCF0.INTCTRLA=TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_LO_gc;
// Compare/Capture channel A interrupt: Disabled
// Compare/Capture channel B interrupt: Disabled
// Compare/Capture channel C interrupt: Disabled
// Compare/Capture channel D interrupt: Disabled
TCF0.INTCTRLB=TC_CCDINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_OFF_gc;
// High resolution extension: Off
HIRESF.CTRLA&= ~HIRES_HREN0_bm;
// Clear the interrupt flags
TCF0.INTFLAGS=TCF0.INTFLAGS;
// Set Counter register
TCF0.CNT=0x0000;
// Set Period register
TCF0.PER=0x9C3F;   //设置定时器周期2.5ms
// Set channel A Compare/Capture register
TCF0.CCA=0x0000;
// Set channel B Compare/Capture register
TCF0.CCB=0x0000;
// Set channel C Compare/Capture register
TCF0.CCC=0x0000;
// Set channel D Compare/Capture register
TCF0.CCD=0x0000;
// Restore interrupts enabled/disabled state
SREG=s;
}
// Timer/Counter TCF0 Overflow/Underflow interrupt service routine
interrupt [TCF0_OVF_vect] void tcf0_overflow_isr(void)
{
// Write your code here
    static int flag;
    if(flag<7)  flag++; else flag=0;
    switch(flag) {
        case 0: // Start the AD conversion on channel 0
            ADCA.CH0.CTRL|= 1<<ADC_CH_START_bp;  //启动ADCA的通道0
            break;
        case 1:
            ADCA.CH1.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCA的通道1
            break;
        case 2:
            ADCA.CH2.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCA的通道2
            break;
        case 3:
            ADCA.CH3.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCA的通道3
            break;
        case 4:
            ADCB.CH0.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCB的通道0
            break;
        case 5:
            ADCB.CH1.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCB的通道1
            break;
        case 6:
            ADCB.CH2.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCB的通道2
            break;
        case 7:
            ADCB.CH3.CTRL|= 1<<ADC_CH_START_bp;        //启动ADCB的通道3
            break;
        default:
            break;
    }
}
3、ADC转换结果通过DMA方式直接写入内存
DMA由四个独立的通道,这里只用两个通道:通道0和通道1DMA通道0ADCA的通道3转换完成事件触发,DMA通道1ADCB的通道3转换完成触发。DMA的程序如下:
void dma_init(void)
{
    DMA_CTRL =DMA_ENABLE_bm;//使能DMA控制系统 0x80;     //ENABLE |RESET |    –  |   -  |DBUFMODE[1:0] | PRIMODE[1:0]
    DMA_CTRL |=DMA_DBUFMODE_DISABLED_gc|DMA_PRIMODE_RR0123_gc;//禁用双缓冲,Round Robin 循环轮询模式
    DMA_CH0_ADDRCTRL=DMA_CH_SRCRELOAD_BURST_gc|DMA_CH_SRCDIR_INC_gc|DMA_CH_DESTRELOAD_BLOCK_gc|DMA_CH_DESTDIR_INC_gc;//0x95;//源地址每次Burst transfer之后加一重载,目的地址每次Block transfer之后加一重载
    DMA_CH0_TRIGSRC=0x13;   //0x10 ADCA ADCA DMA triggers base value    +0x00 CH0 ADC/DAC channel 0
                            //                            +0x01 CH1 ADC/DAC channel 1
                            //                            +0x02 CH2(1) ADC channel 2
                            //                            +0x03 CH3 ADC channel 3
                            //                            +0x04 CH4(2) ADC channel 0, 1, 2, 3
    DMA_CH0_TRFCNT=320;       //int adca_result[40][4]; 320个字节
    DMA_CH0_REPCNT=0x00;
    DMA_CH0_SRCADDR0=0x10;     //#define ADCA_CH0_RES  _SFR_MEM16(0x0224)
                                //    #define ADCA_CH0RES  _SFR_MEM16(0x0210)
                                //    #define ADCA_CH1RES  _SFR_MEM16(0x0212)
                                //    #define ADCA_CH2RES  _SFR_MEM16(0x0214)
                                //    #define ADCA_CH3RES  _SFR_MEM16(0x0216)
    DMA_CH0_SRCADDR1=0x02;
    DMA_CH0_SRCADDR2=0x00;
    DMA_CH0_DESTADDR0=((unsigned int)adca_result)&0xff;
    DMA_CH0_DESTADDR1=((unsigned int)adca_result>>8)&0xff;
    DMA_CH0_DESTADDR2=((unsigned char)adca_result>>16)&0xff;
    DMA_CH0_CTRLA =DMA_CH_ENABLE_bm|DMA_CH_REPEAT_bm|DMA_CH_SINGLE_bm|DMA_CH_BURSTLEN_8BYTE_gc;
            //    REPEAT| SINGLE| REPCNT| Trigger   | Flag set after |Channel disabled after
            //        0 |    0  |    0  |  Block    |   1block       |  1 block
            //        0 |    0  |    1  | Block     |   1 block      | 1 block
            //        0 |    0  | n > 1 | Block     |   1 block      | 1 block
            //        0 |    1  | 0     |BURSTLEN   |   1 block      | 1 block
            //        0 |    1  | 1     |BURSTLEN   |   1 block      | 1 block
            //        0 |    1  | n > 1 |BURSTLEN   |   1 block      | 1 block
            //        1 |    0  | 0     | Block     |   Each block   | Each block
            //        1 |    0  | 1     |Transaction|   1 block      | 1 block
            //        1 |    0  | n > 1 |Transaction|   n blocks     |n blocks
            //        1 |    1  | 0     |BURSTLEN   |   Each block   |Never ***************
            //        1 |    1  | 1     |BURSTLEN   |   1 block      |1 block
            //        1 |    1  | n > 1 |BURSTLEN   |   n blocks     |n blocks
    //DMA通道1
    DMA_CH1_ADDRCTRL=DMA_CH_SRCRELOAD_BURST_gc|DMA_CH_SRCDIR_INC_gc|DMA_CH_DESTRELOAD_BLOCK_gc|DMA_CH_DESTDIR_INC_gc;//0x95;//源地址每次Burst transfer之后加一重载,目的地址每次Block transfer之后加一重载
    DMA_CH1_TRIGSRC=0x23;   //0x20 ADCB ADCB  DMA triggers base value    +0x00 CH0 ADC/DAC channel 0
                            //                            +0x01 CH1 ADC/DAC channel 1
                            //                            +0x02 CH2(1) ADC channel 2
                            //                            +0x03 CH3 ADC channel 3
                            //                            +0x04 CH4(2) ADC channel 0, 1, 2, 3
    DMA_CH1_TRFCNT=320;       //int adcb_result[40][4]; 320个字节
    DMA_CH1_REPCNT=0x00;
    DMA_CH1_SRCADDR0=0x50;     //#define ADCB_CH0_RES  _SFR_MEM16(0x0264)
                                //    #define ADCB_CH0RES  _SFR_MEM16(0x0250)
                                //    #define ADCB_CH1RES  _SFR_MEM16(0x0252)
                                //    #define ADCB_CH2RES  _SFR_MEM16(0x0254)
                                //    #define ADCB_CH3RES  _SFR_MEM16(0x0256)
    DMA_CH1_SRCADDR1=0x02;
    DMA_CH1_SRCADDR2=0x00;
    DMA_CH1_DESTADDR0=((unsigned int)adcb_result)&0xff;
    DMA_CH1_DESTADDR1=((unsigned int)adcb_result>>8)&0xff;
    DMA_CH1_DESTADDR2=((unsigned char)adcb_result>>16)&0xff;
    DMA_CH1_CTRLA =DMA_CH_ENABLE_bm|DMA_CH_REPEAT_bm|DMA_CH_SINGLE_bm|DMA_CH_BURSTLEN_8BYTE_gc;
    //通道2
    //通道3
//    DMA_CH2_ADDRCTRL=DMA_CH_SRCRELOAD_BURST_gc|DMA_CH_SRCDIR_INC_gc|DMA_CH_DESTRELOAD_BLOCK_gc|DMA_CH_DESTDIR_INC_gc;
//0x95;//源地址每次Burst transfer之后加一重载,目的地址每次Block transfer之后加一重载
}
4、主程序中的处理
//**********************ADCA预处理***********************
             for(i=0;i<4;i++){
                adc_value_sum=0;
                for(j=0;j<40;j++)
                adc_value_sum +=adca_result[j];               
adc_value=adc_value_sum/40-adca_offset;//零点修正
                adc_value *= COEFFICENT;
             }
              //**********************ADCB预处理***********************
             for(i=4;i<8;i++){
                adc_value_sum=0;
                for(j=0;j<40;j++)
                adc_value_sum +=adcb_result[j][i-4];   
                adc_value=adc_value_sum/40-adcb_offset;//零点修正
                adc_value *= COEFFICENT;
             }
5、ADCAADCB的初始化程序
//以上是老的ADCA初始化,下面要改成新的
#pragma optsize_default
// Variable used to store the ADC offset
// for 12 Bit Signed conversion mode
signed char adca_offset;
// ADCA initialization
void adca_init(void)
{
unsigned char i;
int offs;
// ADCA is enabled
// Resolution: 12 Bits
// Load the calibration value for 12 Bit resolution
// from the signature row
ADCA.CALL=read_calibration_byte(PROD_SIGNATURES_START+ADCACAL0_offset);
ADCA.CALH=read_calibration_byte(PROD_SIGNATURES_START+ADCACAL1_offset);
// Gain stage impedance mode: High-impedance sources
// Current consumption: No limit
//// Conversion mode: Unsigned
//ADCA.CTRLB=(0<<ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc | (0<<ADC_CONMODE_bp) | ADC_RESOLUTION_12BIT_gc;
// Conversion mode: signed
ADCA.CTRLB=(0<<ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc | (1<<ADC_CONMODE_bp) | ADC_RESOLUTION_12BIT_gc;
// Clock frequency: 62.500 kHz
//ADCA.PRESCALER=ADC_PRESCALER_DIV512_gc;
// Clock frequency: 125.000 kHz
ADCA.PRESCALER=ADC_PRESCALER_DIV256_gc;
// Reference: Internal Vcc/1.6    ,用这个不准确
// Temperature reference: Off
ADCA.REFCTRL=ADC_REFSEL_VCC_gc | (0<<ADC_TEMPREF_bp) | (0<<ADC_BANDGAP_bp);
//参考电压选择内部1V精确电压源,使能带隙电压
//ADCA.REFCTRL=ADC_REFSEL_INT1V_gc | (0<<ADC_TEMPREF_bp) | (1<<ADC_BANDGAP_bp);
// Read and save the ADC offset using channel 0
ADCA.CH0.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
ADCA.CH0.MUXCTRL=ADC_CH_MUXPOS_PIN0_gc | ADC_CH_MUXNEG_PIN0_gc;
// Enable the ADC in order to read the offset
ADCA.CTRLA|=ADC_ENABLE_bm;//|ADC_DMASEL_gm;  //ADCA四个通道都DMA 请求
// Insert a delay to allow the ADC common mode voltage to stabilize
delay_us(2);
// Perform several offset measurements and store the mean value
offs=0;
for (i=0; i<16; i++)
    {
    // Start the AD conversion on channel 0
    ADCA.CH0.CTRL|= 1<<ADC_CH_START_bp;
    // Wait for the AD conversion to complete
    while ((ADCA.CH0.INTFLAGS & ADC_CH_CHIF_bm)==0);
    // Clear the interrupt flag
    ADCA.CH0.INTFLAGS=ADC_CH_CHIF_bm;
    // Read the offset
    offs+=(signed char) ADCA.CH0.RESL;
    }
// Disable the ADC
ADCA.CTRLA&= ~ADC_ENABLE_bm;
// Store the mean value of the offset
adca_offset=(signed char) (offs/16);
//求出零点偏移量,后面实际ADC结果要减去这个量
// Initialize the ADC Compare register
ADCA.CMPL=0x00;
ADCA.CMPH=0x00;
// ADC channel 0 gain: 1
// ADC channel 0 input mode: Differential input signal
//ADCA.CH0.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_SINGLEENDED_gc;
//差分输入,不带增益,输入2V,参考电压3.3/1.6V
ADCA.CH0.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 0 positive input: ADC0 pin
// ADC channel 0 negative input: intGND
ADCA.CH0.MUXCTRL=ADC_CH_MUXPOS_PIN0_gc|ADC_CH_MUXNEGL_GND_gc;  //ADC_CH_MUXNEGH_GND_gc
// ADC channel 1 gain: 1
// ADC channel 1 input mode: Differential input signal
ADCA.CH1.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 1 gain: 1
// ADC channel 1 input mode: Differential input signal
ADCA.CH1.MUXCTRL=ADC_CH_MUXPOS_PIN1_gc|ADC_CH_MUXNEGL_GND_gc;
//
// ADC channel 2 gain: 1
// ADC channel 2 input mode: Differential input signal
ADCA.CH2.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 2 positive input: ADC2 pin
// ADC channel 2 negative input: Internal ground
ADCA.CH2.MUXCTRL=ADC_CH_MUXPOS_PIN2_gc | ADC_CH_MUXNEGL_GND_gc;
// ADC channel 3 gain: 1
// ADC channel 3 input mode: Differential input signal
ADCA.CH3.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 3 positive input: ADC3 pin
// ADC channel 3 negative input: Internal ground
ADCA.CH3.MUXCTRL=ADC_CH_MUXPOS_PIN3_gc | ADC_CH_MUXNEGL_GND_gc;
// Channel 0 interrupt: OFF
// Channel 0 interrupt mode: Conversion Complete
ADCA.CH0.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Channel 1 interrupt: OFF
// Channel 1 interrupt mode: Conversion Complete
ADCA.CH1.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Channel 2 interrupt: OFF
// Channel 2 interrupt mode: Conversion Complete
ADCA.CH2.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Channel 3 interrupt: OFF
// Channel 3 interrupt mode: Conversion Complete
ADCA.CH3.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Free Running mode: On
//ADCA.CTRLB|=ADC_FREERUN_bm;
// Enable the ADC
ADCA.CTRLA|=ADC_ENABLE_bm;//|ADC_DMASEL_gm;
// Insert a delay to allow the ADC common mode voltage to stabilize
delay_us(2);
}
//ADCB的初始化
// Variable used to store the ADC offset
// for 12 Bit Signed conversion mode
signed char adcb_offset;
void adcb_init(void)
{
unsigned char i;
int offs;
// ADCB is enabled
// Resolution: 12 Bits
// Load the calibration value for 12 Bit resolution
// from the signature row
ADCB.CALL=read_calibration_byte(PROD_SIGNATURES_START+ADCBCAL0_offset);
ADCB.CALH=read_calibration_byte(PROD_SIGNATURES_START+ADCBCAL1_offset);
// Free Running mode: Off
// Gain stage impedance mode: Low-impedance sources
// Current consumption: No limit
// Conversion mode: Signed
ADCB.CTRLB=(1<<ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc | (1<<ADC_CONMODE_bp) | ADC_RESOLUTION_12BIT_gc;
// Clock frequency: 125.000 kHz
ADCB.PRESCALER=ADC_PRESCALER_DIV256_gc;
// Reference: Internal Vcc/1.6
// Temperature reference: Off
ADCB.REFCTRL=ADC_REFSEL_VCC_gc | (0<<ADC_TEMPREF_bp) | (0<<ADC_BANDGAP_bp);
// Read and save the ADC offset using channel 0
ADCB.CH0.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
ADCB.CH0.MUXCTRL=ADC_CH_MUXPOS_PIN0_gc | ADC_CH_MUXNEG_PIN0_gc;
// Enable the ADC in order to read the offset
ADCB.CTRLA|=ADC_ENABLE_bm;
// Insert a delay to allow the ADC common mode voltage to stabilize
delay_us(2);
// Perform several offset measurements and store the mean value
offs=0;
for (i=0; i<16; i++)
    {
    // Start the AD conversion on channel 0
    ADCB.CH0.CTRL|= 1<<ADC_CH_START_bp;
    // Wait for the AD conversion to complete
    while ((ADCB.CH0.INTFLAGS & ADC_CH_CHIF_bm)==0);
    // Clear the interrupt flag
    ADCB.CH0.INTFLAGS=ADC_CH_CHIF_bm;
    // Read the offset
    offs+=(signed char) ADCB.CH0.RESL;
    }
// Disable the ADC
ADCB.CTRLA&= ~ADC_ENABLE_bm;
// Store the mean value of the offset
adcb_offset=(signed char) (offs/16);
// Initialize the ADC Compare register
ADCB.CMPL=0x00;
ADCB.CMPH=0x00;
// ADC channel 0 gain: 1
// ADC channel 0 input mode: Differential input signal
ADCB.CH0.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 0 positive input: ADC12 pin
// ADC channel 0 negative input: PAD ground
ADCB.CH0.MUXCTRL=ADC_CH_MUXPOS_PIN12_gc | ADC_CH_MUXNEGL_GND_gc;
// ADC channel 1 gain: 1
// ADC channel 1 input mode: Differential input signal
ADCB.CH1.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 1 positive input: ADC13 pin
// ADC channel 1 negative input: PAD ground
ADCB.CH1.MUXCTRL=ADC_CH_MUXPOS_PIN13_gc | ADC_CH_MUXNEGL_GND_gc;
// ADC channel 2 gain: 1
// ADC channel 2 input mode: Differential input signal
ADCB.CH2.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 2 positive input: ADC14 pin
// ADC channel 2 negative input: PAD ground
ADCB.CH2.MUXCTRL=ADC_CH_MUXPOS_PIN14_gc | ADC_CH_MUXNEGL_GND_gc;
// ADC channel 3 gain: 1
// ADC channel 3 input mode: Differential input signal
ADCB.CH3.CTRL=(0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc;
// ADC channel 3 positive input: ADC15 pin
// ADC channel 3 negative input: PAD ground
ADCB.CH3.MUXCTRL=ADC_CH_MUXPOS_PIN15_gc | ADC_CH_MUXNEGL_GND_gc;
// Event system channel: 7 sweeps ADC channel(s): 0, 1, 2, 3
//ADCB.EVCTRL=ADC_SWEEP_0123_gc | ADC_EVSEL_7_gc | ADC_EVACT_SWEEP_gc;
// Channel 0 interrupt: OFF
// Channel 0 interrupt mode: Conversion Complete
ADCB.CH0.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Channel 1 interrupt: OFF
// Channel 1 interrupt mode: Conversion Complete
ADCB.CH1.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Channel 2 interrupt:OFF
// Channel 2 interrupt mode: Conversion Complete
ADCB.CH2.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Channel 3 interrupt:OFF
// Channel 3 interrupt mode: Conversion Complete
ADCB.CH3.INTCTRL=ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// Enable the ADC
ADCB.CTRLA|=ADC_ENABLE_bm;
// Insert a delay to allow the ADC common mode voltage to stabilize
delay_us(2);
}
6、改为事件驱动ADC转换
由于这个程序中的TCF0定时器溢出中断次数为每秒400次,一次启动8ADC通道,每秒钟每个通道转换50次。TCF0的中断次数400次每秒也严重地占用了CPU资源。拟改为事件驱动ADC转换。这里将ADCAADCB都设置成通道扫描方式,单一事件启动ADC四个通道扫描一遍,扫描次序通道0、通道1、通道2和通道3.
在上述adca_init()中添加:
// Event system channel: 7 sweeps ADC channel(s): 0, 1, 2, 3
ADCA.EVCTRL=ADC_SWEEP_0123_gc | ADC_EVSEL_7_gc | ADC_EVACT_SYNCHSWEEP_gc;
在上述adcb_init()中添加:
// Event system channel: 7 sweeps ADC channel(s): 0, 1, 2, 3
ADCB.EVCTRL=ADC_SWEEP_0123_gc | ADC_EVSEL_7_gc | ADC_EVACT_SYNCHSWEEP_gc;
event_system_init()中添加:
void event_system_init(void)
{
// Event System Channel 0 source: Port D, Pin7
EVSYS.CH0MUX=EVSYS_CHMUX_PORTD_PIN7_gc;
// Event System Channel 1 source: Port F, Pin0
EVSYS.CH1MUX=EVSYS_CHMUX_PORTF_PIN0_gc;
// Event System Channel 2 source: Port F, Pin1
EVSYS.CH2MUX=EVSYS_CHMUX_PORTF_PIN1_gc;
// Event System Channel 3 source: Port F, Pin2
EVSYS.CH3MUX=EVSYS_CHMUX_PORTF_PIN2_gc;
// Event System Channel 4 source: Port F, Pin6
EVSYS.CH4MUX=EVSYS_CHMUX_PORTF_PIN6_gc;
// Event System Channel 4 source: None
EVSYS.CH4MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 5 source: None
EVSYS.CH5MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 6 source: None
EVSYS.CH6MUX=EVSYS_CHMUX_OFF_gc;
// Event System Channel 7 source: TCF0定时器溢出事件
EVSYS.CH7MUX=EVSYS_CHMUX_TCF0_OVF_gc;
// Event System Channel 0 source: Prescaler, divide by 32768
//EVSYS.CH7MUX=EVSYS_CHMUX_PRESCALER_32768_gc;
// Event System Channel 0 Digital Filter Coefficient: 8 Samples
// Quadrature Decoder: Off
EVSYS.CH0CTRL=(EVSYS.CH0CTRL & (~(EVSYS_QDIRM_gm | EVSYS_QDIEN_bm | EVSYS_QDEN_bm | EVSYS_DIGFILT_gm))) |
        EVSYS_DIGFILT_8SAMPLES_gc;
// Event System Channel 1 Digital Filter Coefficient: 1 Sample
EVSYS.CH1CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 2 Digital Filter Coefficient: 1 Sample
// Quadrature Decoder: Off
EVSYS.CH2CTRL=(EVSYS.CH2CTRL & (~(EVSYS_QDIRM_gm | EVSYS_QDIEN_bm | EVSYS_QDEN_bm | EVSYS_DIGFILT_gm))) |
        EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 3 Digital Filter Coefficient: 1 Sample
EVSYS.CH3CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 4 Digital Filter Coefficient: 1 Sample
// Quadrature Decoder: Off
EVSYS.CH4CTRL=(EVSYS.CH4CTRL & (~(EVSYS_QDIRM_gm | EVSYS_QDIEN_bm | EVSYS_QDEN_bm | EVSYS_DIGFILT_gm))) |
        EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 5 Digital Filter Coefficient: 1 Sample
EVSYS.CH5CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 6 Digital Filter Coefficient: 1 Sample
EVSYS.CH6CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel 7 Digital Filter Coefficient: 1 Sample
EVSYS.CH7CTRL=EVSYS_DIGFILT_1SAMPLE_gc;
// Event System Channel output: Disabled
PORTCFG.CLKEVOUT&= ~PORTCFG_EVOUT_gm;
PORTCFG.EVOUTSEL&= ~PORTCFG_EVOUTSEL_gm;
}
tcf0_init()中禁用溢出中断
// Timer/Counter TCF0 initialization
void tcf0_init(void)
{
unsigned char s;
// Note: The correct PORTF direction for the Compare Channels
// outputs is configured in the ports_init function.
// Save interrupts enabled/disabled state
s=SREG;
// Disable interrupts
#asm("cli")
// Disable and reset the timer/counter just to be sure
tc0_disable(&TCF0);
// Clock source: ClkPer/2
TCF0.CTRLA=TC_CLKSEL_DIV2_gc;
// Mode: Normal Operation, Overflow Int./Event on TOP
// Compare/Capture on channel A: Off
// Compare/Capture on channel B: Off
// Compare/Capture on channel C: Off
// Compare/Capture on channel D: Off
TCF0.CTRLB=(0<<TC0_CCDEN_bp) | (0<<TC0_CCCEN_bp) | (0<<TC0_CCBEN_bp) | (0<<TC0_CCAEN_bp) |
        TC_WGMODE_NORMAL_gc;
// Capture event source: None
// Capture event action: None
TCF0.CTRLD=TC_EVACT_OFF_gc | TC_EVSEL_OFF_gc;
// Set Timer/Counter in Normal mode
TCF0.CTRLE=TC_BYTEM_NORMAL_gc;
// Overflow interrupt: Disabled
// Error interrupt: Disabled
TCF0.INTCTRLA=TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_OFF_gc;
// Compare/Capture channel A interrupt: Disabled
// Compare/Capture channel B interrupt: Disabled
// Compare/Capture channel C interrupt: Disabled
// Compare/Capture channel D interrupt: Disabled
TCF0.INTCTRLB=TC_CCDINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_OFF_gc;
// High resolution extension: Off
HIRESF.CTRLA&= ~HIRES_HREN0_bm;
// Clear the interrupt flags
TCF0.INTFLAGS=TCF0.INTFLAGS;
// Set Counter register
TCF0.CNT=0x0000;
// Set Period register
TCF0.PER=0x9C3F;
// Set channel A Compare/Capture register
TCF0.CCA=0x0000;
// Set channel B Compare/Capture register
TCF0.CCB=0x0000;
// Set channel C Compare/Capture register
TCF0.CCC=0x0000;
// Set channel D Compare/Capture register
TCF0.CCD=0x0000;
// Restore interrupts enabled/disabled state
SREG=s;
}
成功实现8个通道ADC转换,不使用中断。

使用特权

评论回复

相关帖子

沙发
zwsam| | 2023-11-1 09:07 | 只看该作者

使用特权

评论回复
板凳
LEDS| | 2023-11-6 10:34 | 只看该作者
单片机中的奢华品牌了。

使用特权

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

本版积分规则

6

主题

61

帖子

0

粉丝