اين همون كدي هست كه اميد زده ، منتها در سطح ريجستر. امشب حس كاري نبود ، گفتم اينا رو بذارم ، شايد مفيد باشه.
كدها رو كامپايل نكردم ، اما بايد درست باشن
( يه تستي بزنيد )
در خود كدها كمي توضيحات داده شده ، كه با توجه به توضيحات قبلي و توضيحات اميد نبايد مشكلي باشه.
و يه توضيح در مورد ريجسترهاي PIO براي sam7 :
در AVR يه ريجستر 8 بيتي داريم كه اگر هر كدوم از بيت هاش رو 0 و يا 1 كنيم ، به ترتيب پايه ي مربوطه كه جزء اون پورت مي شه 0 و يا 1 مي شه. اما در ARM اينطوري نيست!
يك ريجستر 32 بيتي به نام SODR هست ، كه هر كدوم از بيت هاش رو 1 كني ، پايه ي مربوطه 1 مي شه. حالا اگر همون بيت رو 0 كني چي مي شه؟! جواب اينه : هيچي نمي شه ! و اون پايه همچنان 1 مي مونه!
حالا براي 0 كردن پايه بايد چكار كنيم ؟
يه ريجستر 32 بيتي ديگه هست به نام CODR ، بيت مربوط به پايه اي كه مي خواهيم 0 اش كنيم رو در اين ريجستر 1 مي كنيم!
جالبه، نه؟!
معمولا ريجسترهاي ARM ، سه تايي هستن. يه ريجستر 32 بيتي براي set كردن + يك ريجستر 32 بيتي براي Clear كردن كه هم اين و هم قبلي Write only هستند + يك ريجستر 32 بيتي كه وضعيت 0 و 1 بودن پايه ها رو نشون مي ده و Read only هست.
از اين ريجسترها براي PIO كلي دارهه ... ، كه 2تاي ديگه رو هم در ادامه مي گم.
كد اولي به روش بالاست.
همينطور كه ديديد مقدار دهيه اينطوري به ريجسترهاي PIO براي بعضي كاربردها اذيت مي كنه...
چه كنيم كه با 0 كردن بيت ، پايه ي مربوطه 0 و با 1 كردن اون بيت در همون ريجستر ، بيت مربوطه 1 بشه ؟
كافيه ريجستر OWER رو براي پايه هاي مورد نظر فعال كنيم. با اين كار اجازه ي همچين كاري رو داريم!
حالا با 0 و 1 كردن هر پايه در ريجستر ODSR ، پايه هاي مربوطه رو مي تونيم مستقيم 0 و 1 كنيم.
كد دوم هم به اين روش زده شدهه.
اسم ريجسترها خيلي خوب انتخاب شده و راحت مي شه يادشون گرفت :
SODR : Set Output Data Register
CODR : Clear Output Data Rigester
OWER : Output Write Enable Register
ODSR : Output Data Status Register
براي مقدار دهي ريجسترهاي واحد PMC از الگوي زير استفاده مي كنيم ، كه با اين كار داريم به آدرس مورد نظر از اين واحد اشاره مي كنيم.
کد php:
AT91C_BASE_PMC->PMC_XXX=0Xyy;
اسم ريجستر مربوطه رو جاي XXX مي نويسيم.
براي مقدار دهي به PIO ها از الگوي زير استفاده مي كنيم، باز داريم اشاره مي كنيم. اين علامت " <- " كار اشاره رو انجام مي دهه ...
کد php:
AT91C_BASE_PIOA->PIO_XXX=0Xyy;
AT91C_BASE_PIOB->PIO_XXX=0Xyy;
اسم ريجستر مربوطه رو جاي XXX مي نويسيم.
در كدهاي پايين به نحوه ي مقدار دهيه ريجستر ها كه به اين سبك هست دقت كنيد " x<<y " كه بسيار معروف و پر كاربرد هست. دقيقا بيت مورد نظر رو 0 يا 1 مي كنه و نيازي به MASK كردن بين هاي اون ريجستر و and و ... هم نيست !
در برنامه هاي واقعي و درست و حسابي قدرش رو خواهيد فهميد.
اين الگو ، x رو به تعداد y بار به سمت چپ شيفت مي ده ... .
اين كد1:
کد php:
#include <Atmel/ioat91sam7x256.h>
#include <delay.h>
// configuration as output
AT91C_BASE_PMC->PMC_PCER=(1<<AT91C_ID_PIOB); /* Enable Clk for PIOB
PCER : Pio Clock Enable Register */
// config following pins as PIO ; PER : Pio Enable Register
AT91C_BASE_PIOB->PIO_PER=(1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7);
// Config following pins as output ; OER : Otput Enable Register
AT91C_BASE_PIOB->PIO_OER=(1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7);
// End of configuration
int main(void)
{
while(1) // Infinite loop
{
AT91C_BASE_PIOB->PIO_CODR=0xaa; // CODR : Clear Output Data Rigester
delay_ms(50);
AT91C_BASE_PIOB->PIO_SODR=0xaa; // SODR : Set Output Data Register
delay_ms(50);
AT91C_BASE_PIOB->PIO_CODR=0x55;
delay_ms(50);
AT91C_BASE_PIOB->PIO_SODR=0x55;
delay_ms(50);
}
}
اين كد2:
کد php:
#include <Atmel/ioat91sam7x256.h>
#include <delay.h>
AT91C_BASE_PMC->PMC_PCER=(1<<AT91C_ID_PIOB);
AT91C_BASE_PIOB->PIO_PER=(1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7);
AT91C_BASE_PIOB->PIO_OER=(1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7);
// OWER : Output Write Enable Register
AT91C_BASE_PIOB->PIO_OWER=(1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7);
int main(void)
{
while(1)
{
AT91C_BASE_PIOB->PIO_ODSR=0xaa; // ODSR : Output Data Status Register
delay_ms(50);
AT91C_BASE_PIOB->PIO_ODSR=0x00; // 0 -> 0 & 1 -> 1
delay_ms(50);
AT91C_BASE_PIOB->PIO_ODSR=0x55;
delay_ms(50);
AT91C_BASE_PIOB->PIO_ODSR=0x00;
delay_ms(50);
}
}
اميدوارم با اين توضيحات تونسته باشم BackGround مناسبي براي ادامه بهتون داده باشم.
موفق باشيد.