IAR環境でのAtmega16 CマむクロコントロヌラヌのプログラミングずJTAGデバッグ、パヌト2





はじめに



なぜなら 前の蚘事は興味をそそりたした。そしお、私が玄束したように、この蚘事は7セグメントむンゞケヌタ、統合ADCの䜿甚䟋に぀いお説明したす。マむクロコントロヌラヌATmega16。



理論的偎面



ADCの䟋をよく理解するには、この蚘事を読むこずをお勧めしたす 。 私たちの堎合、すべおの䟋で、サンプリング呚波数は10 Hzになりたす。これは100 msのサンプリング呚期に盞圓したす。 なぜなら Atmega16マむクロコントロヌラヌに組み蟌たれた10ビットADCを䜿甚するため、量子化レベルの数は1024になりたす。これは、ポヌリングされる各デゞタル倀の0〜1023の倀の範囲に察応したす。 すべおの䟋の基準電圧は、倖郚電圧を䜿甚し、5 Vに等しくなりたす。入力の基準電圧より䞊、井戞、および䞋は、それぞれ衚瀺されたせん。 ADCの入力電圧が5 Vの堎合、1023のデゞタル倀、0 Vグランドのデゞタル倀は0になりたす。たずえば、3.5 Vの電圧では、3.5 / 5= 716に等しいデゞタル倀が埗られたす。䟋では、非線圢性、れロバむアスの補正は行いたせん。



枩床を枬定するには、 TMP36アナログセンサヌを䜿甚したす。 これは、出力電圧が摂氏の枩床に正比䟋する䜎電圧の高粟床枩床センサヌです。 ATmega16マむクロコントロヌラに組み蟌たれた10ビットADCを䜿甚しお、この電圧をデゞタル化したす。



プログラミングずデバッグ



最初の䟋は、000〜999の範囲の数字の3文字7セグメントむンゞケヌタぞの出力です。むンゞケヌタは静的であり、「0」によっお制埡されたす。 ぀たり 各セグメントは個別のLEDずしお制埡されおいるず蚀えたす。 3぀の7セグメントむンゞケヌタはそれぞれ、個別のポヌトポヌトA、B、Dに接続されおいたす。 個々のセグメントのピン番号ぞの接続は、ポヌトに関係なく同じです。



最初の䟋のプログラムテキスト
/*  */ #include <ioavr.h> #include <intrinsics.h> #include <ina90.h> /* */ //  #define F_CPU 16000000 //  #define UCHAR unsigned char #define UINT unsigned int //   //0 #define SEG_0 ~(0x3f) //1 #define SEG_1 ~(0x06) //2 #define SEG_2 ~(0x5b) //3 #define SEG_3 ~(0x4F) //4 #define SEG_4 ~(0x66) //5 #define SEG_5 ~(0x6d) //6 #define SEG_6 ~(0x7d) //7 #define SEG_7 ~(0x07) //8 #define SEG_8 ~(0x7F) //9 #define SEG_9 ~(0x6F) //A #define SEG_A ~(0x77) //b #define SEG_b ~(0x7c) //C #define SEG_C ~(0x39) //d #define SEG_d ~(0x5e) //E #define SEG_E ~(0x79) //F #define SEG_F ~(0x71) //   #define SEG_MASK (0x7F) //   // //   #define SEG_1DEC_PORT PORTD //   #define SEG_2DEC_PORT PORTB //   #define SEG_3DEC_PORT PORTA //    #define SEG_1DEC_DDR DDRD //    #define SEG_2DEC_DDR DDRB //    #define SEG_3DEC_DDR DDRA /*  */ //   #define DELAY_US(us) __delay_cycles((F_CPU / 1000000) * (us)); //   #define DELAY_MS(ms) __delay_cycles((F_CPU / 1000) * (ms)); //     #define SEG_PORTS_INIT() ( SEG_3DEC_DDR |= SEG_MASK );\ ( SEG_2DEC_DDR |= SEG_MASK );\ ( SEG_1DEC_DDR |= SEG_MASK ); //     #define SEG_PORTS_CLEAR() ( SEG_3DEC_PORT &=~ SEG_MASK );\ ( SEG_2DEC_PORT &=~ SEG_MASK );\ ( SEG_1DEC_PORT &=~ SEG_MASK ); //       #define SEG_PORTS_OUT(x,y,z) ( SEG_3DEC_PORT |= ( x & SEG_MASK ) );\ ( SEG_2DEC_PORT |= ( y & SEG_MASK ) );\ ( SEG_1DEC_PORT |= ( z & SEG_MASK ) ); /*   */ //   const unsigned char numbers[16] = { SEG_0, //0 SEG_1, //1 SEG_2, //2 SEG_3, //3 SEG_4, //4 SEG_5, //5 SEG_6, //6 SEG_7, //7 SEG_8, //8 SEG_9, //9 SEG_A, //A SEG_b, //b SEG_C, //C SEG_d, //d SEG_E, //E SEG_F //F }; //   UINT i = 0; /* ** Name: Seg_Write() ** Description:      **    ** Parameters: UINT dec3number 0 - 999 ** Returns: none */ void Seg_Write(UINT dec3number) { //     UCHAR dec3 = 0 , dec2 = 0 , dec1 = 0; // 4    //     dec3number = dec3number % 1000; //    dec3 = dec3number / 100; //   dec3number = dec3number % 100; //    dec2 = dec3number / 10; //    dec1 = dec3number % 10; //    //   SEG_PORTS_CLEAR(); //  3-  //    //  SEG_PORTS_OUT( numbers[dec3], //  numbers[dec2], //  numbers[dec1] //  ); }//end func /* ** Name: main() ** Description:   ,    ** Parameters: none ** Returns: none */ //   void main( void ) { //   //    SEG_PORTS_INIT(); //  Seg_Write(888); //    DELAY_MS(3000); //    i=0; //   for(;;) { //   Seg_Write(i); //  i++; //    ? //    if (i == 1000) i=0; //  100  DELAY_MS(100); }//end for }
      
      









数倀を出力するには、〜0x3fの圢匏の16進コヌドが䜿甚されたす。各コヌドは、0〜9の範囲の特定の10進数に察応したす。 このようなコヌドごずに、フォヌムSEG_Xの定矩が䜜成されたす。Xは衚瀺される数字です。 これらの16進コヌドは、配列むンデックスの倀が衚瀺される数字に察応するように、数倀[16]配列に収集されたす。 たずえば、数倀[3]配列の3番目の芁玠をポヌトに曞き蟌むず、数倀3むンゞケヌタヌの出力が提䟛されたす。



マクロ関数SEG_PORTS_INITを䜿甚するず、ポヌトA、B、Dの䜿甚枈み出力を出力甚に構成できたす。 8番目以倖のすべおのポヌトピンが䜿甚されたす。 マクロ関数SEG_PORTS_CLEARは、7セグメントむンゞケヌタヌのポヌトをクリアし、すべおの出力を「0」にリセットしたす。 このマクロ関数は、SEG_PORTS_OUTx、y、zずずもに、マスクず遞蚀を組み合わせお3぀すべおのポヌトに倀を曞き蟌むこずで、倀が高ビットに損傷を䞎えるこずなく安党にポヌトに曞き蟌たれるようにしたす。



䟿宜䞊、3桁の数字の出力にはvoid Seg_WriteUINT dec3number関数が䜿甚されたす。ここで、dec3numberは衚瀺される3桁の数字です。 関数では、敎数/による陀算の操䜜ず、陀算の剰䜙を取埗する操䜜を䜿甚しお、30幎ごずの数倀のそれぞれが遞択されたす。 その埌、各10幎の倀は数字[decX]配列のむンデックスずしお䜿甚されたす。ここで、decXは3幎の1぀であり、SEG_PORTS_OUTx、y、zを䜿甚しお数字の䜍眮に埓っおポヌトに曞き蟌たれたす。



プログラムのメむンルヌプでは、倉数iの倀が順次出力され、倀999を超えるず増分されおれロになりたすifステヌトメントは、この状態を分析するために䜿甚されたす。 倉数iの倀の出力は、100ミリ秒の間隔で発生したす。これは、前の蚘事で既に説明した遅延マクロ関数DELAY_MS100によっお提䟛されたす。



デバッグ䞭に、倉数iのシヌケンシャルな増分、およびこの倉数の倀を16進コヌドがSeg_Write関数を䜿甚しお倉換されるこずを確認できたす。







2番目の䟋は、統合ADCを䜿甚しおいたす。 アナログ信号は7番目のチャネルに接続され、その入力はポヌトAの7番目のピンにそれぞれ接続されたす。



2番目の䟋のプログラムテキスト
 /*  */ #include <ioavr.h> #include <intrinsics.h> #include <ina90.h> /* */ //  #define F_CPU 16000000 //  #define UINT unsigned int /*  */ //   #define DELAY_US(us) __delay_cycles((F_CPU / 1000000) * (us)); //   #define DELAY_MS(ms) __delay_cycles((F_CPU / 1000) * (ms)); /*   */ // -  UINT ADC_Result = 0; /*  */ //   void main( void ) { //   //  // 7-   D   DDRD_DDD7 = 1; // 7-   D   "0" PORTD_PORTD7 = 0; //  // 7-   A   DDRA_DDA7 = 0; //     PORTA_PORTA7 = 0; ADMUX_MUX0 = 1; //  ADMUX_MUX1 = 1; ADMUX_MUX2 = 1; ADCSRA_ADEN = 1; //  ADCSRA_ADPS0 = 1; //   16  / 128 = 125 ADCSRA_ADPS1 = 1; //    50-200 ADCSRA_ADPS2 = 1; //  13   125 13 / 125000 = 104 //   for(;;) { //     _NOP(); // 7-   D  "0"  "1"   "1"  "0" //    PORTD_PORTD7 ^= 1; // - ADCSRA_ADSC = 1; // - ? //  (104 ) while (ADCSRA_ADIF == 0); //     _NOP(); //  - ADC_Result = ADC; // //ADC_Result = ADCL; //   //ADC_Result += (ADCH << 8); //   //  ADCSRA_ADIF=1; //  100  (1/0,1  = 10  -  ) DELAY_MS(100); }//end for }//end main
      
      









この䟋では、メむン関数で、前の蚘事で既に説明したLEDを蚭定した埌、ポヌトDの7番目の出力が入力甚に構成されたす。 このため、DDRD制埡レゞスタのDDD7ビットは「0」にリセットされたす。 その埌、PORTAデヌタレゞスタの「PORTA7」ビットを「0」にリセットするこずにより、このピンのプルアップ抵抗が匷制的に切断されたす。



次に、ADMUX制埡レゞスタのMUXxビットに「1」を曞き蟌むこずにより、7番目のADCチャネルが遞択されたす。







次に、ADCSRA制埡レゞスタのADENビットを蚭定しお、ADCをオンにしたす。



ADCSRA制埡レゞスタポヌトのADPSxビットは「1」に蚭定され、ADCが50〜200 kHzの最適な呚波数範囲で動䜜するこずを保蚌したすデヌタシヌトに蚘茉。 ADPSxビットは、128のプリスケヌラヌ倀を提䟛したす。16MHzのクロック呚波数での特定の呚波数倀は、16 MHz / 128 = 128 kHzです。









必芁な蚭定がすべお完了するず、フラグを䜿甚したAD倉換の呚期的な順次開始ずポヌリングが行われたす。 LEDは、プログラム操䜜むベントを瀺すために䜿甚されたす。



AD倉換は、ADSRA制埡レゞスタのADSCビットをセットするこずにより開始されたす。 結果の準備は、この制埡レゞスタのADIFフラグを蚭定するこずにより決定されたす。 ADCの遞択された呚波数で、1回の倉換は104ÎŒs続きたす。 ADIFフラグを蚭定した埌、AD倉換の結果範囲は0〜1023は、ADCLおよびADCHデヌタレゞスタから読み取るこずができたす。 AD倉換の結果は、ADC_Result倉数に曞き蟌たれたす。 次に、゚ントリ「1」でADIFフラグをクリアする必芁がありたす。 ポヌリング間隔は100ミリ秒で、10 Hzのサンプリングレヌトに盞圓したす。



デバッグ䞭に、ADC蚭定の正確性をテストしたり、AD倉換の結果ずしお埗られた量子の倀を評䟡したりできたす。







3番目の䟋もADC調査ですが、远加のマクロ関数を䜿甚しおいたす。



3番目の䟋のプログラムテキスト
 /*  */ #include <ioavr.h> #include <intrinsics.h> #include <ina90.h> /* */ //  #define F_CPU 16000000 //  #define UINT unsigned int //     //  #define LED_DDR DDRD #define LED_PORT PORTD #define LED_PIN DDD7 //       #define ADC_IN_DDR DDRA #define ADC_IN_PORT PORTA #define ADC_IN_DDR_PIN DDA7 #define ADC_IN_PORT_PIN PORTA7 //     #define ADC0 (0<<MUX2)|(0<<MUX1)|(0<<MUX0) #define ADC1 (0<<MUX2)|(0<<MUX1)|(1<<MUX0) #define ADC2 (0<<MUX2)|(1<<MUX1)|(0<<MUX0) #define ADC3 (0<<MUX2)|(1<<MUX1)|(1<<MUX0) #define ADC4 (1<<MUX2)|(0<<MUX1)|(0<<MUX0) #define ADC5 (1<<MUX2)|(0<<MUX1)|(1<<MUX0) #define ADC6 (1<<MUX2)|(1<<MUX1)|(0<<MUX0) #define ADC7 (1<<MUX2)|(1<<MUX1)|(1<<MUX0) //      #define ADC_F_CPU_DIV_2 (0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_4 (0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_8 (0<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_16 (0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_32 (1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_64 (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_128 (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) /*  */ //   #define LED_INIT() ( LED_DDR |= (1<<LED_PIN) ); //  #define LED_LOW() ( LED_PORT &=~ (1<<LED_PIN) ); //  #define LED_HIGH() ( LED_PORT |= (1<<LED_PIN) ); //  #define LED_TOG() ( LED_PORT ^= (1<<LED_PIN) ); //    #define ADC_IN_INIT() ( ADC_IN_DDR &= ~(0<<ADC_IN_DDR_PIN) );\ ( ADC_IN_PORT |= (0<<ADC_IN_PORT_PIN) ); //   #define ADC_SET_CHAN(x) ( ADMUX |= x ); //   #define ADC_ON() ( ADCSRA |= (1<<ADEN) ); //   #define ADC_OFF() ( ADCSRA &=~ (1<<ADEN) ); //     #define ADC_SET_CLK_DIV(x) ( ADCSRA |= x ); // - #define ADC_START_CONV() ( ADCSRA |= (1<<ADSC) ); //   - #define ADC_RES_READY() ( ADCSRA & (1<<ADIF) ) //    - #define ADC_FLAG_CLEAR() ( ADCSRA |= (1<<ADIF) ); //   #define DELAY_US(us) __delay_cycles((F_CPU / 1000000) * (us)); //   #define DELAY_MS(ms) __delay_cycles((F_CPU / 1000) * (ms)); /*   */ // -  UINT ADC_Result = 0; /*  */ //   void main( void ) { //   //  LED_INIT(); //  LED_LOW(); //  //   ADC_IN_INIT(); //   ADC_SET_CHAN(ADC7); ADC_ON(); //  //   16  / 128 = 125 ADC_SET_CLK_DIV(ADC_F_CPU_DIV_128); //    50-200 //  13   125 13 / 125000 = 104  //   for(;;) { //     _NOP(); //  LED_TOG(); // - ADC_START_CONV(); // - ? //  (104 ) while(!ADC_RES_READY()); //     _NOP(); //  - ADC_Result = ADC; // //ADC_Result = ADCL; //   //ADC_Result += (ADCH << 8); //   //  ADC_FLAG_CLEAR(); //  100  (1/0,1  = 10  -  ) DELAY_MS(100); }//end for }//end main
      
      









ADCの7番目のチャンネルの入力は、マクロ関数ADC_IN_INITを䜿甚しお初期化されたす。 ADC_IN_DDR、ADC_IN_PORT、ADC_IN_DDR_PIN、ADC_IN_PORT_PINの定矩は、出力ず、それに応じおADCチャンネルを簡単に倉曎できるようにしたす。



ビットは、ADMUXチャネル遞択制埡レゞスタで蚭定され、マクロ関数ADC_SET_CHANADCxを䜿甚しお構成されたす。ADCxの匕数はチャネル番号を決定したす。xは0〜7の範囲で遞択されたす。 各ADCx定矩は、倀「0」および「1」が遞択されたチャネル番号xに察応するMUXx制埡ビットの集合です。



ADCは、ADC_ONマクロ関数によっおオンになりたす。 分呚噚は、マクロ関数ADC_SET_CLK_DIVADC_F_CPU_DIV_xを䜿甚しお遞択されたす。匕数は、ADC_F_CPU_DIV_xの定矩の数から遞択されたす。



AD倉換は、マクロ関数ADC_START_CONVによっお起動されたす。 AD倉換の準備は、マクロ関数ADC_RES_READYによっお決定されたす。 ADC_FLAG_CLEARでフラグをクリアしたす。



4番目の䟋は、割り蟌みメカニズムを䜿甚しおフラグではなく準備完了むベントをキャプチャするADCポヌリングです。



4番目の䟋のプログラムテキスト
 /*  */ #include <ioavr.h> #include <intrinsics.h> #include <ina90.h> /* */ //  #define F_CPU 16000000 //  #define UINT unsigned int /*  */ //   #define DELAY_US(us) __delay_cycles((F_CPU / 1000000) * (us)); //   #define DELAY_MS(ms) __delay_cycles((F_CPU / 1000) * (ms)); /*   */ // -  UINT ADC_Result = 0; /*  */ //   void main( void ) { //   //  // 7-   D   DDRD_DDD7 = 1; // 7-   D   "0" PORTD_PORTD7 = 0; //  // 7-   A   DDRA_DDA7 = 0; //     PORTA_PORTA7 = 1; ADMUX_MUX0 = 1; //  ADMUX_MUX1 = 1; ADMUX_MUX2 = 1; ADCSRA_ADEN = 1; //  ADCSRA_ADPS0 = 1; //   16  / 128 = 125 ADCSRA_ADPS1 = 1; //    50-200 ADCSRA_ADPS2 = 1; //  13   125 13 / 125000 = 104  ADCSRA_ADIE = 1; //    //  _SEI(); //   for(;;) { //     _NOP(); // 7-   D  "0"  "1"   "1"  "0" //    PORTD_PORTD7 ^= 1; // - ADCSRA_ADSC = 1; //  100  (1/0,1  = 10  -  ) DELAY_MS(100); }//end for }//end main /*   -*/ #pragma vector=ADC_vect __interrupt void ISR_ADC(void) { //     _NOP(); //  - ADC_Result = ADC; // //ADC_Result = ADCL; //   //ADC_Result += (ADCH << 8); //   }//end func
      
      









AD倉換の結果の準備ができたずきに割り蟌みを有効にするには、ADCSRA制埡レゞスタのADIEビットを蚭定する必芁がありたす。 その埌、マクロ関数_SEIを䜿甚しお、すべおのマスクされた割り蟌みのグロヌバルな解決を行いたす。







プログラムのロゞックは、メむンルヌプず割り蟌みハンドラヌの準䞊列動䜜を提䟛するスヌパヌサむクルを備えたシステムである最初の蚘事で既に説明されおいたす。 メむンルヌプでは、AD倉換は100ミリ秒の呚期で開始したす。 箄104ÎŒsの間隔の埌、メむンサむクルは、AD倉換結果の準備むベントによっお割り蟌み凊理のために䞭断されたす。 割り蟌み凊理は、このむベントで呌び出されるISR_ADCハンドラヌ関数を䜿甚しお実行されたす。 AD倉換の結果は、ハンドラヌ関数の本䜓のADCLおよびADCHデヌタレゞスタからコピヌされたす。



デバッグ䞭に、ADC呚蟺モゞュヌルの割り蟌みサブシステムの正しい動䜜をテストできたす。







5番目の䟋は、3番目ず4番目の䟋の共生です。 これは、マクロ関数を䜿甚したADC問い合わせです。



5番目の䟋のプログラムテキスト
 /*  */ #include <ioavr.h> #include <intrinsics.h> #include <ina90.h> /* */ //  #define F_CPU 16000000 //  #define UINT unsigned int //     //  #define LED_DDR DDRD #define LED_PORT PORTD #define LED_PIN DDD7 //       #define ADC_IN_DDR DDRA #define ADC_IN_PORT PORTA #define ADC_IN_DDR_PIN DDA7 #define ADC_IN_PORT_PIN PORTA7 //     #define ADC0 (0<<MUX2)|(0<<MUX1)|(0<<MUX0) #define ADC1 (0<<MUX2)|(0<<MUX1)|(1<<MUX0) #define ADC2 (0<<MUX2)|(1<<MUX1)|(0<<MUX0) #define ADC3 (0<<MUX2)|(1<<MUX1)|(1<<MUX0) #define ADC4 (1<<MUX2)|(0<<MUX1)|(0<<MUX0) #define ADC5 (1<<MUX2)|(0<<MUX1)|(1<<MUX0) #define ADC6 (1<<MUX2)|(1<<MUX1)|(0<<MUX0) #define ADC7 (1<<MUX2)|(1<<MUX1)|(1<<MUX0) //      #define ADC_F_CPU_DIV_2 (0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_4 (0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_8 (0<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_16 (0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_32 (1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_64 (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_128 (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) /*  */ //   #define LED_INIT() ( LED_DDR |= (1<<LED_PIN) ); //  #define LED_LOW() ( LED_PORT &=~ (1<<LED_PIN) ); //  #define LED_HIGH() ( LED_PORT |= (1<<LED_PIN) ); //  #define LED_TOG() ( LED_PORT ^= (1<<LED_PIN) ); //    #define ADC_IN_INIT() ( ADC_IN_DDR &= ~(0<<ADC_IN_DDR_PIN) );\ ( ADC_IN_PORT |= (0<<ADC_IN_PORT_PIN) ); //   #define ADC_SET_CHAN(x) ( ADMUX |= x ); //   #define ADC_ON() ( ADCSRA |= (1<<ADEN) ); //   #define ADC_OFF() ( ADCSRA &=~ (1<<ADEN) ); //     #define ADC_SET_CLK_DIV(x) ( ADCSRA |= x ); // - #define ADC_START_CONV() ( ADCSRA |= (1<<ADSC) ); //    #define ADC_INT_ON() ( ADCSRA |= (1<<ADIE) ); //   #define DELAY_US(us) __delay_cycles((F_CPU / 1000000) * (us)); //   #define DELAY_MS(ms) __delay_cycles((F_CPU / 1000) * (ms)); /*   */ // -  UINT ADC_Result = 0; /*  */ //   void main( void ) { //   //  LED_INIT(); //  LED_LOW(); //  //   ADC_IN_INIT(); //   ADC_SET_CHAN(ADC7); ADC_ON(); //  //   16  / 128 = 125 ADC_SET_CLK_DIV(ADC_F_CPU_DIV_128); //    50-200 //  13   125 13 / 125000 = 104  ADC_INT_ON(); //    //  _SEI(); //   for(;;) { //     _NOP(); //  LED_TOG(); // - ADC_START_CONV(); //  100  (1/0,1  = 10  -  ) DELAY_MS(100); }//end for }//end main /*   -*/ #pragma vector=ADC_vect __interrupt void ISR_ADC(void) { //     _NOP(); //  - ADC_Result = ADC; // //ADC_Result = ADCL; //   //ADC_Result += (ADCH << 8); //   }//end func
      
      









マクロ関数ADC_INT_ONは、割り蟌みを有効にするために䜿甚されたす。



必芁なすべおの䟋を怜蚎したので、マむクロコントロヌラヌの内郚呚蟺ナニットを操䜜する既に怜蚎された䟋に基づいお䜜成されたデゞタル枩床蚈のプロゞェクト党䜓に進みたす。



デゞタル枩床蚈プログラムテキスト
 /*  */ #include <ioavr.h> #include <intrinsics.h> #include <ina90.h> #include <stdbool.h> /* */ //  #define F_CPU 16000000 //  #define UCHAR unsigned char #define UINT unsigned int #define FLOAT_TYPE float //     //   #define LED_DDR DDRD #define LED_PORT PORTD #define LED_PIN DDD7 //      #define F_CPU_DIV_1 (0<<CS02)|(0<<CS01)|(1<<CS00) #define F_CPU_DIV_8 (0<<CS02)|(1<<CS01)|(0<<CS00) #define F_CPU_DIV_64 (0<<CS02)|(1<<CS01)|(1<<CS00) #define F_CPU_DIV_256 (1<<CS02)|(0<<CS01)|(0<<CS00) #define F_CPU_DIV_1024 (1<<CS02)|(0<<CS01)|(1<<CS00) //     #define TCNT0_VALUE 99 //     #define T0_TICK_CNT_LIMIT 10 //       #define ADC_IN_DDR DDRA #define ADC_IN_PORT PORTA #define ADC_IN_DDR_PIN DDA7 #define ADC_IN_PORT_PIN PORTA7 //     #define ADC0 (0<<MUX2)|(0<<MUX1)|(0<<MUX0) #define ADC1 (0<<MUX2)|(0<<MUX1)|(1<<MUX0) #define ADC2 (0<<MUX2)|(1<<MUX1)|(0<<MUX0) #define ADC3 (0<<MUX2)|(1<<MUX1)|(1<<MUX0) #define ADC4 (1<<MUX2)|(0<<MUX1)|(0<<MUX0) #define ADC5 (1<<MUX2)|(0<<MUX1)|(1<<MUX0) #define ADC6 (1<<MUX2)|(1<<MUX1)|(0<<MUX0) #define ADC7 (1<<MUX2)|(1<<MUX1)|(1<<MUX0) //      #define ADC_F_CPU_DIV_2 (0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_4 (0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_8 (0<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_16 (0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) #define ADC_F_CPU_DIV_32 (1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_64 (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0) #define ADC_F_CPU_DIV_128 (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) //   //0 #define SEG_0 ~(0x3f) //1 #define SEG_1 ~(0x06) //2 #define SEG_2 ~(0x5b) //3 #define SEG_3 ~(0x4F) //4 #define SEG_4 ~(0x66) //5 #define SEG_5 ~(0x6d) //6 #define SEG_6 ~(0x7d) //7 #define SEG_7 ~(0x07) //8 #define SEG_8 ~(0x7F) //9 #define SEG_9 ~(0x6F) //A #define SEG_A ~(0x77) //b #define SEG_b ~(0x7c) //C #define SEG_C ~(0x39) //d #define SEG_d ~(0x5e) //E #define SEG_E ~(0x79) //F #define SEG_F ~(0x71) // #define SEG_GRAD ~(0x63) //   #define SEG_MASK (0x7F) //   // //   #define SEG_1DEC_PORT PORTD //   #define SEG_2DEC_PORT PORTB //   #define SEG_3DEC_PORT PORTA //    #define SEG_1DEC_DDR DDRD //    #define SEG_2DEC_DDR DDRB //    #define SEG_3DEC_DDR DDRA /*  */ //    #define LED_INIT() ( LED_DDR |= (1<<LED_PIN) ); //   #define LED_LOW() ( LED_PORT &=~ (1<<LED_PIN) ); //   #define LED_HIGH() ( LED_PORT |= (1<<LED_PIN) ); //   #define LED_TOG() ( LED_PORT ^= (1<<LED_PIN) ); //    #define TIMER0_SET_CLK_DIV(x) ( TCCR0 |= x ); //     #define TIMER0_SET_CNT(x) ( TCNT0 = x ); //      #define TIMER0_OVF_INT_ON() ( TIMSK|=(1<<TOIE0) ); //    #define ADC_IN_INIT() ( ADC_IN_DDR &= ~(0<<ADC_IN_DDR_PIN) );\ ( ADC_IN_PORT &= ~(0<<ADC_IN_PORT_PIN) ); //   #define ADC_SET_CHAN(x) ( ADMUX |= x ); //   #define ADC_ON() ( ADCSRA |= (1<<ADEN) ); //   #define ADC_OFF() ( ADCSRA &=~ (1<<ADEN) ); //     #define ADC_SET_CLK_DIV(x) ( ADCSRA |= x ); // - #define ADC_START_CONV() ( ADCSRA |= (1<<ADSC) ); //    #define ADC_INT_ON() ( ADCSRA |= (1<<ADIE) ); //     #define SEG_PORTS_INIT() ( SEG_3DEC_DDR |= SEG_MASK );\ ( SEG_2DEC_DDR |= SEG_MASK );\ ( SEG_1DEC_DDR |= SEG_MASK ); //     #define SEG_PORTS_CLEAR() ( SEG_3DEC_PORT &=~ SEG_MASK );\ ( SEG_2DEC_PORT &=~ SEG_MASK );\ ( SEG_1DEC_PORT &=~ SEG_MASK ); //       #define SEG_PORTS_OUT(x,y,z) ( SEG_3DEC_PORT |= ( x & SEG_MASK ) );\ ( SEG_2DEC_PORT |= ( y & SEG_MASK ) );\ ( SEG_1DEC_PORT |= ( z & SEG_MASK ) ); //   #define DELAY_US(us) __delay_cycles((F_CPU / 1000000) * (us)); //   #define DELAY_MS(ms) __delay_cycles((F_CPU / 1000) * (ms)); /*   */ //     T0 UINT T0_tick_cnt=0; //   const unsigned char numbers[16] = { SEG_0, //0 SEG_1, //1 SEG_2, //2 SEG_3, //3 SEG_4, //4 SEG_5, //5 SEG_6, //6 SEG_7, //7 SEG_8, //8 SEG_9, //9 SEG_A, //A SEG_b, //b SEG_C, //C SEG_d, //d SEG_E, //E SEG_F //F }; //    FLOAT_TYPE T = 0; // -  UINT ADC_Result = 0; //  - - UINT ADC_res_cnt = 0; //   UINT Sum = 0; //   - bool ADCReadyFlag = false; /* ** Name: Seg_Write() ** Description:       **    ** Parameters: UINT T -   0 - 99 C ** Returns: none */ void Seg_Write(UINT T) { //     UINT dec2 = 0 , dec1 = 0; //     T = T % 100; //   dec2 = T / 10; //   dec1 = T % 10; //    //   SEG_PORTS_CLEAR(); //  3-  //    //  SEG_PORTS_OUT( numbers[dec2], //  numbers[dec1], //  SEG_GRAD // ); }//end func /* ** Name: main() ** Description:   ,    ** Parameters: none ** Returns: none */ //   void main( void ) { //   //    SEG_PORTS_INIT(); //  LED_INIT(); //  LED_LOW(); //  ( Normal) TIMER0_SET_CLK_DIV(F_CPU_DIV_1024);//   16 000 000  // 16 000 000  / 1024 = 15 625  // 1 / 15 625  = 0,000064  =64  TIMER0_SET_CNT(TCNT0_VALUE); // 156 * 0,000064 c = 0,009984 c (10 ) //      255-156 = 99 TIMER0_OVF_INT_ON(); //      //  //   ADC_IN_INIT(); //   ADC_SET_CHAN(ADC7); ADC_ON(); //  //   16  / 128 = 125 ADC_SET_CLK_DIV(ADC_F_CPU_DIV_128); //    50-200 //  13   125 13 / 125000 = 104  ADC_INT_ON(); //    //    T=0; //   Sum = 0; //  _SEI(); //   for(;;) { //     _NOP(); // -  //  if(ADCReadyFlag) { //     _NOP(); //  ADCReadyFlag = false; //  LED_TOG(); //  //- Sum += ADC_Result; //  //- ADC_res_cnt++; //  -? if ( ADC_res_cnt == 8 ) { //     _NOP(); //  ADC_res_cnt = 0; //   ADC_Result = Sum / 8; //  Sum = 0; //    T = ADC_Result*(5.0/1023); //    T = ((T-0.75)*100)+25; //    //  Seg_Write((UINT)T); }//end if }//end if }//end for }//end main /*   T0  */ #pragma vector=TIMER0_OVF_vect __interrupt void ISR_TickTimer(void) { //     _NOP(); //    T0 T0_tick_cnt++; //  100  if (T0_tick_cnt >= T0_TICK_CNT_LIMIT) { //     _NOP(); //    T0 T0_tick_cnt=0; //   // - ADC_START_CONV(); }//end for //   //   TIMER0_SET_CNT(TCNT0_VALUE); }//end func /*   -*/ #pragma vector=ADC_vect __interrupt void ISR_ADC(void) { //     _NOP(); //  - ADC_Result = ADC; // //ADC_Result = ADCL; //   //ADC_Result += (ADCH << 8); //   //   - ADCReadyFlag = true; }//end func
      
      









呚蟺レゞスタの蚭定に関しおは、マクロ機胜ですでに説明したLED、ハヌドりェアタむマヌ、ADCの蚭定が䜿甚されたす。



プログラムのロゞックは、メむンルヌプの疑䌌䞊列動䜜ず、ティックハヌドりェアタむマヌおよびADC甚の2぀の割り蟌みハンドラヌに集䞭しおいたす。ティックタむマヌ割り蟌みハンドラヌで、100ミリ秒間隔の経過のむベントが蚘録され、マクロ関数ADC_START_CONVを䜿甚しおAD倉換が開始されたす。玄104ÎŒsの間隔の埌、AD倉換の結果が準備されるず、割り蟌みがトリガヌされたす。 ISR_ADCハンドラヌの本䜓では、AD倉換の結果がADC_Result倉数に蚘録され、bool型のADCReadyFlag準備フラグが蚭定されたすこの型を䜿甚するには、stdbool.hラむブラリが#includeディレクティブで以前に接続されおいたした。



このフラグを蚭定するむベントは、ifステヌトメントによっおメむンルヌプで修正されたす。その埌、フラグがリセットされ、AD倉換の8぀の結果が合蚈されるたで、AD倉換の結果ADC_Resultが倉数Sumに合蚈されたす。 8぀の結果が取埗され、合蚈されるず、Sum倉数の合蚈が8で陀算されたす。したがっお、シンプルなデゞタルフィルタリングオプションが実装され、倖郚フィルタリングスキヌムに加えおノむズの倚いUSB電源により䜎ノむズビットが削枛されたす。



フィルタリングされた結果はADC_Result倉数に曞き蟌たれ、Sum倉数はれロにリセットされたす。次に、量子で埗られたフィルタリング結果は、単玔な算術挔算を䜿甚しおボルトに倉換されたす。なぜなら基準電圧は5 Vで、それに察応する量子の最倧倀は1023です。量子の倀のボルトに倉換するには、それを1023で陀算し、5で乗算するだけで十分です。結果の小数倀を実数型で保存したす。さらに、TMP36に手元にデヌタシヌトがあり、25床では出力が750 mVであり、䞊䞋は10 mVに盞圓するこずがわかっおいるため、次の匏T =T -0.75* 100+25。さらに、床単䜍の枩床倀はvoid Seg_WriteUINT T関数を䜿甚しお7セグメントむンゞケヌタヌに衚瀺されたす。これは、最初の䟋ずは異なり、2桁の数字を床蚘号で衚瀺したす。ディスプレむに衚瀺される数十幎の論理は同じです。



デバッグ䞭に、蚘述されたプログラムのすべおのロゞック、および䞭間倉数の倀ず最終結果の䞡方の蚈算の正確さをトレヌスできたす。







おわりに



IARプロゞェクトの圢匏のすべおの䟋は、ここからダりンロヌドできたす。



All Articles