📄 adc.c
字号:
/***********************************************************************
* *
* This file contains the implementation of adc.h for the dsPIC30F3011 *
* device and the 5DOF test board v3. *
* *
***********************************************************************
* *
* Author: Tom Pycke *
* Filename: adc.c *
* Date: 13/10/2007 *
* File Version: 1.00 *
* Other Files Required: adc.h *
* *
***********************************************************************
* *
* Other Comments: *
* The 5DOF test board v3 is using the following ADC input pins: *
* AN2 till AN7 using AN0 and AN1 as voltage referene. *
* I included the code for 2 low-pass filters: *
* - Average of last 2 samples *
* - Median over 3 samples *
* - Runge-Kutta 4th order *
***********************************************************************/
#include "common.h"
// we're implementing ../adc.h
#include "../adc.h"
// to define the timer 3 counter value
#define SAMPLINGRATE 1800
#define SAMPCOUNT (FCY/SAMPLINGRATE)+1
unsigned int adc_buf[16];
volatile unsigned int* ADC16Ptr = &ADCBUF0; //Pointer to ADC register buffer,
unsigned int adc_filter_buffer[4][6] = { {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0} };
unsigned int current_buf = 1;
void adc_init()
{
adc_stop();
// CONTROL BITS (See p17-34 in "dsPIC30F Family Reference Manual")
// Sequence Select
ADCON2bits.SMPI = 5; // Interrupt on 6th sample
ADCON2bits.CHPS = 0; // Sample channel CH0
ADCON1bits.SIMSAM = 0; // n/a for single channel sample
ADCON2bits.BUFM = 0; // Single 16-word result buffer
ADCON2bits.ALTS = 0; // Always use MUX A input select
// MUX A Input Select
ADCHSbits.CH0SA = 0; // Overridden by CSCNA
ADCHSbits.CH0NA = 0; // Select VREF- for CH0- input
ADCON2bits.CSCNA = 1; // Scan channel 0 inputs
ADCSSL = 0b011111100; // Scan AN2..AN7
ADCHSbits.CH123SA = 0; // n/a
ADCHSbits.CH123NA = 0; // n/a
// MUX B Input Select
ADCHSbits.CH123SA = 0; // n/a
ADCHSbits.CH123NA = 0; // n/a
// SPECIFIC BITS
ADCON1bits.FORM = 0b10; // Use fractional (DOUT = dddd dddd dd00 0000) for future compatibility with 12-bit ADC
ADCON1bits.SSRC = 2; // Use TIMER3 trigger to start convertion
ADCON1bits.ASAM = 1; // Sampling begins immediately after last conversion completes. SAMP bit is auto set
ADCON2bits.VCFG = 0b011; // Use VREF+ and VREF- as reference
ADCON3bits.ADCS = 0b011111; // Timing for 8MHz
ADPCFG = 0xFF00; // AN0..AN7 are analog
TRISB = 0b11111111; // Port B is input
// INITIALIZE TIMER3 (used to trigger ADC)
TMR3 = 0x0000;
PR3 = SAMPCOUNT;
IFS0bits.ADIF = 0; //Clear the A/D interrupt flag bit
IEC0bits.ADIE = 1; //Set the A/D interrupt enable bit
}
void adc_start()
{
//Turn on the A/D converter
//This is typically done after configuring other registers
ADCON1bits.ADON = 1;
//Start Timer 3
T3CONbits.TON = 1;
}
void adc_stop()
{
// Turn off the A/D converter
ADCON1bits.ADON = 0;
// Stop TIMER 3
T3CONbits.TON = 0;
}
/*
* ADC interrupt, called when 6 conversions are done
*
* Implements 4th order Runge-Kutta filter
*/
void __attribute__((__interrupt__)) _ADCInterrupt(void)
{
unsigned int i;
for (i=0; i < 6; i++)
adc_filter_buffer[current_buf][i] = ADC16Ptr[i];
for (i=0; i < 6; i++)
adc_buf[i] = (adc_filter_buffer[current_buf][i]/6 +
adc_filter_buffer[(current_buf+1)%4][i]/6 +
adc_filter_buffer[(current_buf+2)%4][i]/3 +
adc_filter_buffer[(current_buf+3)%4][i]/3);
current_buf = (current_buf+1) % 4;
IFS0bits.ADIF = 0;
}
/* NO FILTERING */
/*void __attribute__((__interrupt__)) _ADCInterrupt(void)
{
unsigned int channel = 0;
unsigned int buffer = 0;
for (buffer=0; buffer < 6; buffer++)
adc_buf[buffer] = ADC16Ptr[buffer];
IFS0bits.ADIF = 0;
}
*/
/* Average over 2 samples */
/*unsigned int adc_buf1[6];
unsigned int adc_buf2[6];
unsigned int adc_buf3[6];
unsigned int adc_buf4[6];*/
/*void __attribute__((__interrupt__)) _ADCInterrupt(void)
{
unsigned int channel = 0;
unsigned int buffer = 0;
if (current_buf == 1)
{
for (buffer=0; buffer < 6; buffer++)
adc_buf1[buffer] = ADC16Ptr[buffer];
current_buf = 2;
}
else
{
for (buffer=0; buffer < 6; buffer++)
adc_buf2[buffer] = ADC16Ptr[buffer];
current_buf = 1;
}
for (buffer=0; buffer < 6; buffer++)
adc_buf[buffer] = (adc_buf1[buffer]/2 + adc_buf2[buffer]/2);
IFS0bits.ADIF = 0;
}
*/
/* Median over 3 samples */
/*unsigned int middle(unsigned int x, unsigned int y, unsigned int z)
{
if (x > y)
{
if (z > x)
return x;
else if (z > y)
return z;
else
return y;
}
else // x < y
{
if (z < x)
return x;
else if (z < y) // & x < z
return z;
else
return y;
}
}
void __attribute__((__interrupt__)) _ADCInterrupt(void)
{
unsigned int channel = 0;
unsigned int buffer = 0;
if (current_buf == 1)
{
for (buffer=0; buffer < 6; buffer++)
adc_buf1[buffer] = ADC16Ptr[buffer];
current_buf = 2;
}
else if (current_buf == 2)
{
for (buffer=0; buffer < 6; buffer++)
adc_buf2[buffer] = ADC16Ptr[buffer];
current_buf = 3;
}
else if (current_buf == 3)
{
for (buffer=0; buffer < 6; buffer++)
adc_buf3[buffer] = ADC16Ptr[buffer];
current_buf = 1;
}
for (buffer=0; buffer < 6; buffer++)
adc_buf[buffer] = middle(adc_buf1[buffer], adc_buf2[buffer], adc_buf3[buffer]);
IFS0bits.ADIF = 0;
}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -