atmega2560上的ADC代码

时间:2015-03-01 11:26:25

标签: arduino atmega

我编写代码来测量存储在ch1阵列中的通道编号上的ADC值(前2个通道对应于电容器电压Vc的测量;然后接下来的6个通道对应于栅极电流Ia,Ib,Ic的测量;以及后6个通道对应于电网电压Va,Vb,Vc的测量。 我正在为arduino-Mega的Atmega2560编写代码。

代码的整体结构: 1.在功能设置()中,我初始化了ADC,串行监视器和中断 2.在函数循环()中,我为存储在名为ch1的数组中的每个通道启动ADC转换,以依次获得电容器电压,电网电流和电网电压。

我无法获得理想的结果,我的意思是在5-6行之后没有任何东西打印在串行终端上。

#define F_CPU 16000000UL
#include <avr/io.h> 
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <util/atomic.h>


#define ChannelMax 4
uint8_t ch1[]={0,0,1,1,2,2,3,3,4,4,5,5,6,6};//channels for //Vc,Vc,Ia,Ia,Ib,IB,Ic,Ic,Va,Va,Vb,Vb,Vc,Vc(capacitor voltage,grid current,grid voltage)

volatile unsigned short ci=0;//index for ch1 array

unsigned int ADarray[15];//array to store ADC output data
volatile unsigned short readFlag=0;//it is set from ADC ISR when either Vc 
or all I or all V is measured twice     






void setupADC();
uint16_t adc_read(uint8_t ch);
void adc_start(uint8_t ch);
//setup function detail for arduino
void setup()
{
   cli();

   Serial.begin(9600);        // connect to the serial port
   setupADC();

   sei();


}

//looping for infinity
void loop()
{
   while(1) 
   {

    //initialize things
    ci=0;// start with first channel present in ch1
    Serial.print("Vc measuring started with");
    Serial.println(ch1[ci]);
    adc_start(ch1[ci]);//start adc to measure Vc i.e ch1[0] and ch1[1]
    //do something whil Vc is measured

   while(1){ //wait till end of ADC measurement of Vc
     if(readFlag==0){
     Serial.println(readFlag);
     Serial.println("Vc beingmeasured"); 
   }
   else break;

  };
  readFlag=0; Serial.println("Vc finally measured"); 
 //use Vc i.e. ADarray[1] for calculation



 Serial.print("I measuring started with ");Serial.println(ch1[ci]);
 adc_start(ch1[ci]);//start adc to measure grid current Ia,Ib,Ic i.e ch1[2] 
   //to ch1[7]
 //do something while grid current is being measured
 while(1){  //wait for end of measurement of grid current
  if(readFlag==0){
    Serial.println(readFlag);
    Serial.println("I beingmeasured"); 
  }
  else break;
 };
readFlag=0; Serial.println("I finally measured"); 
//Use i i.e. ADarray[3],5,7 for calculation





 Serial.print("V measuring started with ");Serial.println(ch1[ci]);
  adc_start(ch1[ci]);//start measurement of grid voltage Va,Vb and Vc
 //do something while grid volt is being measured
 while(1){//wait till end of measurement of grid voltage
   if(readFlag==0){
    Serial.println(readFlag);
    Serial.println("V beingmeasured"); 
   }
   else break;
 };
 readFlag=0;Serial.println("V finally measured"); 
 //Use V i.e. ADarray[9],11,13 for calculation




  }//end of while loop
}//end of loop function

 //setup registers for ADC in atmega 2560
 void setupADC(){
   ADCSRA = 0;
    ADCSRB = 0;
    ADMUX = ch1[ci];        // Channel 0 only
    ADMUX |= (1<<REFS0);//ADMUX|=0b01000000;//use it if u want to use AVCC       //as Aref internally ,but dont forget to use external cap at AREF

    ADCSRA = _BV(ADEN)  ;  // Enable ADC, 
    //ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) ;//prescale at 128.
    ADCSRA|=_BV(ADIE);//to interupt enable for ADC 
    //ADCSRA |= _BV(ADSC);  // Start initial ADC cycle


}   
//Interrupt service routine for ADC measurment
ISR(ADC_vect){

    ADarray[ci]=(unsigned int)ADC;
    Serial.print(ch1[ci]);Serial.println("adc read");
    ci++;ci++;Serial.print(ci);
    //if(ci>=ChannelMax) ci=0;

    if((ci==2) ||( ci==8) ||(ci==14)){
     Serial.println("finished");
     readFlag=1;
     return ;
    }   
   //Serial.println("adc started");
   adc_start(ch1[ci]);
   //Serial.print(ch1[ci]);Serial.println("adc started");





}



//function to start ADC for particular channel
void adc_start(uint8_t ch){
     // Serial.print(ch);Serial.println("adc started subroutine");
    // select the corresponding channel 0~7
    // ANDing with ’7? will always keep the value
    // of ‘ch’ between 0 and 7
    ch &= 0b00001111;  // AND operation with 7
    ADMUX = (ADMUX & 0xF0)|ch; // clears the bottom 3 bits before ORing

    // start single convertion
    // write ’1? to ADSC
    ADCSRA |= (1<<ADSC);
}

1 个答案:

答案 0 :(得分:0)

做事,我明白One不应该在ISR中使用Serial.print或者从ISR调用的任何函数(也许是因为Serial.print使用中断)......那么问题是如何调试ISR内部?我可以使用Atomic_Block做某事吗?