Professional Documents
Culture Documents
هﺮ دﺳﺘﮕﺎﻩ ﺑﺮﻧﺎﻣﻪ ﭘﺬﯾﺮ )ﻣﺎﻧﻨﺪ ﯾﮏ ﮐﺎﻣﭙﻴﻮﺗﺮ ﯾﺎ ﯾﮏ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ( داراﯼ دو ﺑﺨـﺶ اﺻـﻠﯽ اﺳـﺖ :ﺳـﺨﺖ
اﻓﺰار و ﻧﺮم اﻓﺰار .ﺑﺎ ﭼﻴﺴﺘﯽ اﯾﻦ دو ﺑﺨﺶ ﮐﻢ و ﺑﻴﺶ ﺁﺷﻨﺎ هﺴﺘﻴﻢ.
ﻧﮑﺘﻪ ﺑﺴﻴﺎر ﻣﻬﻢ و در ﻋﻴﻦ ﺣﺎل ﺳﺎدﻩ اﯼ ﮐﻪ ﺑﺎﯾﺪ ﺑﻪ ﺁن ﺗﻮﺟﻪ ﮐﺮد ﻧﺤﻮﻩ ﺑﺮﻗﺮارﯼ ارﺗﺒﺎط ﺑﻴﻦ ﺳﺨﺖ اﻓﺰار
و ﻧﺮم اﻓﺰار در ﯾﮏ ﻣﻴﮑﺮو ﮐﻨﺘﺮﻟﺮ اﺳﺖ.
ﺑﺎﯾﺪ راهﯽ وﺟﻮد داﺷﺘﻪ ﺑﺎﺷﺪ ﮐﻪ دﺳﺘﻮراﺗﯽ ﮐﻪ ﻧﺮم اﻓﺰار ﺻﺎدر ﻣﯽ ﮐﻨﺪ ،ﺑﻪ ﺳﺨﺖ اﻓﺰار ﻣﻨﺘﻘﻞ ﺷﻮد ﺗﺎ
r
ﺳﺨﺖ اﻓﺰار ﺑﻪ درﺳﺘﯽ ﺁﻧﻬﺎ را اﺟﺮا ﮐﻨﺪ .در ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮهﺎ »واﺳﻄﻪ ارﺗﺒﺎﻃﯽ ﻣﻴـﺎن ﺳـﺨﺖ اﻓـﺰار و ﻧـﺮم
.i
اﻓﺰار« ،ﺣﺎﻓﻄﻪ داﺧﻠﯽ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ اﺳﺖ .ﺣﺎﻓﻄﻪ داﺧﻠﯽ ﺑﻪ دوﺑﺨﺶ ﺗﻘﺴﻴﻢ ﻣﯽ ﺷﻮد ﮐﻪ ﯾﮑﯽ از اﯾـﻦ
دو ﺑﺨﺶ وﻇﻴﻔﻪ ﺑﺮﻗﺮارﯼ ارﺗﺒﺎط ﻣﻴﺎن ﺳﺨﺖ اﻓﺰار و ﻧﺮم اﻓﺰار را ﺑﺮ ﻋﻬﺪﻩ دارد .هﺮ ﺑﺎﯾﺖ در اﯾﻦ ﺑﺨﺶ ﯾﮏ
s
»رﺟﻴﺴﺘﺮ« ﻧﺎﻣﻴﺪﻩ ﻣﯽ ﺷﻮد .هﺮ رﺟﻴﺴﺘﺮ ﮐﺎرﺑﺮد ﻣﺸﺨﺼﯽ دارد.ﺑﻪ اﯾﻦ ﺗﺮﺗﻴﺐ ،ﻧﺮم اﻓﺰار ﺑﻪ وﺳﻴﻠﻪ ﻗﺮار
دادن ﻣﻘﺎدﯾﺮ ﻣﺸﺨﺼﯽ در اﯾﻦ رﺟﻴﺴﺘﺮ هﺎ دﺳﺘﻮرات ﻣﺸﺨﺼﯽ ﺑﻪ ﺳﺨﺖ اﻓﺰار ﻣﯽ دهﺪ.
r
e
k
ورودﯼ و ﺧﺮوﺟﯽ ﻣﻌﻤﻮﻟﯽ )(Simple I/O
a
ﯾــﮏ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟــﺮ ،ﺑــﺮ ﺧــﻼف ﯾــﮏ ﮐــﺎﻣﭙﻴﻮﺗﺮ ،ﻣﺠﻬــﺰ ﺑــﻪ وﺳــﺎﯾﻞ ورودﯼ و ﺧﺮوﺟــﯽ ﭘﻴــﺸﺮﻓﺘﻪ اﯼ ﻣﺎﻧﻨــﺪ
Keyboard ،Speaker ،Monitorو ﯾﺎ Mouseﻧﻴﺴﺖ .ﺑﻠﮑﻪ ﺗﻨﻬﺎ راﻩ ارﺗﺒـﺎط ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮهـﺎ )ﻣﺎﻧﻨـﺪ هـﺮ IC
lM
دﯾﮕﺮﯼ( ﭘﺎﯾﻪ هﺎﯼ ICﻣﯽ ﺑﺎﺷﺪ) .ﭘﺎﯾﻪ هﺎﯼ ICزاﺋﺪﻩ هﺎﯼ ﻓﻠﺰﯼ ﮐﻮﭼﮑﯽ هﺴﺘﻨﺪ ﮐﻪ اﻃﺮف ICﻗﺮار ﻣﯽ
ﮔﻴﺮﻧﺪ) .ﺷﮑﻞ (١
o
tr
n
o
.C
w
w
w
ﺷﮑﻞ .١ﺳﻤﺖ راﺳﺖ :ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ .A89C51ﺳﻤﺖ ﭼﭗ :ﻧﺎم ﭘﺎﯾﻪ هﺎﯼ اﯾﻦ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ.
ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ AT89C51داراﯼ ۴٠ﭘﻴﻦ ﯾﺎ ﭘﺎﯾﻪ اﺳﺖ ٣٢ .ﺗـﺎ از اﯾـﻦ ﭘـﻴﻦ هـﺎ ،ورودﯼ هـﺎ و ﺧﺮوﺟـﯽ هـﺎﯼ
دﯾﺠﻴﺘﺎل هﺴﺘﻨﺪ .ﺑﻪ اﯾﻦ ﻣﻌﻨﯽ ﮐﻪ ﺑﻪ ﻋﻨﻮان ﺧﺮوﺟﯽ وﻟﺘﺎژ هﺎﯼ ٠وﻟﺖ و ﯾﺎ ۵وﻟﺖ را ﺗﻮﻟﻴـﺪ ﻣـﯽ ﮐﻨﻨـﺪ،
) ٠ﯾﺎ ١ﻣﻨﻄﻘﯽ( .ﺑﺮاﯼ ﻣﺜﺎل ﯾﮏ ﺧﺮوﺟﯽ دﯾﺠﻴﺘﺎل ﻧﻤﯽ ﺗﻮاﻧﺪ ﯾﮏ ﻣﻮج ﺳﻴﻨﻮﺳـﯽ ﺗﻮﻟﻴـﺪ ﮐﻨـﺪ .اﻣّـﺎ ﻣـﯽ
ﺗﻮاﻧﺪ ﯾﮏ ﻣﻮج ﻣﺮﺑﻌﯽ ﺑﺎ دو ﺳﻄﺢ ﺻﻔﺮ و ۵وﻟﺖ اﯾﺠﺎد ﻧﻤﺎﯾﺪ.
ﺑﺮاﯼ ﯾﮏ ورودﯼ دﯾﺠﻴﺘﺎل ﻧﻴﺰ ﺗﻨﻬﺎ دو ﻣﻘﺪار ٠ﯾﺎ ١ﻣﻨﻄﻘﯽ ﻗﺎﺑـﻞ درﮎ اﺳـﺖ .اﮔـﺮ وﻟﺘـﺎژ اﻋﻤـﺎل ﺷـﺪﻩ از
ﺧﺎرج ﻣﻴﮑﺮو از ﻣﻘﺪار ﻣﺸﺨﺼﯽ )ﺣﺪود ٢وﻟﺖ( ﺑـﺎﻻﺗﺮ ﺑﺎﺷـﺪ از ﻧﻈـﺮ ﻣﻴﮑـﺮو ،١و اﮔـﺮ از ﺁن ﺣـﺪ ﭘـﺎﯾﻴﻦ ﺗـﺮ
ﺑﺎﺷﺪ ﺻﻔﺮ اﺳﺖ.
از ﻣﻴﺎن اﯾﻦ ۴٠ﭘﺎﯾﻪ ٨،ﭘﺎﯾﻪ ﮐﺎرﺑﺮد هﺎﯾﯽ ﻏﻴﺮ از I/Oدارﻧـﺪ و ٣٢ﭘﺎﯾـﻪ دﯾﮕـﺮ در ﻏﺎﻟـﺐ » ۴ﭘـﻮرت« ٨ﺑﻴﺘـﯽ
واﺳﻄﻪ ارﺗﺒﺎط ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ﺑﺎ ﺟﻬﺎن ﺧﺎرج هﺴﺘﻨﺪ .اﯾﻦ ﭼﻬﺎر ﭘـﻮرت از ٠ﺗـﺎ ٣ﺷـﻤﺎرﻩ ﮔـﺬارﯼ ﺷـﺪﻩ اﻧـﺪ.
r
ﻣﺤﻞ ﭘﺎﯾﻪ هﺎﯼ هﺮ ﭘﻮرت در ﺷﮑﻞ ١ﻧﻤﺎﯾﺶ دادﻩ ﺷﺪﻩ اﺳﺖ.
.i
هﻤﺎﻧﻄﻮر ﮐﻪ ﮔﻔﺘﻪ ﺷﺪ وﺳﻴﻠﻪ ارﺗﺒﺎط ﻣﻴﺎن ﺳﺨﺖ اﻓﺰار و ﻧﺮم اﻓﺰار ،رﺟﻴﺴﺘﺮهﺎ هﺴﺘﻨﺪ .ﻓﺮض ﮐﻨﻴﺪ ﻣـﯽ
s
ﺧﻮاهﻴﻢ وﻟﺘﺎژ ﯾﮑﯽ از ﭘﺎﯾﻪ هﺎﯼ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ را ۵وﻟﺖ ﻗـﺮار دهـﻴﻢ ) ١ﻣﻨﻄﻘـﯽ( .ﺗﻮﺟـﻪ ﮐﻨﻴـﺪ ﮐـﻪ در اﯾـﻦ
ﺣﺎﻟﺖ اﯾﻦ ﭘﺎﯾﻪ ،ﯾﮏ ﺧﺮوﺟﯽ اﺳﺖ .ﺑﺎﯾﺪ رﺟﻴﺴﺘﺮﯼ وﺟﻮد داﺷـﺘﻪ ﺑﺎﺷـﺪ ﮐـﻪ اﯾـﻦ اﻣﮑـﺎن را ﺑـﺮاﯼ ﺑﺮﻧﺎﻣـﻪ
r
ﻧﻮﯾﺲ ﻓﺮاهﻢ ﺁورد ﺗﺎ ﻣﻘﺪار ﻣﻨﻄﻘﯽ دﻟﺨﻮاهﯽ را ﺑﺮ روﯼ هﺮ ﯾﮏ از ﭘﺎﯾﻪ هـﺎﯼ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟـﺮ ﻗـﺮار دهـﺪ .در
e
ﻓﺎﯾﻞ Headerاﯼ ﮐﻪ ﻣﺎ ﺑﻪ ﺑﺮﻧﺎﻣﻪ هﺎﯼ ﺧﻮد اﺿﺎﻓﻪ ) (includeﻣﯽ ﮐﻨﻴﻢ ) (AT89X51.hﺑـﺮاﯼ هـﺮ ﯾـﮏ از
اﯾﻦ رﺟﻴﺴﺘﺮ هﺎ ﻧﺎﻣﯽ در ﻧﻈﺮ ﮔﺮﻓﺘﻪ ﺷﺪﻩ ﺗﺎ ﮐﺎر ﺑﺮﻧﺎﻣﻪ ﻧﻮﯾﺴﯽ ﺳﺎدﻩ ﺗـﺮ ﺷـﻮد .١ﺑـﻪ اﯾـﻦ ﺗﺮﺗﻴـﺐ ﻧﻴـﺎزﯼ
k
ﻧﻴﺴﺖ ﮐﻪ ﻣﺎ هﺮ ﺑﺎر ﺑﺎ ﻣﺮاﺟﻌﻪ ﺑﻪ ﺷﮑﻞ ﺣﺎﻓﻄﻪ ،ﺁدرﺳﻬﺎ را ﺑﻴﺎﺑﻴﻢ و ﻣﯽ ﺗﻮاﻧﻴﻢ از اﯾﻦ اﺳﺎﻣﯽ اﺳـﺘﻔﺎدﻩ
ﮐﻨﻴﻢ .هﺮ ﭘﻮرت ٨ﺑﻴﺘﯽ ﺑﺎ ﯾﮏ ﺑﺎﯾﺖ ) ٨ﺑﻴﺖ( ﻣﺘﻨﺎﻇﺮ اﺳﺖ .ﺑﻨﺎﺑﺮاﯾﻦ ﺗﻨﺎﻇﺮﯼ ﯾﮏ ﺑﻪ ﯾﮏ ﻣﻴﺎن ،ﺑﻴﺘﻬﺎﯼ هﺮ
a
ﯾﮏ از اﯾﻦ رﺟﻴﺴﺘﺮ هﺎ ﺑﺎ ﭘﺎﯾﻪ هﺎﯼ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ﺑﻪ وﺟﻮد ﻣﯽ ﺁﯾـﺪ و ﻣﻘـﺪار هـﺮ ﺑﻴـﺖ در رﺟﻴـﺴﺘﺮ ،ﺗﻌﻴـﻴﻦ
lM
ﮐﻨﻨﺪﻩ وﻟﺘﺎژ ﭘﺎﯾﻪ ﻣﺘﻨﺎﻇﺮ ﺁن ﺧﻮاهﺪ ﺑﻮد .ﺑﻪ ﻋﻨﻮان ﻣﺜﺎل رﺟﻴﺴﺘﺮ ﻣﺘﻨﺎﻇﺮ ﭘـﻮرت ،P0 ،٠در ﺷـﮑﻞ ٢ﻧـﺸﺎن
دادﻩ ﺷﺪﻩ اﺳﺖ.
o
tr
ﺷﮑﻞ .٢رﺟﻴﺴﺘﺮ .P0اﯾﻦ رﺟﻴﺴﺘﺮ ارﺗﺒﺎط ﺑﻴﻦ ﻧﺮم اﻓﺰار و ﭘﻴﻨﻬﺎﯼ ﭘﻮرت ٠را ﺑﺮﻗﺮار ﻣﯽ ﮐﻨﺪ.
n
ﻣﺜﺎل : ١
o
.C
ﻓﺮض ﮐﻨﻴﺪ ﺧﺮوﺟﯽ دو ﺳﻨﺴﻮر ﺗﺸﺨﻴﺺ رﻧﮓ )ﺳﻴﺎﻩ و ﺳﻔﻴﺪ( ﺑﻪ دو ﭘﺎﯾـﻪ از ﻣﻴﮑﺮوﮐﻨﺘﺮﻟـﺮ ﻣﺘـﺼﻞ ﺷـﺪﻩ
اﺳﺖ .هﺮ ﯾﮏ از اﯾﻦ ﺳﻨﺴﻮرهﺎ اﮔﺮ رﻧﮓ ﺳﻔﻴﺪ را ﺗﺸﺨﻴﺺ دهﺪ )ﺑﺒﻴﻨﺪ( ﺧﺮوﺟﯽ ﺧـﻮد را ١ﻣﻨﻄﻘـﯽ )۵
وﻟﺖ( ﻗﺮار ﻣـﯽ دهـﺪ ،و ﺑـﺮاﯼ ﺳـﻴﺎﻩ ٠ ،ﻣﻨﻄﻘـﯽ )ﺻـﻔﺮ وﻟـﺖ( .ﺣـﺎل ﻣـﯽ ﺧـﻮاهﻴﻢ ،ﺑـﺮاﯼ ﺁزﻣـﻮدن اﯾـﻦ
w
ﺳﻨﺴﻮرهﺎ ،دو ﭼﺮاغ ) (LEDرا ﺑﻪ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ﻣﺘﺼﻞ ﮐﺮدﻩ و ﺑﺮﻧﺎﻣﻪ اﯼ ﺑﻨﻮﺳﻴﻢ ﮐﻪ ﺑـﺎ ﺗـﺸﺨﻴﺺ ﺳـﻔﻴﺪ
ﭼﺮاغ هﺎ روﺷﻦ ﺷﻮﻧﺪ و ﺑﺎ ﺗﺸﺨﻴﺺ ﺳﻴﺎﻩ ،ﺧﺎﻣﻮش .ﻣﺪار ﻻزم در ﺷﮑﻞ ٣ﻧﺸﺎن دادﻩ ﺷﺪﻩ اﺳﺖ.
w
w
1ﺑﺪ ﻧﻴﺴﺖ ﯾﮏ ﺑﺎر ﻣﺤﺘﻮﯾﺎت اﯾﻦ ﻓﺎﯾﻞ را ﺑﺒﻴﻨﻴﺪ .ﺑﺎ اﻧﺘﺨﺎب File|Openدر ،Keilﻣﯽ ﺗﻮاﻧﻴﺪ اﯾﻦ ﻓﺎﯾﻞ را از ﺁدرس
[Keil]\C51\INC\Atmelﺑﺎز ﮐﻨﻴﺪ .ﻣﻨﻈﻮر از ] [Keilﻣﺤﻠﯽ اﺳﺖ ﮐﻪ Keilرا در ﺁن ﻧﺼﺐ ﮐﺮدﻩ اﯾﺪ.
r
.i
s
r
e
k
a
ﺷﮑﻞ .٣ﻣﺤﻞ ﭘﺎﯾﻪ هﺎ ﺟﺎﺑﺠﺎ ﺷﺪﻩ ،ﻣﯽ ﺗﻮاﻧﻴﺪ ﺁﻧﻬﺎ را از روﯼ اﺳﻢ ﯾﺎ ﺷﻤﺎرﻩ ﭘﺎﯾﻪ ﭘﻴﺪا ﮐﻨﻴﺪ.
lM
Sensorهﺎ ﺑﻪ ﭘﻴﻦ اول و دوم از ﭘﻮرت P1.0) ١و (P1.1ﻣﺘﺼﻞ ﺷﺪﻩ اﻧﺪ LED .هﺎ هﻢ ﺑﻪ P2.0و .P2.7
ﻧﮑﺘﻪ ﻣﻬﻢ :ﻗﺒﻞ از اﯾﻨﮑﻪ ﺑﺘﻮاﻧﻴﻢ از ﯾﮑﯽ از ﭘﺎﯾﻪ هﺎﯼ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ﺑﻪ ﻋﻨﻮان ورودﯼ اﺳﺘﻔﺎدﻩ ﮐﻨـﻴﻢ ،ﻻزم
اﺳﺖ اﺑﺘﺪا هﻤﺎن ﭘﻴﻦ را ﯾﮏ ﮐﻨﻴﻢ .اﯾﻦ ﻋﻤﻞ ﭘﺎﯾﻪ ﻣﻮرد ﻧﻈﺮ را ﺁﻣﺎدﻩ درﯾﺎﻓﺖ ورودﯼ ﻣﯽ ﮐﻨﺪ.
Timerهﺎ
ﺑﺮاﯼ اﯾﻨﮑﻪ ﺳﻨﺠﺶ زﻣﺎن ﺑﺮاﯼ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ﻣﻴﺴﺮ ﺑﺎﺷﺪ ﺑﺎﯾﺪ ﻣﻌﻴﺎرﯼ از زﻣﺎن در اﺧﺘﻴﺎر ﺳﺨﺖ اﻓﺰار ﻗـﺮار
ﺑﮕﻴﺮد .اﯾﻦ ﮐﺎر ﺑﻪ وﺳﻴﻠﻪ ﺳﻴﮕﻨﺎل Clockاﻧﺠﺎم ﻣﯽ ﺷﻮد .ﺳﻴﮕﻨﺎل ،Clockﯾﮏ ﻣﻮج ﭘﺮﯾﻮدﯾﮏ ﺑﺎ ﻓﺮﮐـﺎﻧﺶ
r
ﻣﺸﺨﺺ اﺳﺖ .ﻓﺮﮐﺎﻧﺲ Clockﺑﺮاﯼ ﯾﮏ 8051ﺣﺪاﮐﺜﺮ ﻣﯽ ﺗﻮاﻧﺪ 24 MHzﺑﺎﺷﺪ اﻣّـﺎ ﻣﻘـﺪار ﻣﻌﻤـﻮل ﺁن
.i
12 MHzاﺳﺖ .ﻓﺮﮐﺎﻧﺲ اﯾﻦ ﺳﻴﮕﻨﺎل ،ﭘﻴﺶ از ﺁﻧﮑـﻪ ﺑـﻪ Timerهـﺎ اﻋﻤـﺎل ﺷـﻮد ،ﺑـﻪ ١٢ﺗﻘـﺴﻴﻢ ﻣـﯽ
ﺷـﻮد .ﯾﻌﻨــﯽ ﻓﺮﮐــﺎﻧﺲ ﺳــﻴﮕﻨﺎل Clockاﻋﻤـﺎل ﺷــﺪﻩ ﺑــﻪ Timerهــﺎ 1 MHzﺧﻮاهــﺪ ﺑــﻮد) .از اﯾــﻦ ﭘــﺲ
s
ﻓﺮﮐﺎﻧﺲ Clockاﻋﻤﺎل ﺷﺪﻩ ﺑﻪ Timerرا 1 MHzدر ﻧﻈﺮ ﻣﯽ ﮔﻴﺮﯾﻢ ،ﺑﻨﺎﺑﺮاﯾﻦ هﺮ ﭘﺮﯾـﻮد Clockﮐـﻪ ﺑـﻪ ﺁن
»ﺳﻴﮑﻞ ﻣﺎﺷﻴﻦ« ﻧﻴﺰ ﮔﻔﺘﻪ ﻣﯽ ﺷﻮد ١ ،ﻣﻴﮑﺮوﺛﺎﻧﻴﻪ ﺧﻮاهﺪ ﺑﻮد(
r
e
هﺮ Timerدر واﻗﻊ ﯾﮏ ﺷﻤﺎرﻧﺪﻩ ) (Counterاﺳﺖ ﮐﻪ ﺗﻌﺪاد ﭘﺮﯾﻮدهﺎﯼ ﺳﻴﮕﻨﺎل Clockرا )ﺑﻌﺪ از ﺗﻘﺴﻴﻢ
k
ﻓﺮﮐﺎﻧﺲ ﺑﺮ (١٢ﻣﯽ ﺷﻤﺎرد .اﮔﺮ ﻓﺮﮐﺎﻧﺲ Clockاﻋﻤـﺎل ﺷـﺪﻩ ﺑـﻪ Timerرا 1 MHzﻓـﺮض ﮐﻨـﻴﻢ ،هـﺮ ١
ﻣﻴﮑﺮو ﺛﺎﻧﻴﻪ ،ﻣﺤﺘﻮاﯼ اﯾﻦ ﺷﻤﺎرﻧﺪﻩ ﯾﮏ واﺣﺪ اﻓﺰاﯾﺶ ﻣﯽ ﯾﺎﺑﺪ .ﻣـﯽ ﺗـﻮان ﺑـﺎ ﺿـﺮب ﮐـﺮدن ﻣﺤﺘـﻮاﯼ اﯾـﻦ
a
ﺷﻤﺎرﻧﺪﻩ در ﭘﺮﯾﻮد Clockﻣﺪت زﻣﺎن ﺳﭙﺮﯼ ﺷﺪﻩ را ﻣﺤﺎﺳﺒﻪ ﻧﻤﻮد.
lM
هﺮ ﯾﮏ از Timerهﺎﯼ ١۶ ،٨٠۵١ﺑﻴﺘﯽ هﺴﺘﻨﺪ .ﯾﻌﻨﯽ ﻣﻘﺪارﯼ ﮐﻪ Timerﻣﯽ ﺷﻤﺎرد در دو ﺑﺎﯾـﺖ )١۶
ﺑﻴﺖ( ﻧﮕﻬﺪارﯼ ﻣﯽ ﺷﻮد .ﺑﻨﺎﺑﺮاﯾﻦ ﺑﺰرﮔﺘﺮﯾﻦ ﻋﺪدﯼ ﮐﻪ ﯾﮏ Timerﻣﯽ ﺗﻮاﻧﺪ ذﺧﻴﺮﻩ ﮐﻨﺪ ،216 – 1 ،ﯾﻌﻨـﯽ
۶۵۵٣۵اﺳﺖ .اﮔﺮ رﺟﻴﺴﺘﺮ Timerﺣﺎوﯼ اﯾـﻦ ﻋـﺪد ﺑﺎﺷـﺪ ،ﺑـﺎ اﻋﻤـﺎل ﭘـﺎﻟﺲ ﺑﻌـﺪﯼ Clockﭼـﻪ اﺗﻔـﺎﻗﯽ
ﺧﻮاهﺪ اﻓﺘﺎد؟ ﻣﻘﺪار ﺑﻌﺪﯼ رﺟﻴﺴﺘﺮ ٠اﺳﺖ .در واﻗﻊ رﺟﻴﺴﺘﺮ Overflow ،Timerﯾﺎ ﺳﺮرﯾﺰ ﻣـﯽ ﺷـﻮد و
o
ﺑﻴــﺖ دﯾﮕــﺮﯼ ﺑــﻪ ﺟــﺰ ١۶ﺑﻴــﺖ ﺷــﻤﺎرﻧﺪﻩ ) (Flagﺑــﻪ ﻧــﺸﺎن ،Overflowﯾــﮏ ﻣــﯽ ﺷــﻮد .از اﯾــﻦ اﺗﻔــﺎق
) Overflowو ﯾﮏ ﺷﺪن ﺑﻴﺖ (Flagﺑﺮاﯼ اﯾﺠﺎد ﺗﺄﺧﻴﺮ ﺑﻪ ﻣﻴﺰان ﻣﺸﺨﺺ اﺳﺘﻔﺎدﻩ ﻣﯽ ﺷﻮد.
tr
ﻓﺮض ﮐﻨﻴﺪ ﻗﺼﺪ دارﯾﻢ ﺗﺄﺧﻴﺮﯼ ﺑﻪ اﻧﺪازﻩ ١٠٠ﻣﻴﮑﺮوﺛﺎﻧﻴﻪ اﯾﺠﺎد ﮐﻨﻴﻢ .در اﯾﻦ ﺻـﻮرت ،ﻋـﺪد 65535 – 100
n
را در رﺟﻴﺴﺘﺮ Timerﻗﺮار ﻣﯽ دهﻴﻢ .ﺑﻌﺪ از ١٠٠ﭘﺮﯾـﻮد Clockﻣﺤﺘـﻮاﯼ رﺟﻴـﺴﺘﺮ ﺑـﻪ ﺣـﺪاﮐﺜﺮ ﺧـﻮد ﻣـﯽ
رﺳﺪ و Overflowﻣﯽ ﺷﻮد و هﻤﺰﻣﺎن ﺑﺎ ﺁن ﺑﻴﺖ ﻧﺸﺎن دهﻨﺪﻩ ﺳﺮرﯾﺰ ﻧﻴﺰ ﯾـﮏ ﻣـﯽ ﺷـﻮد .در واﻗـﻊ ﯾـﮏ
o
ﺷﺪن ﺑﻴﺖ Overflowﺑﻪ ﻣﻌﻨﯽ ﺳﭙﺮﯼ ﺷﺪن زﻣﺎن ﻣﻮرد ﻧﻈﺮ اﺳﺖ.
.C
هﻤﺎﻧﻄﻮر آﻪ ﮔﻔﺘـﻪ ﺷـﺪ ﻣﻴﻜﺮوآﻨﺘﺮﻟـﺮ AT89C51داراي دو Timerاﺳـﺖ .اﻳـﻦ دو Timerﺑـﺎ اﻋـﺪاد ٠و ١
ﻧﺸﺎن دادﻩ ﻣﻲ ﺷﻮﻧﺪ .هﻤﭽﻨﻴﻦ رﺟﻴﺴﺘﺮهﺎي هﺮ آﺪام از اﻳﻦ دو Timerﺑﺎ هﻤـﻴﻦ دو رﻗـﻢ از هـﻢ ﺗﻤﻴـﺰ
دادﻩ ﻣﻲ ﺷﻮﻧﺪ .از اﻳﻦ ﭘﺲ ،ﺑﺮاي ﺣﻔﻆ آﻠﻴﺖ ﻣﻄﺎﻟﺐ ،ﺑﻪ ﺟﺎي ١ﻳﺎ ٠از xاﺳﺘﻔﺎدﻩ ﻣﻲ آﻨﻴﻢ ،زﻳﺮا اﻳـﻦ
w
ﺣﺎل ﺑﺎ دﻗﺖ ﺑﻴﺸﺘﺮي ﺳﺨﺖ اﻓﺰار Timerرا ﺑﺮرﺳﻲ ﻣﻲ آﻨﻴﻢ .رﺟﻴﺴﺘﺮ ١۶ﺑﻴﺘـﻲ Timerدر واﻗـﻊ از دو
رﺟﻴﺴﺘﺮ ٨ﺑﻴﺘﻲ ﺑﻪ ﻧﺎﻣﻬﺎي THxو TLxﺗﺸﻜﻴﻞ ﻣﻲ ﺷﻮد ٨ ،(Timer High byte) THx .ﺑﻴﺖ ﺑﺎﻻ و TLx
) ٨ (Timer Low byteﺑﻴﺖ ﭘﺎﻳﻴﻦ هﺴﺘﻨﺪ .ﺷﻜﻞ ۴رﺟﻴﺴﺘﺮ Timerرا ﻧﺸﺎن ﻣﻲ دهﺪ.
w
r
.i
s
r
e
ﺷﮑﻞ .۴رﺟﻴﺴﺘﺮهﺎﯼ ﺷﻤﺎرﻧﺪﻩ ٨ .Timerﺑﻴﺖ ﺑﺎﻻ در THو ٨ﺑﻴﺖ ﭘﺎﯾﻴﻦ در TLﻗﺮار ﻣﯽ ﮔﻴﺮﻧﺪ.
k
ﻣﺪهﺎي آﺎري Timer
a
هﺮ Timerﻣﻲ ﺗﻮاﻧﺪ ﭼﻬﺎر "رﻓﺘﺎر" ﻣﺘﻔﺎوت داﺷﺘﻪ ﺑﺎﺷﺪ آﻪ ﺑﻪ هﺮ ﻳﻚ از اﻳﻨﻬﺎ ﻳﻚ "ﻣﺪ آﺎري" ﻣﻲ ﮔﻮﻳﻨـﺪ.
lM
از اﻳﻦ ﭼﻬﺎر ﻣﺪ ،ﻣﺎ ﺗﻨﻬﺎ دو ﻣﺪ را ﺑﺮرﺳﻲ ﻣﻲ آﻨﻴﻢ .ﻣﺪ ١و ﻣﺪ .٢
o
Timerدر ﻣﺪ ١از ﺗﻤﺎم ١۶ﺑﻴﺖ ﺧﻮد ﺑﺮاي ﺷﻤﺎرش اﺳﺘﻔﺎدﻩ ﻣﻲ آﻨﺪ .ﻳﻌﻨـﻲ ﺑﺰرﮔﺘـﺮﻳﻦ ﻋـﺪد در Timer
ﻣﻲ ﺗﻮاﻧﺪ 65535ﺑﺎﺷﺪ .ﻧﺘﻴﺠﺘﺎً ﻃﻮﻻﻧﻲ ﺗﺮﻳﻦ ﺗﺄﺧﻴﺮي آـﻪ Timerدر ﻣـﺪ ١ﻣـﻲ ﺗﻮاﻧـﺪ ﺑـﻪ ﺗﻨﻬـﺎﻳﻲ اﻳﺠـﺎد
آﻨﺪ ،آﻤﻲ ﺑﻴﺶ از ۶۵ﻣﻴﻠﻲ ﺛﺎﻧﻴﻪ اﺳﺖ .در اﻳﻦ ﻣﺪ ،هﺮ ﺑﺎر آـﻪ Timerﺳـﺮرﻳﺰ ﻣـﻲ ﺷـﻮد ،ﺑﺎﻳـﺪ ﻣﻘـﺪار
n
ﻣﻮرد ﻧﻈﺮ را دوﺑﺎرﻩ در ﺁن Loadآﺮد .اﻳﻦ ﻋﻤﻞ ﻧﻴﺎز ﺑﻪ ﭼﻨﺪ ﻣﻴﻜﺮوﺛﺎﻧﻴﻪ زﻣﺎن دارد و زﻣﺎﻧﻲ آﻪ ﺑـﺎزﻩ زﻣـﺎﻧﻲ
ﻣﻮرد ﻧﻈﺮ آﻮﭼﻚ ﺑﺎﺷﺪ )ﻣﺜﻼً ﺗﻮﻟﻴﺪ ﻣﻮج (100 KHzاﻳﻦ ﻣﺴﺌﻠﻪ دﻗﺖ را آﺎهﺶ ﻣﻲ دهﺪ) .ﻣﺜﻼً ﺑـﻪ ﺟـﺎي
o
اﻳﻦ ﻣﺪ ﻣﺸﻜﻠﻲ آﻪ در ﻣﻮرد ﻣﺪ ١ﻣﻮرد ﺑﺤﺚ ﻗﺮار ﮔﺮﻓﺖ را ﺑﺮﻃﺮف ﻣﻲ آﻨﺪ .در ﻣﺪ ،٢ﺗﻨﻬﺎ هـﺸﺖ ﺑﻴـﺖ
از Timerﺑﺮاي ﺷﻤﺎرش اﺳﺘﻔﺎدﻩ ﻣﻲ ﺷﻮد )ﺑﻨﺎﺑﺮاﻳﻦ ﻃﻮﻻﻧﻲ ﺗـﺮﻳﻦ ﺗـﺄﺧﻴﺮ ﻣـﻲ ﺗﻮاﻧـﺪ ٢۵۵ﻣﻴﻜـﺮو ﺛﺎﻧﻴـﻪ
ﺑﺎﺷﺪ( .اﻣّﺎ ٨ﺑﻴﺖ دﻳﮕﺮ Timerﻣﻘﺪار ﺑﻌﺪي آﻪ ﺑﺎﻳﺪ در ٨ﺑﻴـﺖ ﺷـﻤﺎرﻧﺪﻩ ﻗـﺮار دادﻩ ﺷـﻮد را ذﺧﻴـﺮﻩ ﻣـﻲ
آﻨــﺪ .ﻣــﺜﻼً ﺑــﺮاي ﺗﻮﻟﻴــﺪ ﻳــﻚ ﻣــﻮج ،100 KHzﻋــﺪد 255 – 10را هــﻢ در رﺟﻴــﺴﺘﺮ ﺷــﻤﺎرﻧﺪﻩ و هــﻢ در
رﺟﻴﺴﺘﺮي ذﺧﻴﺮﻩ آﻨﻨﺪﻩ ﻗﺮار ﻣﻲ دهﻴﻢ ،زﻣـﺎﻧﻲ آـﻪ ﺑـﺮاي اوﻟـﻴﻦ ﺑـﺎر Overflowاﺗﻔـﺎق ﺑﻴﻔﺘـﺪ ،ﺑـﺎ اﻳﻨﻜـﻪ
ﻣﺤﺘﻮاي رﺟﻴﺴﺘﺮ ﺷﻤﺎرﻧﺪﻩ ﺻﻔﺮ ﺷﺪﻩ اﺳﺖ )درﺳﺖ ﭘﺲ از (Overflowاﻣّﺎ هﻤﺮﻣـﺎن ﺑـﺎ ،Overflowﺑـﻪ
ﻃﻮر ﺧﻮدآﺎر و ﺗﻮﺳﻂ ﺳﺨﺖ اﻓﺰار ،ﻣﻘﺪار 255 – 10از رﺟﻴﺴﺘﺮ ذﺧﻴﺮﻩ آﻨﻨﺪﻩ ﺑﻪ رﺟﻴﺴﺘﺮ ﺷﻤﺎرﻧﺪﻩ آﭙـﻲ
r
ﻣﻲ ﺷﻮد و ﺷﻤﺎرش اداﻣﻪ ﻣﻲ ﻳﺎﺑﺪ .ﺑﻪ اﻳﻦ ﺗﺮﺗﻴﺐ ﺑﺪون اﻳﻨﻜﻪ زﻣﺎن اﺿـﺎﻓﻲ ﺗﻠـﻒ ﺷـﻮد " Timerدﻗﻴﻘـﺎً"
هﺮ ١٠ﻣﻴﻜﺮوﺛﺎﻧﻴﻪ ﻳﻚ ﺑﺎر Overflowﻣﻲ ﺷﻮد .اﻳﻦ ﺧﺎﺻﻴﺖ را Auto Reloadﮔﻮﻳﻨﺪ.
.i
s
r
e
k
a
lM
o
tr
n
ﭘﻴﺶ از ﺁﻧﻜﻪ از Timerهﺎ اﺳﺘﻔﺎدﻩ آﻨﻴﻢ ﻻزم اﺳـﺖ اﺑﺘـﺪا Timerرا ﺑـﺮاي آـﺎر در ﻣـﺪ ﻣـﻮرد ﻧﻈـﺮ ﺗﻨﻈـﻴﻢ
.C
آﻨﻴﻢ .ﻋﻼوﻩ ﺑﺮ ﺗﻌﻴﻴﻦ ﻣﺪ ﺗﻨﻈﻴﻤﺎت دﻳﮕﺮي ﻧﻴﺰ ﻻزم اﺳﺖ آﻪ در زﻳﺮ ﺷﺮح دادﻩ ﻣﻲ ﺷﻮد.
ﺷﺮح ﮐﺎر اﯾﻦ ﺑﻴﺘﻬﺎ در ﺟﺪول زﯾﺮ ﺁﻣﺪﻩ اﺳﺖ .ﺑﻴﺘﻬﺎﯼ GATEو ) C/Tﺑﻴﺘﻬﺎﯼ ١و ٢و ۶و (٧ﻓﻌﻼً ﺑﺮاﯼ ﻣـﺎ
ﮐﺎرﺑﺮدﯼ ﻧﺪارﻧﺪ.
Bit Bit Name Purpose Timer
r
0 Timer works regardless of INT0 (P3.2)
.i
2 C/T0 1 Timer counts impulses on T0 (P3.4) T0
0 Timer counts impulses of internal oscillator
s
1 T0M1 Timer mode T0
r
0 T0M0 Timer mode T0
e
ﺗﻌﻴﻴﻦ ﻣـﯽ ﺷـﻮﻧﺪ ﺑـﻪ ﺷـﺮح زﯾـﺮ ﻣـﯽTMOD هﺎ ﮐﻪ ﺑﻪ وﺳﻴﻠﻪ ﺑﻴﺘﻬﺎﯼ رﺟﻴﺴﺘﺮTimer ﻣﺪهﺎﯼ ﻣﺨﺘﻠﻒ
k
. اﺳﺘﻔﺎدﻩ ﺧﻮاهﻴﻢ ﮐﺮد٢ و١ ﻣﺎ ﺗﻨﻬﺎ از ﻣﺪهﺎﯼ.ﺑﺎﺷﻨﺪ
a
T0M1 T0M0 Mode lM Description
0 0 0 13-bit Timer
0 1 1 16-bit Timer
1 0 2 8-bit auto-reload
o
1 1 3 Split mode
tr
. ﻣﺮﺑﻮط ﻣﯽ ﺷﻮﻧﺪTimer از ﻣﻴﺎن اﯾﻦ ﺑﻴﺘﻬﺎ ﺗﻨﻬﺎ ﭼﻬﺎر ﺑﻴﺖ ﺑﺎﻻ ﺑﻪ
w
w
w
ﺷﺮح ﮐﺎر اﯾﻦ ﺑﻴﺘﻬﺎ در ﺟﺪول زﯾﺮ ﺁﻣﺪﻩ اﺳﺖ.
r
4 TR0 1 - Timer T0 is on T0
.i
0 - Timer T0 is off
s
ﺑﻴﺖ TFx : (Timer Flag) TFدر واﻗﻊ هﻤﺎن ﺑﻴﺖ ﻧﺸﺎن دهﻨﺪﻩ Overflowﻣﯽ ﺑﺎﺷﺪ.
r
ﺑﻴﺖ : (Timer Run bit) TRxاﮔﺮ اﯾﻦ ﺑﻴﺖ ﺻﻔﺮ ﺷﻮد Timer ،دﯾﮕﺮ ﭘﺎﻟﺲ هﺎﯼ ﺳﻴﮕﻨﺎل Clockرا ﻧﺨﻮاهﺪ
e
ﺷﻤﺮد و ﻣﺤﺘﻮاﯼ رﺟﻴﺴﺘﺮ ﺷﻤﺎرﻧﺪﻩ ﺑﺪون ﺗﻐﻴﻴﺮ ﺑﺎﻗﯽ ﻣﯽ ﻣﺎﻧﺪ.
k
ﺑﺮﻧﺎﻣﻪ رﯾﺰﯼ Timerدر ﻣﺪ ١
a
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ اﯾﻨﮑﻪ هﺮ Timerرا در ﭼﻪ ﻣﺪﯼ اﺳﺘﻔﺎدﻩ ﺧﻮاهﻴﺪ ﮐﺮد .ﻣﻘﺪار ﻣﻨﺎﺳﺒﯽ در TMODﻗﺮار .١
lM
دهﻴﺪ GATE .و C/Tرا ﺻﻔﺮ ﮐﻨﻴﺪ.
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﻣﻘﺪار ﺗﺄﺧﻴﺮ ﻣﻮرد ﻧﻴﺎز ،ﻣﻘﺎدﯾﺮ ﻣﻨﺎﺳﺐ را در THو TLﻗﺮار دهﻴﺪ. .٢
Timerرا روﺷﻦ ﮐﻨﻴﺪ. .٣
o
ﺑﻴﺖ ﺳﺮرﯾﺰ ا ﺻﻔﺮ ﮐﻨﻴﺪ ،ﺗﺎ در ﺳﺮرﯾﺰ ﺑﻌﺪﯼ ﯾﮏ ﺷﺪن ﺁن ﻗﺎﺑﻞ ﺗﺸﺨﻴﺺ ﺑﺎﺷﺪ. .۶
ﺑﻪ ﻣﺮﺣﻠﻪ ٢ﺑﺎز ﮔﺮدﯾﺪ. .٧
n
ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ اﯾﻨﮑﻪ هﺮ Timerرا در ﭼﻪ ﻣﺪﯼ اﺳﺘﻔﺎدﻩ ﺧﻮاهﻴﺪ ﮐﺮد .ﻣﻘﺪار ﻣﻨﺎﺳﺒﯽ در TMODﻗﺮار .١
دهﻴﺪ GATE .و C/Tرا ﺻﻔﺮ ﮐﻨﻴﺪ.
رﺟﻴﺴﺘﺮ THxرا Loadﮐﻨﻴﺪ .ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ اﻣﮑﺎن Auto Reloadﻧﻴﺎزﯼ ﺑﻪ Loadﮐـﺮدن TLxﻧـﺪارﯾﻢ. .٢
w
ﺑﻪ ﻣﺤﺾ روﺷﻦ ﺷﺪن Timerﻣﻘﺪار درون THxﺑﻪ TLxﮐﭙﯽ ﺷﺪﻩ و ﺷﻤﺎرش ﺁﻏﺎز ﺧﻮاهﺪ ﺷﺪ.
Timerرا روﺷﻦ ﮐﻨﻴﺪ. .٣
ﻣﻨﺘﻈﺮ ﯾﮏ ﺷﺪن TFxﺑﻤﺎﻧﻴﺪ. .۴
w
ﻣﺜﺎل : ٢
ﻣﯽ ﺧﻮاهﻴﻢ ﻣﻮج ﻣﺮﺑﻌﯽ ﺑﺎ ﻓﺮﮐﺎﻧﺲ 25 KHzروﯼ ﭘﺎﯾﻪ ١ول از ﭘـﻮرت (P1.0) ١اﯾﺠـﺎد ﮐﻨـﻴﻢ.در اﯾﻨـﺼﻮرت
ﻻزم اﺳﺖ ﮐﻪ در هﺮ ﻧﻴﻢ ﭘﺮﯾﻮد ﯾﮏ ﺑﺎر وﻟﺘﺎژ اﯾﻦ ﭘﺎﯾﻪ ﺗﻐﻴﻴﺮ ﮐﻨـﺪ .ﭘﺮﯾـﻮد اﯾـﻦ ﻣـﻮج ۴٠ﻣﻴﮑﺮوﺛﺎﻧﻴـﻪ اﺳـﺖ و
ﻧﺼﻒ ﺁن ٢٠ﻣﻴﮑﺮوﺛﺎﻧﻴﻪ ﺧﻮاهﺪ ﺷﺪ .اﮔـﺮ ار ﻣـﺪ Timer ١اﺳـﺘﻔﺎدﻩ ﮐﻨـﻴﻢ ،زﻣـﺎن ﻻزم ﺟﻬـﺖ اﺟـﺮا ﺷـﺪن
ﻣﺮاﺣﻞ ٢ ،۶ ،۵و ٣ﺣﺪود ١٠ﻣﻴﮑﺮوﺛﺎﻧﻴﻪ اﺳﺖ و در اﯾـﻦ ﻣـﺪت Timerﺧـﺎﻣﻮش اﺳـﺖ و زﻣـﺎن را اﻧـﺪازﻩ
ﮔﻴﺮﯼ ﻧﻤﯽ ﮐﻨﺪ .ﺑﻨﺎﺑﺮاﯾﻦ اﯾﻦ ١٠ﻣﻴﮑﺮوﺛﺎﻧﻴﻪ ﺧﻄﺎ ﻣﺤﺴﻮب ﻣﯽ ﺷﻮد .از ﺁﻧﺠﺎ ﮐﻪ اﯾﻦ ﺧﻄـﺎ ﺑـﺎ ٢٠ﻣﻴﮑـﺮو
ﺛﺎﻧﻴﻪ ﻗﺎﺑﻞ ﻣﻘﺎﯾﺴﻪ اﺳﺖ و ﻓﺮﮐﺎﻧﺲ ﻣﻮج ﺣﺎﺻﻠﻪ را ﺑـﻪ ﺷـﺪت ﺗﻐﻴﻴـﺮ ﻣـﯽ دهـﺪ ) 16 KHzﺑـﻪ ﺟـﺎﯼ 25
(KHzﺑﻨﺎﺑﺮاﯾﻦ ﻧﻤﯽ ﺗﻮاﻧﻴﻢ از ﻣﺪ ١اﺳﺘﻔﺎدﻩ ﮐﻨﻴﻢ و ﺑﺎﯾﺪ از ﺧﺎﺻﻴﺖ Auto Reloadﻣـﺪ ٢ﺑﻬـﺮﻩ ﺑﺒـﺮﯾﻢ ﮐـﻪ
ﻣﻮﺟﺐ ﺣﺬف اﯾﻦ ﺧﻄﺎ ﻣﯽ ﺷﻮد.
ﺑﺮﻧﺎﻣﻪ زﯾﺮ اﺳﺘﻔﺎدﻩ از Timer 0را ﺑﺮاﯼ ﺗﻮﻟﻴﺪ ﻣﻮﺟﯽ ﺑﺎ ﻓﺮﮐﺎﻧﺲ 25 KHzﻧﺸﺎن ﻣﯽ دهﺪ.
r
.i
s
r
e
k
a
lM
هﻤﺎن ﻃﻮر ﮐﻪ ﻣﯽ ﺑﻴﻨﻴﺪ ﺑﻪ هﻨﮕﺎم اﺳﺘﻔﺎدﻩ از ﻣﺪ ٢روﺷﻦ ﮐﺮدن Timerو ﻣﻘﺪار دهﯽ ﺑﻪ THﺗﻨﻬـﺎ ﯾـﮏ
ﺑﺎر اﻧﺠﺎم ﻣﯽ ﺷﻮد )ﺑﺮ ﺧﻼف ﻣﺪ (١
o
tr
وﻗﻔﻪ هﺎ
n
ﻓﺮض ﮐﻨﻴﺪ ﺑﺨﻮاهﻴﻢ در ﻣﺜﺎل » ٢هﻢ زﻣﺎن« دو ﻣﻮج ﻣﺮﺑﻌﯽ ﺗﻮﻟﻴﺪ ﮐﻨﻴﻢ .ﺑﺎ روﺷـﯽ ﮐـﻪ در ﺑـﺎﻻ اراوﻩ ﺷـﺪ
o
اﯾﻦ اﻣﺮ ﻣﻴﺴﺮ ﻧﻤﯽ ﺑﺎﺷﺪ .ﻋﻠﺖ ﺁﻧﺴﺖ ﮐﻪ ﺣﻠﻘﻪ ;) while (!TF0اﺟﺮاﯼ ﺑﺮﻧﺎﻣﻪ را در هﻤﺎن ﺧـﻂ ﻣﺘﻮﻗـﻒ
ﺧﻮاهﺪ ﮐﺮد و اﮔﺮ ) TF1ﻣﺮﺑﻮط ﺑﻪ ﻣﻮج ﻣﺮﺑﻌﯽ دوم( ﻗﺒﻞ از TF0ﯾﮏ ﺷﻮد ،ﺑﺮﻧﺎﻣﻪ ﭘﺎﺳﺦ ﻣﻨﺎﺳـﺐ ،ﯾﻌﻨـﯽ
.C
Notﮐﺮدن ﺑﻪ ﻣﻮﻗﻊ ﭘﻴﻦ ﺧﺮوﺟﯽ ﻣﺮﺑﻮط ﺑﻪ ﻣﻮج ﻣﺮﺑﻌﯽ دوم را ﺑﻪ ﯾﮏ ﺷﺪن ﺁن ﻧﻤﯽ دهﺪ.
ﺑﻨﺎﺑﺮاﯾﻦ ﻻزم اﺳﺖ روش دﯾﮕﺮﯼ را ﺑﺮاﯼ رﺳﻴﺪن ﺑﻪ اﯾﻦ ﻣﻨﻈﻮر ﺑﻪ ﮐﺎر ﺑﺒﺮﯾﻢ .ﻣﮑﺎﻧﻴﺴﻤﯽ ﮐـﻪ ﺑـﺮاﯼ ﺣـﻞ
w
اﯾﻦ ﻣﺸﮑﻞ ﺑﻪ ﮐﺎر ﻣﯽ رود وﻗﻔﻪ ﯾﺎ Interruptﻧﺎم دارد .وﻗﻔﻪ در واﻗﻊ ﺧﺒﺮ وﻗﻮع اﺗﻔﺎق ﻣﺸﺨﺼﯽ اﺳـﺖ
ﮐﻪ از ﺳﺨﺖ اﻓﺰار ﺑﻪ ﻧﺮم اﻓﺰار دادﻩ ﻣﯽ ﺷﻮد و ﻧـﺮم اﻓـﺰار ﻋﮑـﺲ اﻟﻌﻤـﻞ ﻣﻨﺎﺳـﺐ را ﺑـﻪ ﺁن ﻧـﺸﺎن ﻣـﯽ
w
دهﺪ.
w
ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ AT89C51داراﯼ ۵ﻣﻨﺒﻊ وﻗﻔﻪ ﻣﺨﺘﻠﻒ اﺳﺖ ﮐﻪ در اداﻣﻪ ﺑﻪ ﺑﺮرﺳﯽ ﺁﻧﻬﺎ ﺧﻮاهﻴﻢ ﭘﺮداﺧـﺖ.
دو ﻋﺪد از اﯾﻦ وﻗﻔﻪ هﺎ ﺑﻪ Timerهﺎ اﺧﺘﺼﺎص دارﻧﺪ )هﺮ Timerﯾـﮏ وﻗﻔـﻪ( .هـﺮ وﻗﻔـﻪ داراﯼ ﯾـﮏ ISR
) (Interrupt Service Routineﻣﯽ ﺑﺎﺷﺪ ISR .هﺮ وﻗﻔﻪ ،ﺗﺎﺑﻌﯽ اﺳﺖ ﮐﻪ ﺑـﻪ هﻨﮕـﺎم وﻗـﻮع ﺁن ﺑـﻪ ﻃـﻮر
ﺧﻮدﮐﺎر اﺟﺮا ﻣـﯽ ﺷـﻮد .اﯾـﻦ ﺗـﺎﺑﻊ در واﻗـﻊ هﻤـﺎن ﭘﺎﺳـﺦ ﻧـﺮم اﻓـﺰار ﺑـﻪ ﺳـﺨﺖ اﻓـﺰار اﺳـﺖ .در زﺑـﺎن C
ﻣﺨــﺼﻮص ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮهــﺎ ،ﺗــﺎﺑﻊ وﻗﻔــﻪ ) (ISRﺑــﻪ وﺳــﻴﻠﻪ ﮐﻠﻤــﻪ Interruptو ﺷــﻤﺎرﻩ وﻗﻔــﻪ ﻣــﻮرد ﻧﻈــﺮ
ﻣﺸﺨﺺ ﻣﯽ ﺷﻮد .ﺷﻤﺎرﻩ وﻗﻔﻪ هﺎ در ٨٠۵١در ﺟﺪول زﯾﺮ ﻣـﺸﺨﺺ ﺷـﺪﻩ اﺳـﺖ .ﺟـﺪول زﯾـﺮ ﺷـﻤﺎرﻩ
هﺎﯼ ﻗﺮاردادﯼ ﺑﺮاﯼ وﻗﻔﻪ هﺎ را ﻧﺸﺎن ﻣﯽ دهﺪ .ﻣﺎ ﻓﻌﻼً ﺗﻨﻬﺎ ﺑﺎ وﻗﻔﻪ هـﺎﯼ ١و Timer) ٣هـﺎ( ﺳـﺮوﮐﺎر
دارﯾﻢ.
وﻗﻔﻪ هﺎ را ﻣﯽ ﺗﻮان ﻓﻌﺎل ﯾﺎ ﻏﻴﺮ ﻓﻌﺎل ﮐﺮد .ﻣﻤﮑﻦ اﺳﺖ ﺷﻤﺎ در ﻃﺮاﺣﯽ ﺧﺎﺻـﯽ ﺑـﻪ ﺑﻌـﻀﯽ وﻗﻔـﻪ هـﺎ
r
ﻧﻴﺎزﯼ ﻧﺪاﺷﺘﻪ ﺑﺎﺷﻴﺪ در اﯾﻦ ﺻﻮرت ﻣﯽ ﺗﻮاﻧﻴﺪ ﺁﻧﻬﺎ را ﻏﻴﺮ ﻓﻌﺎل ﮐﻨﻴﺪ .در ﻣﻘﺎﺑﻞ ﺑﺎﯾﺪ ﺗﻤﺎم وﻗﻔﻪ هﺎﯾﯽ ﮐﻪ
.i
ﻗﺼﺪ دارﯾﺪ ﻣﻮرد اﺳﺘﻔﺎدﻩ ﻗﺮار دهﻴﺪ را ﻓﻌﺎل ﮐﻨﻴﺪ .رﺟﻴﺴﺘﺮ IEﺑﺮاﯼ ﺗﻌﻴﻴﻦ اﯾﻨﮑﻪ ﮐﺪام وﻗﻔﻪ ﻓﻌﺎل و ﮐﺪام
ﯾﮏ ﻏﻴﺮ ﻓﻌﺎل ﺑﺎﺷﺪ اﺳﺘﻔﺎدﻩ ﻣﯽ ﺷﻮد.
s
رﺟﻴﺴﺘﺮ : IE
r
e
k
a
lM
Bit Purpose
در ﻣﻮرد ﺑﻴﺖ EAﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﺻﻔﺮ ﺑﻮدن اﯾﻦ ﺑﻴﺖ ،ﺗﻤﺎم وﻗﻔﻪ هﺎ را ﻏﻴﺮ ﻓﻌﺎل ﻣﯽ ﮐﻨﺪ ،اﻣّﺎ ﯾﮏ ﺑﻮدن ﺁن
ﺑﻪ ﺗﻨﻬﺎﯾﯽ وﻗﻔﻪ اﯼ را ﻓﻌﺎل ﻧﻤﯽ ﮐﻨﺪ ﺑﻠﮑﻪ ﻻزم اﺳﺖ ﺑﻴﺖ ﺧﺎص وﻗﻔﻪ ﻣﻮرد ﻧﻈﺮ ﻧﻴﺰ ﯾﮏ ﺷﻮد.
w
ﻣﺜﺎل : ٣
w
در اﯾﻦ ﻣﺜﺎل ﻗﺼﺪ دارﯾﻢ ﺑﺎ اﺳﺘﻔﺎدﻩ از Timerهﺎ دو ﻣﻮج ﻣﺮﺑﻌﯽ ﺑﺎ ﻓﺮﮐﺎﻧﺴﻬﺎﯼ 20 KHzو 10 KHzﺗﻮﻟﻴﺪ
ﮐﻨﻴﻢ .ﺑﺎ اﺳﺘﻔﺎدﻩ از وﻗﻔﻪ هﺎ »ﺑﻪ ﻧﻈﺮ ﻣﯽ رﺳﺪ« ﮐﻪ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ دو ﮐﺎر را هﻤﺰﻣﺎن اﻧﺠﺎم ﻣﯽ دهﺪ ،اﻣّﺎ
w
دو ﺗﺎﺑﻊ ISRهﻴﭻ ﺟﺎ در ﻃﻮل ﺑﺮﻧﺎﻣﻪ ﻓﺮاﺧﻮاﻧﯽ ﻧﺸﺪﻩ اﻧﺪ .در ﺻﻮرﺗﯽ ﮐﻪ ﺳﻌﯽ ﮐﻨﻴﺪ ﯾـﮏ ISRرا )ﮐـﻪ ﺑـﺎ
tr
ﮐﻠﻤﻪ Interruptﻣﺸﺨﺺ ﻣﯽ ﺷﻮد( در ﺑﺮﻧﺎﻣﻪ ﻓﺮاﺧﻮاﻧﯽ ﮐﻨﻴﺪ ﮐﺎﻣﭙـﺎﯾﻠﺮ ﭘﻴﻐـﺎم ﺧﻄـﺎﯾﯽ ﻧﻤـﺎﯾﺶ ﺧﻮاهـﺪ
داد! ﯾﮏ ﺗﺎﺑﻊ ISRﺗﻮﺳﻂ ﺳﺨﺖ اﻓﺰار و ﺑﻪ ﻃﻮر ﺧﻮدﮐﺎر ﻓﺮاﺧﻮاﻧﯽ ﻣﯽ ﺷﻮد .ﺑﺮ ﺧـﻼف ﺗﻮاﺑـﻊ ﻣﺘـﺪاول ﮐـﻪ
ﺗﻮﺳﻂ ﻧﺮم اﻓﺰار )در ﻃﻮل ﺑﺮﻧﺎﻣﻪ( ﻓﺮاﺧﻮاﻧﯽ ﻣﯽ ﺷﻮﻧﺪ.
n
در اﯾﻦ ﺑﺮﻧﺎﻣﻪ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ دو ﻣﻮج ﻣﺮﺑﻌﯽ ﺗﻮﻟﻴﺪ ﻣﯽ ﮐﻨﺪ اﻣّﺎ ﺗـﺎﺑﻊ mainﻋﻤـﻼً ﮐـﺎرﯼ اﻧﺠـﺎم ﻧﻤـﯽ دهـﺪ.
o
ﭼﻨﺪ دﺳﺘﻮر اول ﺗﻨﻄﻴﻤﺎﺗﯽ هﺴﺘﻨﺪ ﮐﻪ ﻇﺮف ﭼﻨﺪ ﻣﻴﮑﺮوﺛﺎﻧﻴﻪ اﺟﺮا ﻣﯽ ﺷﻮﻧﺪ و ﺳﭙﺲ ﺣﻠﻘﻪ ;)while (1
.C
ﺗﺎﺑﻊ mainرا ﻣﻌﻠﻖ ﻧﮕﺎﻩ ﻣﯽ دارد .اﯾﻦ ﻧﻴﺰ ﺑﻪ ﺧﺎﻃﺮ اﺳﺘﻔﺎدﻩ از Interruptاﺳﺖ.
w
وﻗﻔﻪ ﺧﺎرﺟﯽ
هﻤﺎﻧﻄﻮر آﻪ ﺗـﺎ آﻨـﻮن ﺗﻮﺿـﻴﺢ دادﻩ ﺷـﺪ ،ﻓﺮاﺧـﻮاﻧﻲ ﺧﻮدآـﺎر ISRﻣﺮﺑـﻮط ﺑـﻪ هـﺮ وﻗﻔـﻪ ﺳـﺒﺐ ﻣـﻲ ﺷـﻮد آـﻪ
w
ﻣﻴﻜﺮوآﻨﺘﺮﻟﺮ ﺑﺘﻮاﻧﺪ ﭼﻨﺪ آﺎر را ﺑﻪ ﻃﻮر هﻤﺰﻣﺎن اﻧﺠﺎم دهﺪ .در واﻗﻊ ﻣﻴﻜﺮوآﻨﺘﺮﻟﺮ در هﺮ ﻟﺤﻈﻪ ﺗﻨﻬﺎ ﻳﻚ آﺎر اﻧﺠـﺎم
ﻣﻲ دهﺪ ،اﻣّﺎ ﺑﻪ ﺧﺎﻃﺮ ﺳﺮﻋﺖ زﻳﺎد اﺟﺮاي ﺑﺮﻧﺎﻣﻪ )ﺣﺪود ﻧﻴﻢ ﻣﻴﻠﻴﻮن دﺳﺘﻮر در ﺛﺎﻧﻴﻪ( اﻳﻨﻄﻮر ﺑﻪ ﻧﻈﺮ ﻣﻲ رﺳﺪ
w
وﻗﻔﻪ ﺧﺎرﺟﻲ ﺑﻪ ﻣﻴﻜﺮوآﻨﺘﺮﻟﺮ اﺟﺎزﻩ ﻣﻲ دهﺪ آﻪ در آﻨﺎر آﺎرهﺎي دﻳﮕﺮي آﻪ اﻧﺠﺎم ﻣﻲ دهـﺪ از وﻗـﻮع "اﺗﻔـﺎق"
ﻣﺸﺨﺼﻲ در دﻧﻴﺎي ﺧﺎرج ﻧﻴﺰ "ﺑﺎ آﻤﻚ ﻳﻚ وﻗﻔـﻪ" ﻣﻄﻠـﻊ ﺷـﻮد .در ﺳـﺎدﻩ ﺗـﺮﻳﻦ ﺣﺎﻟـﺖ اﻳـﻦ اﺗﻔـﺎق ﻣـﻲ ﺗﻮاﻧـﺪ
ﻓﺸﺮدﻩ ﺷﺪن ﻳﻚ آﻠﻴﺪ ﺑﺎﺷﺪ.
دو ﭘﺎﻳﻪ از ﭘﺎﻳﻪ هﺎي ﻣﻴﻜﺮوآﻨﺘﺮﻟﺮ ﺑﻪ ﻧﺎﻣﻬﺎي INT0و INT1ﻣﺮﺑﻮط ﺑﻪ دو وﻗﻔﻪ ﺧﺎرﺟﻲ هﺴﺘﻨﺪ .اﯾﻦ وﻗﻔـﻪ
هﺎ ﻣﯽ ﺗﻮاﻧﻨﺪ در دو ﺣﺎﻟﺖ ﺣﺴﺎس ﺑﻪ ﻟﺒﻪ و ﺣﺴﺎس ﺑﻪ ﺳﻄﺢ ﮐﺎر ﮐﻨﻨﺪ.
در ﺣﺎﻟﺖ ﺣﺴﺎس ﺑﻪ ﻟﺒﻪ اﮔﺮ ﺳﻄﺢ ﻣﻨﻄﻘﻲ اﻳﻦ ﭘﻴﻦ هﺎ از ﻳﻚ ﺑﻪ ﺻﻔﺮ ﺗﻐﻴﻴﺮ آﻨﺪ )از ۵وﻟـﺖ ﺑـﻪ ٠وﻟـﺖ(
ﻳﻚ وﻗﻔﻪ رخ ﺧﻮاهﺪ داد .اﯾﻦ ﺗﻐﻴﺮ ﺳﻄﺢ را اﺻﻄﻼﺣﺎً ﻟﺒﻪ ﮔﻮﯾﻨﺪ .در واﻗﻊ وﻗﻔﻪ ﺑﺎ ﯾﮏ ﻟﺒﻪ ﻣﻨﻔﯽ )ﮔﺬز ١ﺑـﻪ
(٠اﺟﺮا ﻣﯽ ﺷﻮد.
وﻗﻔﻪ ﺣﺴﺎس ﺑﻪ ﺳﻄﺢ ﺑﺎ ﺻﻔﺮ ﺷﺪن ﺳﻄﺢ ﻣﻨﻄﻘﯽ رخ ﻣﯽ دهﺪ و ﺗﺎ زﻣﺎﻧﯽ ﮐﻪ وﻟﺘﺎژ اﻋﻤﺎل ﺷـﺪﻩ ﺑـﻪ
ﭘﺎﯾﻪ وﻗﻔﻪ ﺻﻔﺮ ﺑﺎﺷﺪ ISRوﻗﻔﻪ ﺧﺎرﺟﯽ ﭘﯽ در ﭘﯽ اﺟﺮا ﺧﻮاهﺪ ﺷﺪ.
ﻣﺜﺎل : ۴
r
.i
در اﯾﻦ ﻣﺜﺎل ﻗﺼﺪ دارﯾﻢ ﻣﺪارﯼ ﺑﺎ دو ﺧﺮوﺟﯽ ﻃﺮاﺣﯽ ﮐﻨﻴﻢ ﮐﻪ هﺮ ﺧﺮوﺟﯽ ﯾﮏ ﻣﻮج ﻣﺮﺑﻌـﯽ ﺗﻮﻟﻴـﺪ ﻣـﯽ
ﮐﻨـﺪ) .اﻟﺒﺘــﻪ ﺑــﺎ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟــﺮ ﮐﺎرهـﺎﯼ زﯾــﺎدﯼ ﻣــﯽ ﺗــﻮان اﻧﺠــﺎم داد و ﺗﻮﻟﻴـﺪ ﻣــﻮج ﻣﺮﺑﻌــﯽ ﺗﻨﻬــﺎ ﮐــﺎرﺑﺮد ﺁن
s
ﻧﻴﺴﺖ!!( اﯾﻦ ﻣﺪار دو ﮐﻠﻴﺪ دارد ﮐﻪ در ﺣﮑﻢ ﮐﻠﻴﺪ ON/OFFﺧﺮوﺟﯽ هﺎ هﺴﺘﻨﺪ.
r
ﻣﺪار زﯾﺮ اﺗﺼﺎل ﮐﻠﻴﺪ هﺎ را ﺑـﺮاﯼ وﻗﻔـﻪ دادن ﺑـﻪ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟـﺮ ﻧـﺸﺎن ﻣـﯽ دهـﺪ .ﻣـﺴﺘﻄﻴﻞ هـﺎ ﻣﻘﺎوﻣـﺖ
e
هﺴﺘﻨﺪ!! وﻗﺘﯽ ﮐﻠﻴﺪ ﻗﻄﻊ اﺳﺖ ﺑﻪ ﻋﻠﺖ ﻧﺎ ﭼﻴﺰ ﺑـﻮدن ﺟﺮﯾـﺎن ورودﯼ ﭘﺎﯾـﻪ INTxوﻟﺘـﺎژ دو ﺳـﺮ ﻣﻘﺎوﻣـﺖ
ﺻﻔﺮ اﺳﺖ ،ﺑﻨﺎﺑﺮاﯾﻦ ﭘﺎﯾﻪ INTxﯾﮏ ﺧﻮاهﺪ ﺑﻮد .زﻣـﺎﻧﯽ ﮐـﻪ ﮐﻠﻴـﺪ وﺻـﻞ اﺳـﺖ ﭘﺎﯾـﻪ INTxﻣـﺴﺘﻘﻴﻤﺎً ﺑـﻪ
k
زﻣﻴﻦ وﺻﻞ ﻣﯽ ﺷﻮد و اﯾﻦ ﭘﺎﯾﻪ ﺻﻔﺮ ﻣﯽ ﺷﻮد .ﭘﺲ ﻓﺸﺮدن ﮐﻠﻴﺪ ﺳﺒﺐ اﯾﺠﺎد ﯾﮏ ﮔﺬر از ﯾﮏ ﺑﻪ ﺻﻔﺮ ﯾﺎ
a
ﯾﮏ ﻟﺒﻪ ﻣﻨﻔﯽ ) ١ﺑﻪ (٠روﯼ ﭘﺎﯾﻪ INTxﻣﯽ ﺷﻮد .اﮔﺮ وﻗﻔﻪ را در وﺿﻌﻴﺖ ﺣـﺴﺎس ﺑـﻪ ﻟﺒـﻪ ﻗـﺮار دهـﻴﻢ
ﻓﺸﺮدن ﮐﻠﻴﺪ ﺳﺒﺐ اﺟﺮا ﺷﺪن وﻗﻔﻪ ﻣﯽ ﺷﻮد .اﻣﺎ وﺻﻞ ﻧﮕﻪ داﺷﺘﻦ ﺁن ﺗﺄﺛﻴﺮﯼ ﻧﺪارد .زﯾـﺮا ﻟﺒـﻪ دﯾﮕـﺮﯼ
lM اﯾﺠﺎد ﻧﻤﯽ ﮐﻨﺪ.
o
tr
n
o
.C
w
w
w
ﺑﺮﻧﺎﻣﻪ زﯾﺮ ﻋﻤﻞ ﻣﻮرد ﻧﻈﺮ را اﻧﺠﺎم ﺧﻮاهﺪ داد.
r
.i
s
r
e
k
a
lM
o
tr
n
o
.C
w
ﺗﻮﺿﻴﺢ :ﺑﻴﺘﻬﺎﯼ IT0و IT1ﺣﺴﺎس ﺑﻪ ﻟﺒﻪ ﯾﺎ ﺳﻄﺢ ﺑﻮدن وﻗﻔﻪ را ﺗﻌﻴﻴﻦ ﻣﯽ ﮐﻨﻨـﺪ .در اﺑﺘـﺪا Timerهـﺎ
روﺷﻦ ﻧﺸﺪﻩ اﻧﺪ .زﯾﺮا در ﺗﺎﺑﻊ TRx mainﻣﻘﺪار دهﯽ ﻧﺸﺪﻩ و ﻣﻘﺪار ﭘﻴﺶ ﻓﺮض ﺁن ﺻﻔﺮ اﺳﺖ .ﺑﻨﺎﺑﺮاﯾﻦ
w
Timerهﺎ ﺧﺎﻣﻮﺷﻨﺪ و ﺳﺮرﯾﺰﯼ رخ ﻧﻤﯽ دهﺪ .از اﯾﻦ رو وﻗﻔﻪ هﻢ اﺗﻔﺎق ﻧﻤﯽ اﻓﺘﺪ ISR .ﻧﻴـﺰ اﺟـﺮا ﻧﻤـﯽ
ﺷﻮد و از ﻣﻮج ﻣﺮﺑﻌﯽ ﺧﺒﺮﯼ ﻧﻴﺴﺖ.
w
ﺑﺎ ﻓﺸﺮدن هﺮ ﮐﻠﻴﺪ ﯾﮑﯽ از وﻗﻔﻪ هﺎﯼ ﺧـﺎرﺟﯽ اﺟـﺮا ﻣـﯽ ﺷـﻮﻧﺪ و ﺑﻴـﺖ TRxرا ﺗﻐﻴﻴـﺮ ﻣـﯽ دهﻨـﺪ .اﮔـﺮ
Timerهﺎ ﺧﺎﻣﻮش ﺑﺎﺷﻨﺪ روﺷﻦ ﻣﯽ ﺷﻮﻧﺪ )و ﺑﺎﻟﻌﮑﺲ( .ﺑﺎ روﺷﻦ ﺷﺪن هﺮ Timerﻣﻮج ﻣﺮﺑﻌﯽ ﻣﺮﺑﻮط
ﺑﻪ ﺁن روﯼ ﭘﺎﯾﻪ ﻣﺮﺑﻮﻃﻪ ﻇﺎهﺮ ﺧﻮاهﺪ ﺷﺪ.