You are on page 1of 13

‫ارﺗﺒﺎط ﺳﺨﺖ اﻓﺰار ﺑﺎ ﻧﺮم اﻓﺰار‬

‫هﺮ دﺳﺘﮕﺎﻩ ﺑﺮﻧﺎﻣﻪ ﭘﺬﯾﺮ )ﻣﺎﻧﻨﺪ ﯾﮏ ﮐﺎﻣﭙﻴﻮﺗﺮ ﯾﺎ ﯾﮏ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ( داراﯼ دو ﺑﺨـﺶ اﺻـﻠﯽ اﺳـﺖ ‪ :‬ﺳـﺨﺖ‬
‫اﻓﺰار و ﻧﺮم اﻓﺰار‪ .‬ﺑﺎ ﭼﻴﺴﺘﯽ اﯾﻦ دو ﺑﺨﺶ ﮐﻢ و ﺑﻴﺶ ﺁﺷﻨﺎ هﺴﺘﻴﻢ‪.‬‬

‫ﻧﮑﺘﻪ ﺑﺴﻴﺎر ﻣﻬﻢ و در ﻋﻴﻦ ﺣﺎل ﺳﺎدﻩ اﯼ ﮐﻪ ﺑﺎﯾﺪ ﺑﻪ ﺁن ﺗﻮﺟﻪ ﮐﺮد ﻧﺤﻮﻩ ﺑﺮﻗﺮارﯼ ارﺗﺒﺎط ﺑﻴﻦ ﺳﺨﺖ اﻓﺰار‬
‫و ﻧﺮم اﻓﺰار در ﯾﮏ ﻣﻴﮑﺮو ﮐﻨﺘﺮﻟﺮ اﺳﺖ‪.‬‬

‫ﺑﺎﯾﺪ راهﯽ وﺟﻮد داﺷﺘﻪ ﺑﺎﺷﺪ ﮐﻪ دﺳﺘﻮراﺗﯽ ﮐﻪ ﻧﺮم اﻓﺰار ﺻﺎدر ﻣﯽ ﮐﻨﺪ‪ ،‬ﺑﻪ ﺳﺨﺖ اﻓﺰار ﻣﻨﺘﻘﻞ ﺷﻮد ﺗﺎ‬

‫‪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‬‬

‫ﺑﺮﻧﺎﻣﻪ زﯾﺮ‪ ،‬ﻋﻤﻞ ﻣﻮرد ﻧﻈﺮ را اﻧﺠﺎم ﺧﻮاهﺪ داد‪.‬‬


‫‪o‬‬
‫‪tr‬‬
‫‪n‬‬
‫‪o‬‬
‫‪.C‬‬
‫‪w‬‬
‫‪w‬‬
‫‪w‬‬

‫ﻧﮑﺘﻪ ﻣﻬﻢ ‪ :‬ﻗﺒﻞ از اﯾﻨﮑﻪ ﺑﺘﻮاﻧﻴﻢ از ﯾﮑﯽ از ﭘﺎﯾﻪ هﺎﯼ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ﺑﻪ ﻋﻨﻮان ورودﯼ اﺳﺘﻔﺎدﻩ ﮐﻨـﻴﻢ‪ ،‬ﻻزم‬
‫اﺳﺖ اﺑﺘﺪا هﻤﺎن ﭘﻴﻦ را ﯾﮏ ﮐﻨﻴﻢ‪ .‬اﯾﻦ ﻋﻤﻞ ﭘﺎﯾﻪ ﻣﻮرد ﻧﻈﺮ را ﺁﻣﺎدﻩ درﯾﺎﻓﺖ ورودﯼ ﻣﯽ ﮐﻨﺪ‪.‬‬
‫‪ Timer‬هﺎ‬

‫ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ ‪ AT89C51‬داراﯼ دو ‪ Timer‬اﺳﺖ ﮐﻪ ﻣﯽ ﺗﻮاﻧﻨﺪ ﺑﻪ ﺻﻮرت ﻣـﺴﺘﻘﻞ از هـﻢ‪ ،‬ﺑـﺮاﯼ ﺳـﻨﺠﺶ‬


‫ﺑﺎزﻩ هﺎﯼ زﻣﺎﻧﯽ ﻣﻮرد اﺳﺘﻔﺎدﻩ ﻗﺮار ﮔﻴﺮﻧﺪ‪.‬‬

‫ﭼﮕﻮﻧﮕﯽ ﻋﻤﻠﮑﺮد ‪ 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‬در ﺣﻮزﻩ آﺎري ﻣﺎ( آﺎﻣﻼً ﻣﺸﺎﺑﻬﻨﺪ‪.‬‬


‫‪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‬در ﻣﺪ ‪١‬‬


‫‪tr‬‬

‫‪ Timer‬در ﻣﺪ ‪ ١‬از ﺗﻤﺎم ‪ ١۶‬ﺑﻴﺖ ﺧﻮد ﺑﺮاي ﺷﻤﺎرش اﺳﺘﻔﺎدﻩ ﻣﻲ آﻨﺪ‪ .‬ﻳﻌﻨـﻲ ﺑﺰرﮔﺘـﺮﻳﻦ ﻋـﺪد در ‪Timer‬‬
‫ﻣﻲ ﺗﻮاﻧﺪ‪ 65535‬ﺑﺎﺷﺪ‪ .‬ﻧﺘﻴﺠﺘﺎً ﻃﻮﻻﻧﻲ ﺗﺮﻳﻦ ﺗﺄﺧﻴﺮي آـﻪ ‪ Timer‬در ﻣـﺪ ‪ ١‬ﻣـﻲ ﺗﻮاﻧـﺪ ﺑـﻪ ﺗﻨﻬـﺎﻳﻲ اﻳﺠـﺎد‬
‫آﻨﺪ‪ ،‬آﻤﻲ ﺑﻴﺶ از ‪ ۶۵‬ﻣﻴﻠﻲ ﺛﺎﻧﻴﻪ اﺳﺖ‪ .‬در اﻳﻦ ﻣﺪ‪ ،‬هﺮ ﺑﺎر آـﻪ ‪ Timer‬ﺳـﺮرﻳﺰ ﻣـﻲ ﺷـﻮد‪ ،‬ﺑﺎﻳـﺪ ﻣﻘـﺪار‬
‫‪n‬‬

‫ﻣﻮرد ﻧﻈﺮ را دوﺑﺎرﻩ در ﺁن ‪ Load‬آﺮد‪ .‬اﻳﻦ ﻋﻤﻞ ﻧﻴﺎز ﺑﻪ ﭼﻨﺪ ﻣﻴﻜﺮوﺛﺎﻧﻴﻪ زﻣﺎن دارد و زﻣﺎﻧﻲ آﻪ ﺑـﺎزﻩ زﻣـﺎﻧﻲ‬
‫ﻣﻮرد ﻧﻈﺮ آﻮﭼﻚ ﺑﺎﺷﺪ )ﻣﺜﻼً ﺗﻮﻟﻴﺪ ﻣﻮج ‪ (100 KHz‬اﻳﻦ ﻣﺴﺌﻠﻪ دﻗﺖ را آﺎهﺶ ﻣﻲ دهﺪ‪) .‬ﻣﺜﻼً ﺑـﻪ ﺟـﺎي‬
‫‪o‬‬

‫‪ 80 KHz ،100 KHz‬ﺧﻮاهﺪ ﺷﺪ(‬


‫‪.C‬‬
‫‪w‬‬
‫‪w‬‬
‫‪w‬‬
‫ﻋﻤﻠﻜﺮد ‪ Timer‬در ﻣﺪ ‪٢‬‬

‫اﻳﻦ ﻣﺪ ﻣﺸﻜﻠﻲ آﻪ در ﻣﻮرد ﻣﺪ ‪ ١‬ﻣﻮرد ﺑﺤﺚ ﻗﺮار ﮔﺮﻓﺖ را ﺑﺮﻃﺮف ﻣﻲ آﻨﺪ‪ .‬در ﻣﺪ ‪ ،٢‬ﺗﻨﻬﺎ هـﺸﺖ ﺑﻴـﺖ‬
‫از ‪ 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‬‬


‫‪o‬‬

‫ﭘﻴﺶ از ﺁﻧﻜﻪ از ‪ Timer‬هﺎ اﺳﺘﻔﺎدﻩ آﻨﻴﻢ ﻻزم اﺳـﺖ اﺑﺘـﺪا ‪ Timer‬را ﺑـﺮاي آـﺎر در ﻣـﺪ ﻣـﻮرد ﻧﻈـﺮ ﺗﻨﻈـﻴﻢ‬
‫‪.C‬‬

‫آﻨﻴﻢ‪ .‬ﻋﻼوﻩ ﺑﺮ ﺗﻌﻴﻴﻦ ﻣﺪ ﺗﻨﻈﻴﻤﺎت دﻳﮕﺮي ﻧﻴﺰ ﻻزم اﺳﺖ آﻪ در زﻳﺮ ﺷﺮح دادﻩ ﻣﻲ ﺷﻮد‪.‬‬

‫رﺟﻴﺴﺘﺮ ‪: (Timer MODe) TMOD‬‬


‫‪w‬‬
‫‪w‬‬
‫‪w‬‬

‫ﺷﺮح ﮐﺎر اﯾﻦ ﺑﻴﺘﻬﺎ در ﺟﺪول زﯾﺮ ﺁﻣﺪﻩ اﺳﺖ‪ .‬ﺑﻴﺘﻬﺎﯼ ‪ GATE‬و ‪) C/T‬ﺑﻴﺘﻬﺎﯼ ‪ ١‬و ‪ ٢‬و ‪ ۶‬و ‪ (٧‬ﻓﻌﻼً ﺑﺮاﯼ ﻣـﺎ‬
‫ﮐﺎرﺑﺮدﯼ ﻧﺪارﻧﺪ‪.‬‬
Bit Bit Name Purpose Timer

7 GATE1 1 Timer works only if INT1 (P3.3) is set T1


0 Timer works regardless of INT1 (P3.3)

6 C/T1 1 Timer counts impulses on T1 (P3.5) T1


0 Timer counts impulses of internal oscillator

5 T1M1 Timer mode T1

4 T1M0 Timer mode T1

3 GATE0 1 Timer works only if INT0 (P3.2) is set T0

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 CONtrol) TCON ‫رﺟﻴﺴﺘﺮ‬


n
o
.C

.‫ ﻣﺮﺑﻮط ﻣﯽ ﺷﻮﻧﺪ‬Timer ‫از ﻣﻴﺎن اﯾﻦ ﺑﻴﺘﻬﺎ ﺗﻨﻬﺎ ﭼﻬﺎر ﺑﻴﺖ ﺑﺎﻻ ﺑﻪ‬
w
w
w
‫ﺷﺮح ﮐﺎر اﯾﻦ ﺑﻴﺘﻬﺎ در ﺟﺪول زﯾﺮ ﺁﻣﺪﻩ اﺳﺖ‪.‬‬

‫‪Bit‬‬ ‫‪Bit Name‬‬ ‫‪Purpose‬‬ ‫‪Timer‬‬

‫‪7‬‬ ‫‪TF1‬‬ ‫‪This bit is automatically set in case‬‬ ‫‪T1‬‬


‫‪of overflow in Timer T1‬‬

‫‪6‬‬ ‫‪TR1‬‬ ‫‪1 - Timer T1 is on‬‬ ‫‪T1‬‬


‫‪0 - Timer T1 is off‬‬

‫‪5‬‬ ‫‪TF0‬‬ ‫‪This bit is automatically set in case‬‬ ‫‪T0‬‬


‫‪of overflow in Timer T0‬‬

‫‪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‬‬

‫ﻣﻨﺘﻈﺮ ﺑﻤﺎﻧﻴﺪ ﺗﺎ ﺑﻴﺖ ‪ (TFx) Overflow‬ﯾﮏ ﺷﻮد‪.‬‬ ‫‪.۴‬‬


‫‪ Timer‬را ﻣﺘﻮﻗﻒ ﮐﻨﻴﺪ‪.‬‬ ‫‪.۵‬‬
‫‪tr‬‬

‫ﺑﻴﺖ ﺳﺮرﯾﺰ ا ﺻﻔﺮ ﮐﻨﻴﺪ‪ ،‬ﺗﺎ در ﺳﺮرﯾﺰ ﺑﻌﺪﯼ ﯾﮏ ﺷﺪن ﺁن ﻗﺎﺑﻞ ﺗﺸﺨﻴﺺ ﺑﺎﺷﺪ‪.‬‬ ‫‪.۶‬‬
‫ﺑﻪ ﻣﺮﺣﻠﻪ ‪ ٢‬ﺑﺎز ﮔﺮدﯾﺪ‪.‬‬ ‫‪.٧‬‬
‫‪n‬‬

‫ﺑﺮﻧﺎﻣﻪ رﯾﺰﯼ ‪ Timer‬در ﻣﺪ ‪٢‬‬


‫‪o‬‬
‫‪.C‬‬

‫ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ اﯾﻨﮑﻪ هﺮ ‪ Timer‬را در ﭼﻪ ﻣﺪﯼ اﺳﺘﻔﺎدﻩ ﺧﻮاهﻴﺪ ﮐﺮد‪ .‬ﻣﻘﺪار ﻣﻨﺎﺳﺒﯽ در ‪ TMOD‬ﻗﺮار‬ ‫‪.١‬‬
‫دهﻴﺪ‪ GATE .‬و ‪ C/T‬را ﺻﻔﺮ ﮐﻨﻴﺪ‪.‬‬
‫رﺟﻴﺴﺘﺮ ‪ THx‬را ‪ Load‬ﮐﻨﻴﺪ‪ .‬ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ اﻣﮑﺎن ‪ Auto Reload‬ﻧﻴﺎزﯼ ﺑﻪ ‪ Load‬ﮐـﺮدن ‪ TLx‬ﻧـﺪارﯾﻢ‪.‬‬ ‫‪.٢‬‬
‫‪w‬‬

‫ﺑﻪ ﻣﺤﺾ روﺷﻦ ﺷﺪن ‪ Timer‬ﻣﻘﺪار درون ‪ THx‬ﺑﻪ ‪ TLx‬ﮐﭙﯽ ﺷﺪﻩ و ﺷﻤﺎرش ﺁﻏﺎز ﺧﻮاهﺪ ﺷﺪ‪.‬‬
‫‪ Timer‬را روﺷﻦ ﮐﻨﻴﺪ‪.‬‬ ‫‪.٣‬‬
‫ﻣﻨﺘﻈﺮ ﯾﮏ ﺷﺪن ‪ TFx‬ﺑﻤﺎﻧﻴﺪ‪.‬‬ ‫‪.۴‬‬
‫‪w‬‬

‫‪ TF‬را ﺻﻔﺮ ﮐﻨﻴﺪ‪.‬‬ ‫‪.۵‬‬


‫ﺑﻪ ﻣﺮﺣﻠﻪ ‪ ۴‬ﺑﺎز ﮔﺮدﯾﺪ‪.‬‬ ‫‪.۶‬‬
‫‪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‬‬ ‫‪Enables/disables all interrupt sources‬‬


‫‪o‬‬

‫‪ET2‬‬ ‫‪Timer T2 interrupt‬‬


‫‪tr‬‬

‫‪ES‬‬ ‫‪UART and SPI interrupts‬‬

‫‪ET1‬‬ ‫‪Timer T1 interrupt‬‬


‫‪n‬‬

‫‪EX1‬‬ ‫‪External interrupt: pin INT1‬‬

‫‪ET0‬‬ ‫‪Timer T0 interrupt‬‬


‫‪o‬‬

‫‪EX0‬‬ ‫‪External interrupt: pin INT0‬‬


‫‪.C‬‬

‫در ﻣﻮرد ﺑﻴﺖ ‪ EA‬ﺗﻮﺟﻪ ﮐﻨﻴﺪ ﮐﻪ ﺻﻔﺮ ﺑﻮدن اﯾﻦ ﺑﻴﺖ‪ ،‬ﺗﻤﺎم وﻗﻔﻪ هﺎ را ﻏﻴﺮ ﻓﻌﺎل ﻣﯽ ﮐﻨﺪ‪ ،‬اﻣّﺎ ﯾﮏ ﺑﻮدن ﺁن‬
‫ﺑﻪ ﺗﻨﻬﺎﯾﯽ وﻗﻔﻪ اﯼ را ﻓﻌﺎل ﻧﻤﯽ ﮐﻨﺪ ﺑﻠﮑﻪ ﻻزم اﺳﺖ ﺑﻴﺖ ﺧﺎص وﻗﻔﻪ ﻣﻮرد ﻧﻈﺮ ﻧﻴﺰ ﯾﮏ ﺷﻮد‪.‬‬
‫‪w‬‬

‫ﻣﺜﺎل ‪: ٣‬‬
‫‪w‬‬

‫در اﯾﻦ ﻣﺜﺎل ﻗﺼﺪ دارﯾﻢ ﺑﺎ اﺳﺘﻔﺎدﻩ از ‪ Timer‬هﺎ دو ﻣﻮج ﻣﺮﺑﻌﯽ ﺑﺎ ﻓﺮﮐﺎﻧﺴﻬﺎﯼ ‪ 20 KHz‬و ‪ 10 KHz‬ﺗﻮﻟﻴﺪ‬
‫ﮐﻨﻴﻢ‪ .‬ﺑﺎ اﺳﺘﻔﺎدﻩ از وﻗﻔﻪ هﺎ »ﺑﻪ ﻧﻈﺮ ﻣﯽ رﺳﺪ« ﮐﻪ ﻣﻴﮑﺮوﮐﻨﺘﺮﻟﺮ دو ﮐﺎر را هﻤﺰﻣﺎن اﻧﺠﺎم ﻣﯽ دهﺪ‪ ،‬اﻣّﺎ‬
‫‪w‬‬

‫در واﻗﻊ اﯾﻨﻄﻮر ﻧﻴﺴﺖ!‬


‫‪r‬‬
‫‪.i‬‬
‫‪s‬‬
‫‪r‬‬
‫‪e‬‬
‫‪k‬‬
‫‪a‬‬
‫‪lM‬‬
‫ﻧﮑﺘﻪ ﻣﻬﻢ ‪:‬‬
‫‪o‬‬

‫دو ﺗﺎﺑﻊ ‪ 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‬ﻣﻮج ﻣﺮﺑﻌﯽ ﻣﺮﺑﻮط‬
‫ﺑﻪ ﺁن روﯼ ﭘﺎﯾﻪ ﻣﺮﺑﻮﻃﻪ ﻇﺎهﺮ ﺧﻮاهﺪ ﺷﺪ‪.‬‬

You might also like