51単片機C言語の遅延関数はどのように定義して使用します

4878 ワード

C言語定義遅延関数は主に無意味な命令の実行によって遅延の目的を達成する.Cプログラムでは異なるタイプの変数を用いて遅延設計を行うことができる.実験的に試験した結果、unsigned charタイプはunsigned intよりも最適化されたコードを有し、使用時にunsigned charを遅延変数として使用すべきである.ある結晶振動が12 MHzの単片機を例にとると、結晶振動が12 MHzである機械周期が1 usである.遅延xmsミリ秒の遅延関数を定義します.
 void delay(unsigned int xms) // xms         
      {
      unsigned int x,y;
      for(x=xms;x>=0;x--)
      for(y=110;y>=0;y--);
      }

1.51単片機C言語遅延関数の使用は以下のように古典的な遅延関数を与える.(1)500 ms遅延サブルーチンは以下の通りである.
void delay500ms(void)
{
  unsigned char i,j,k;
  for(i=15;i>=0;i--)
  for(j=202;j>=0;j--)
  for(k=81;k>=0;k--);
}

計算分析:プログラムは3層の循環を共有し、1層の循環n:R 52=812=162 us DJNZ 2 us;二層サイクルm:R 6*(n+3)=202165=33330 us DJNZ 2 us+R 5賦値1 us=3 us;3層サイクル:R 7(m+3)=15333333=499995 us DJNZ 2 us+R 6賦値1 us=3 usサイクル外:5 usサブプログラム呼び出し2 us+サブプログラム戻り2 us+R 7賦値1 us=5 us遅延総時間=3層サイクル+サイクル外=499995+5=500000 us=500 ms計算式:遅延時間=〔(2 R 5+3)*R 6+3〕*R 7+5(2)200 ms遅延サブプログラム:
void delay200ms(void)
{
  unsigned char i,j,k;
  for(i=5;i》0;i--)
  for(j=132;j》0;j--)
  for(k=150;k》0;k--);
}

(3)10 ms遅延サブルーチン:
void delay10ms(void)
{
  unsigned char i,j,k;
  for(i=5;i》0;i--)
  for(j=4;j》0;j--)
  for(k=248;k》0;k--);
}

(4)1 s遅延サブルーチン:
void delay1s(void)
{
  unsigned char h,i,j,k;
  for(h=5;h》0;h--)
  for(i=4;i》0;i--)
  for(j=116;j》0;j--)
  for(k=214;k》0;k--);
}

単片機C言語の正確な遅延については、ネット上では、遅延値が正確でない値がどれだけあるかを示すことが多く、正確で高い要求に達していないが、本関数は以上の欠点を克服し、遅延値を正確にカウントし、1 usに正確に達することができる.本例で使用するCPUはSTC 12 C 5412シリーズ12倍速の単片機である.パラメータ値を修正すれば他の系例単片機も通用し、適用範囲が広い.3つの遅延関数の説明は、関数呼び出しは2つのレベルに分けられます.1つのレベルは10 US未満の遅延であり、2つのレベルは10 US以上の遅延です.
//10 US未満【1 US級で遅延】
//--------------マイクロ秒級遅延----------
for(i=X;i)X;i-)遅延時間=(3+5*X)/12ヒント(単位us、Xは255より大きくできません)
//======10 USより大きい「21.9955 Ms未満の使用可能な【10 US級遅延関数】=
void Delay10us(uchar Ms)
{
  uchar data i;
  for(;Ms》0;Ms--)
  for(i=26;i》0;i--);
}

i=[(遅延値-1.75)*12/Ms-15]/4遅延したい場合はi=[(60-1.75)*12/6-15]/4=25.375≒26;iの値=26を修正し、上の【10 US級遅延関数】Delay 10 us(6)を呼び出すと正確に60 US遅延する;遅延したい場合は64 USの2つの関数を組み合わせて使用することができる:Delay 10 us(6);for(i=9;i)X;i-)共遅延64 US単片機C言語の正確な遅延については、ネット上では、遅延値が正確でない値がいくらであるか、正確で高い要求に達していないことが多いが、本関数は以上の欠点を克服し、遅延値を正確にカウントし、正確に1 usに達することができる.本例で使用するCPUはSTC 12 C 5412シリーズ12倍速の単片機である.パラメータ値を修正すれば他の系例単片機も通用し、適用範囲が広い.
3つの遅延関数について、次のように説明します.
関数呼び出しは2つのレベルに分けられます.1つのレベルは10 US未満の遅延であり、2つのレベルは10 US以上の遅延です.
//10 US未満【1 US級で遅延】
//--------------マイクロ秒級遅延----------
for(i=X;i)X;i-)遅延時間=(3+5*X)/12ヒント(単位us、Xは255より大きくできません)
//======10 USより大きい「21.9955 Ms未満の使用可能な【10 US級遅延関数】=
void Delay10us(uchar Ms)
{
  uchar data i;
  for(;Ms》0;Ms--)
  for(i=26;i》0;i--);
}

i=[(遅延値-1.75)*12/Ms-15]/4遅延したい場合はi=[(60-1.75)*12/6-15]/4=25.375≒26;iの値=26を修正し、上の【10 US級遅延関数】Delay 10 us(6)を呼び出します.正確に60 US遅延します.64 USを遅延したい場合は、この2つの関数配列を組み合わせて使用できます.Delay 10 us(6);for(i=9;i)X;i-)共遅延64 US 2.以下、C 51における遅延サブルーチンの設計において注意すべき問題を示す(いくつかの経験談)
(1)、C 51において正確な遅延サブプログラム設計を行う場合、できるだけ遅延サブプログラムに局所変数を定義しないか少なくし、すべての遅延サブプログラムにおける変数はパラメトリック関数によって伝達される.(2)、遅延サブプログラム設計時にdo...whileを採用し、構造的に循環体を作るのはfor構造より循環体を作るほうがよい.(3)、遅延サブプログラム設計時に、ループ体ネストを行う場合は、先内サイクルを採用し、先減よりも減減減し、内サイクルを行うのがよい.
一.500 ms遅延サブルーチンによって生成されたアセンブリ:
C:0x0800 7F0F MOV R7,#0x0F

  C:0x0802 7ECA MOV R6,#0xCA

  C:0x0804 7D51 MOV R5,#0x51

  C:0x0806 DDFE DJNZ R5,C:0806

  C:0x0808 DEFA DJNZ R6,C:0804

  C:0x080A DFF6 DJNZ R7,C:0802

  C:0x080C 22 RET

2.200 ms遅延サブルーチンによるアセンブリ
C:0x0800 7F05 MOV R7,#0x05

  C:0x0802 7E84 MOV R6,#0x84

  C:0x0804 7D96 MOV R5,#0x96

  C:0x0806 DDFE DJNZ R5,C:0806

  C:0x0808 DEFA DJNZ R6,C:0804

  C:0x080A DFF6 DJNZ R7,C:0802

  C:0x080C 22 RET

3.10 ms遅延サブルーチンによって生成されたアセンブリ:
C:0x0800 7F05 MOV R7,#0x05

  C:0x0802 7E04 MOV R6,#0x04

  C:0x0804 7DF8 MOV R5,#0xF8

  C:0x0806 DDFE DJNZ R5,C:0806

  C:0x0808 DEFA DJNZ R6,C:0804

  C:0x080A DFF6 DJNZ R7,C:0802

  C:0x080C 22 RET

四.1 s遅延サブルーチンによるアセンブリ
C:0x0800 7F05 MOV R7,#0x05

  C:0x0802 7E04 MOV R6,#0x04

  C:0x0804 7D74 MOV R5,#0x74

  C:0x0806 7CD6 MOV R4,#0xD6

  C:0x0808 DCFE DJNZ R4,C:0808

  C:0x080A DDFA DJNZ R5,C:0806

  C:0x080C DEF6 DJNZ R6,C:0804

  C:0x080E DFF2 DJNZ R7,C:0802

  C:0x0810 22 RET

3.遅延に関する他の例http://www.ceet.hbnu.edu.cn/bbs/viewthread.php?TId=3749、作者:秋ちゃん
水晶振動:12 MHz
1:5~500us
void delay(unsigned char i)
{
  while(--i) ;
}

計算方法:ix 2+5で5~515 usの遅延が完了
2:10us~2ms
void delay(unsigned char i)
{
  for( ;i》0 ;i--) ;
}

計算方法:ix 8+10で10 us~2.05msの遅延が完了
3:2ms~130ms
void delay(unsigned char i,unsigned char j)
{
  for( ;j》0 ;j--)
  for( ;i》0 ;i--) ;
}

計算方法:(ix 2+3)xj+5 u
転載先:http://www.elecfans.com/emb/580729_a.html