امتیاز موضوع:
  • 1 رأی - میانگین امتیازات: 4
  • 1
  • 2
  • 3
  • 4
  • 5
مشکل با adc
نویسنده پیام
salehjg آفلاین
مدیر بخش
*****

ارسال‌ها: 1,281
موضوع‌ها: 133
تاریخ عضویت: آذر ۱۳۸۸

تشکرها : 9560
( 8557 تشکر در 2603 ارسال )
ارسال: #1
مشکل با adc
سلام
حسابی کلافه شدم...

نمی تونم دلیل حالتی که باهاش روبرو هستم رو پیدا کنم...
چند تا سنسور هست که با ADC مدام پشت سر هم (با حداکثر سرعت ممکن) مقادیرشونو میگیرم...

سخت افزار هم اینطوره که هر هشت تا سنسور به ADC0 تا ADC7 وصل شده و هر هشت کانال ADC فعال شدن

اما بعضی وقتی(بصورت کاملا راندم) توی اون حلقه ی while گیر میکنه، دلیلش هم اینکه طبق مقدار رجیستر تنها چهار تا کانال اول ADC ، عملیات تبدیل شدن اشون تموم شده.... همون طور توی اون حلقه گیر میوفته....

فرکانس MCK مساوی 47923200 هرتزه

PRESCALER قسمت ADC ، چهار هه.... یعنی فرکانس ADC میشه MCK/10
resolution بصورت 10 بیت مقدار دهی شده
startup time رو 15 مقدار دهی کردم.
sample and hold رو برابر 13 مقدار دهی کردم....( این یکی توی گیر کردن تاثیر داره... وقتی 13 هه، کم تر گیر میکنه... اگه بیشتر بشه بعد 2 سه بار اسکن کردن سنسور ها، برنامه باز گیر میکنه)


اینم کد:

کد:
    //ADC init
            AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
                *AT91C_ADC_CR = 1; //soft reset      
                *AT91C_ADC_MR = (0x4<<8)|(15 <<16)|(13<<24); //startup time ----- sample & hold time        
                *AT91C_ADC_CHER = 0xff; //enabling all of channels    
                while(    *AT91C_ADC_CHSR & 0xff != 0xff)

-----------------------------------------------------------------
.
.
.
// in the function

                    PIO_Clear(buffer_select2)  ;   //sel1 = 001
                    PIO_Clear(buffer_select1)  ;
                    PIO_Set(buffer_select0)    ;
                    delay_us(2); //10
                    *AT91C_ADC_CR = 2; //start conversion
                //    delay_us(1);
                    while(((*AT91C_ADC_SR)&0xff)!=0xff);
                
                    front_ptr[0] = *AT91C_ADC_CDR0;
                    front_ptr[1] = *AT91C_ADC_CDR1;    
                    front_ptr[2] = *AT91C_ADC_CDR2;
                    front_ptr[3] = *AT91C_ADC_CDR3;
                    front_ptr[4] = *AT91C_ADC_CDR4;
                    front_ptr[5] = *AT91C_ADC_CDR5;
                    front_ptr[6] = *AT91C_ADC_CDR6;
                    front_ptr[7] = *AT91C_ADC_CDR7;
(آخرین ویرایش در این ارسال: ۱۵-شهریور-۱۳۹۲, ۰۲:۲۶:۳۸، توسط salehjg.)
۱۴-شهریور-۱۳۹۲, ۱۸:۱۱:۵۲
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : orange signal, babyy
sharin آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,053
موضوع‌ها: 28
تاریخ عضویت: مرداد ۱۳۸۹

تشکرها : 3714
( 8171 تشکر در 2772 ارسال )
ارسال: #2
RE: مشکل با adc
سلام.

توی خط زیر گیر می کنه؟
کد php:
while(((*AT91C_ADC_SR)&0xff)!=0xff); 

از نظر من این خط اشتباه هست!
همونطور که می دونی خط ها دونه دونه به ADC وصل می شن و تبدیلشون صورت می گیرهه و در هر لحظه یکی از بیت های EOCx یک می شه که پایان تبدیلش رو نشون می دهه.
یا دونه دونه باید بذاری تو while و بعد مقدار دهی کنی. یا باید از وقفه استفاده کنی.
و هر بار که به وقفه می ری ، یکی از خط ها تبدیلش تمام شده و باید بری برای خط بعدی.

موفق باشی.

۱۴-شهریور-۱۳۹۲, ۱۹:۴۲:۲۵
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : salehjg, babyy
salehjg آفلاین
مدیر بخش
*****

ارسال‌ها: 1,281
موضوع‌ها: 133
تاریخ عضویت: آذر ۱۳۸۸

تشکرها : 9560
( 8557 تشکر در 2603 ارسال )
ارسال: #3
RE: مشکل با adc
ممنون بابت پاسخ
آره تو همون خط گیر میکنه
یعنی هر بار که رجیستر وضعیت sr خونده میشه، بیت های مربوط به اتمام عملیات هر کانال اگر مثلا قبل خوندن 1 بود، بعد از خوندن صفر میشه؟ استدلال شما این بود؟
-----------------------------------------
حالا اگه بخوام با وقفه بنویسم، طبق استدلال بالا :) چطوری کنترل میشه؟ یعنی تابع وقفه چطور کنترلش میکنه؟ اگه رجیستر sr رو بخونه که باز همه ی 1 ها 0 میشن..( eoc ها)

مثلا اگه توی enable interrupt reg ، هر هشت تا eoc رو 1 کنم، زمانی که هر 8 تا کانال کارشون تموم شده، وقفه رخ میده؟



ساختار برنامه جوریه که نمیشه از وقفه استفاده کرد.... میشه ها ولی باید نصف برنامه رو تغییر بدم که زمان محدودی دارم....
(آخرین ویرایش در این ارسال: ۱۴-شهریور-۱۳۹۲, ۲۰:۰۶:۴۵، توسط salehjg.)
۱۴-شهریور-۱۳۹۲, ۱۹:۵۷:۳۳
وب سایت ارسال‌ها
پاسخ
sharin آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,053
موضوع‌ها: 28
تاریخ عضویت: مرداد ۱۳۸۹

تشکرها : 3714
( 8171 تشکر در 2772 ارسال )
ارسال: #4
RE: مشکل با adc
شما الان داری می گی status رو بخون اگر برابر با 0xff نبود همینجا تو حلقه ی while منتظر بمون.
حالت عادی هر کدوم که تمام بشه فقط یکی از اون 8بیت پایین رجیستر status یک می شه ، یا همه صفر هست یا فقط یکیشون 1 هست. اینه که همیشه در این حلقه می مونه :)
باید بگی :
کد php:
while(((*AT91C_ADC_SR)&0xff)==0x00); 
بعد switch case بذاری برای هر 8 حالت ممکن.
یعنی : 0x01 , 0x02 , 0x04, 0x08 , 0x10 , 0x20 , 0x40 , 0x80
که هر کدوم flag اتمام تبدیل برای یکی از 8 خط هستن.
موفق باشی.

۱۴-شهریور-۱۳۹۲, ۲۰:۰۷:۴۹
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : babyy, salehjg
salehjg آفلاین
مدیر بخش
*****

ارسال‌ها: 1,281
موضوع‌ها: 133
تاریخ عضویت: آذر ۱۳۸۸

تشکرها : 9560
( 8557 تشکر در 2603 ارسال )
ارسال: #5
RE: مشکل با adc
نقل قول: شما الان داری می گی status رو بخون اگر برابر با 0xff نبود همینجا تو حلقه ی while منتظر بمون.
حالت عادی هر کدوم که تمام بشه فقط یکی از اون 8بیت پایین رجیستر status یک می شه ، یا همه صفر هست یا فقط یکیشون 1 هست. اینه که همیشه در این حلقه می مونه :)
سوال 1 - این توضیحاتو برای تابع وقفه دادین؟ ( من فرض کردم که جواب شما منفی یه)

سوال2 - اون قسمت bold عجیب به نظر میرسهBiggrin
مگه هر هشت تا کانال فعال نیست؟
مگه مدار داخلی adc ، خودش یکی یکی تموم کانال ها رو پشت سر هم انتخاب و به adc وصل نمیکنه؟
یعنی بالاخره بعد یه مدت زمان تبدیل همه ی هشت کانال تموم میشه و تمام eoc ها یک میشن توی status.... درسته؟

نقل قول: باید بگی :
کد php:
while(((*AT91C_ADC_SR)&0xff)==0x00); 
بعد switch case بذاری برای هر 8 حالت ممکن.
یعنی : 0x01 , 0x02 , 0x04, 0x08 , 0x10 , 0x20 , 0x40 , 0x80
که هر کدوم flag اتمام تبدیل برای یکی از 8 خط هستن.
موفق باشی.
بخاطر سوال های بالا ، منظورتونو نفهمیدم Shy



ممنون
۱۴-شهریور-۱۳۹۲, ۲۰:۳۲:۴۴
وب سایت ارسال‌ها
پاسخ
sharin آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,053
موضوع‌ها: 28
تاریخ عضویت: مرداد ۱۳۸۹

تشکرها : 3714
( 8171 تشکر در 2772 ارسال )
ارسال: #6
RE: مشکل با adc
نقل قول: سوال 1 - این توضیحاتو برای تابع وقفه دادین؟ ( من فرض کردم که جواب شما منفی یه)
نه ، کلی گفتم.
نقل قول: سوال2 - اون قسمت bold عجیب به نظر میرسه
هر بار status خونده بشه ، هر بیتی که یک بودهه 0 می شه.
دیباگ کن و مقدار این رجیستر status رو بخون ، ببین درست می گم یا نه :)

وقتی تبدیل هیچ خطی پایان نیافته باشه ، همه صفر هستن.
وقتی هر کدوم از خط ها تبدیلش تمام بشه ، EOCx مربوطه 1 می شه و بعد از این وقتی status رو بخونی بیت مربوطه EOCx پاک می شه ، یا همون 0. کاری ندارهه که وقفه فعال باشه یا نه ، یه چیز کلی هست.
پس هیچ وقت همه ی EOCx ها با هم نمی تونن 1 بشن.
منظورم فعال کردن 8 خط نیست ، منظورم پایان تبدیل هست ، اینا ظاهرا 2 منظورهه اند.

نقل قول: مگه مدار داخلی adc ، خودش یکی یکی تموم کانال ها رو پشت سر هم انتخاب و به adc وصل نمیکنه؟
فکر نکنم!
نقل قول: یعنی بالاخره بعد یه مدت زمان تبدیل همه ی هشت کانال تموم میشه و تمام eoc ها یک میشن توی status.... درسته؟
طبق گفته های بالا خیر ، بعید می دونم.

نقل قول: بخاطر سوال های بالا ، منظورتونو نفهمیدم
حالا یه دور دیگه بخون ، ببین اوکی هست؟

۱۴-شهریور-۱۳۹۲, ۲۱:۰۲:۱۹
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : babyy, salehjg
sharin آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,053
موضوع‌ها: 28
تاریخ عضویت: مرداد ۱۳۸۹

تشکرها : 3714
( 8171 تشکر در 2772 ارسال )
ارسال: #7
RE: مشکل با adc
الان دقیق تر چک کردم ، اصلاح می کنم ، اگر status رو مدام چک نکنیم ، می تونه 0xff بشه.
اما چون مدام دارهه چک می شه این اتفاق نمی یفته و می شه همون حرفی که زدم.
در مورد اتوماتیک خوندن پایه ها ، این کار رو باید نرم افزاری انجام داد ، الان رجیسترها رو چک کردم و چیزی برای اینکار به چشمم نخورد. در تنظیمات شما هم همینطور.

موفق باشی.

۱۴-شهریور-۱۳۹۲, ۲۲:۳۵:۳۵
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : babyy, salehjg
salehjg آفلاین
مدیر بخش
*****

ارسال‌ها: 1,281
موضوع‌ها: 133
تاریخ عضویت: آذر ۱۳۸۸

تشکرها : 9560
( 8557 تشکر در 2603 ارسال )
ارسال: #8
RE: مشکل با adc
نقل قول: هر بار status خونده بشه ، هر بیتی که یک بودهه 0 می شه.
دیباگ کن و مقدار این رجیستر status رو بخون ، ببین درست می گم یا نه :)

وقتی تبدیل هیچ خطی پایان نیافته باشه ، همه صفر هستن.
وقتی هر کدوم از خط ها تبدیلش تمام بشه ، EOCx مربوطه 1 می شه و بعد از این وقتی status رو بخونی بیت مربوطه EOCx پاک می شه ، یا همون 0. کاری ندارهه که وقفه فعال باشه یا نه ، یه چیز کلی هست.
پس هیچ وقت همه ی EOCx ها با هم نمی تونن 1 بشن.
منظورم فعال کردن 8 خط نیست ، منظورم پایان تبدیل هست ، اینا ظاهرا 2 منظورهه اند.
ایول
مرسی

نقل قول: فکر نکنم!
یکمی مبهم نوشته دیتاشیت...
اون مالتی پلکسر رو میگم
ما فقط کانال ها رو enable میکنم ، بعد یه دستور start میدیم که برای همه کانال ها مشترکه( من اینطوری میکنم.... کارم درسته؟)


پس باید این وسط ، یه مداری پایه های انتخاب مالتی پلکسر رو کنترل کنه دیگه....

نقل قول: الان دقیق تر چک کردم ، اصلاح می کنم ، اگر status رو مدام چک نکنیم ، می تونه 0xff بشه.
اما چون مدام دارهه چک می شه این اتفاق نمی یفته و می شه همون حرفی که زدم.
در مورد اتوماتیک خوندن پایه ها ، این کار رو باید نرم افزاری انجام داد ، الان رجیسترها رو چک کردم و چیزی برای اینکار به چشمم نخورد. در تنظیمات شما هم همینطور.

موفق باشی.
ولی اون کد یه مشکل دیگه داره
حالتی رو فرض کنید که دستور start رو دادیم.... ولی هنوز هیچ کدوم از کانال ها تموم نشده کارش، و همه ی eoc ها صفر ان هنوز....
اون وقت خیلی راحت از اون حلقه خارج میشه که این نامطلوبه
۱۴-شهریور-۱۳۹۲, ۲۳:۱۰:۴۵
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : babyy
sharin آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,053
موضوع‌ها: 28
تاریخ عضویت: مرداد ۱۳۸۹

تشکرها : 3714
( 8171 تشکر در 2772 ارسال )
ارسال: #9
RE: مشکل با adc
نقل قول: یکمی مبهم نوشته دیتاشیت...
اون مالتی پلکسر رو میگم
ما فقط کانال ها رو enable میکنم ، بعد یه دستور start میدیم که برای همه کانال ها مشترکه( من اینطوری میکنم.... کارم درسته؟)
پس باید این وسط ، یه مداری پایه های انتخاب مالتی پلکسر رو کنترل کنه دیگه....
راستی شما اومدی همه خط ها رو Enable کردی!
والا کاری که من کردم ، تک تک enable می کردم ، هر دفعه فقط یک پایه ، و بعد مقدار می خوندم. البته من فقط برای تاچ ازش استفاده کردم با یه سری کارا که فقط به یک خط اش نیاز بودهه.
برای scan کردن فکر نکنم سخت افزاری اینکار رو کنه ، جایی به چشم نخوردهه. دونه دونه Enable کن و دونه دونه بخون.

۱۴-شهریور-۱۳۹۲, ۲۳:۵۹:۵۷
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : salehjg, babyy
salehjg آفلاین
مدیر بخش
*****

ارسال‌ها: 1,281
موضوع‌ها: 133
تاریخ عضویت: آذر ۱۳۸۸

تشکرها : 9560
( 8557 تشکر در 2603 ارسال )
ارسال: #10
RE: مشکل با adc
بله بله بله Biggrin

آخرش با دونه دونه خوندن کنار اومدم Biggrin

کاش رجیستر وضعیت با خونده شدن، پاک نمیشد....
پاک شدنش کارو خیلی سخت کرده
میکرو های دیگه هم adc ایشون این مدلیه؟
انصافا خیلی مزخرفه
بدتر از این نمی شد .... کم کم sam7 ها اذیتم میکنن :|
اینم کد:

کد:
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<0;
                    *AT91C_ADC_CR = 2;    
                    while(((*AT91C_ADC_SR)& 1<<0)!=1<<0);
                    front_ptr[0] = *AT91C_ADC_CDR0;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<1;
                    *AT91C_ADC_CR = 2;        
                    while(((*AT91C_ADC_SR)& 1<<1)!=1<<1);
                    front_ptr[1] = *AT91C_ADC_CDR1;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<2;
                    *AT91C_ADC_CR = 2;          
                    while(((*AT91C_ADC_SR)& 1<<2)!=1<<2);
                    front_ptr[2] = *AT91C_ADC_CDR2;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<3;
                    *AT91C_ADC_CR = 2;        
                    while(((*AT91C_ADC_SR)& 1<<3)!=1<<3);
                    front_ptr[3] = *AT91C_ADC_CDR3;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<4;
                    *AT91C_ADC_CR = 2;            
                    while(((*AT91C_ADC_SR)& 1<<4)!=1<<4);
                    front_ptr[4] = *AT91C_ADC_CDR4;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<5;
                    *AT91C_ADC_CR = 2;            
                    while(((*AT91C_ADC_SR)& 1<<5)!=1<<5);
                    front_ptr[5] = *AT91C_ADC_CDR5;;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<6;
                    *AT91C_ADC_CR = 2;                
                    while(((*AT91C_ADC_SR)& 1<<6)!=1<<6);
                    front_ptr[6] = *AT91C_ADC_CDR6;
                    //----------------------------------------------
                    *AT91C_ADC_CHDR = 0xff;
                    *AT91C_ADC_CHER = 1<<7;
                    *AT91C_ADC_CR = 2;              
                    while(((*AT91C_ADC_SR)& 1<<7)!=1<<7);
                    front_ptr[7] = *AT91C_ADC_CDR7;
                    //----------------------------------------------

خدایا شکرت بالاخره حل شد مشکلم
آقا مرتضی دمت گرمHeart

شبت رعد و برقی Biggrin Wink
(آخرین ویرایش در این ارسال: ۱۵-شهریور-۱۳۹۲, ۰۰:۰۶:۴۸، توسط salehjg.)
۱۵-شهریور-۱۳۹۲, ۰۰:۰۳:۳۱
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : babyy, kimiafars, sharin
sharin آفلاین
مدیر بازنشسته
*****

ارسال‌ها: 2,053
موضوع‌ها: 28
تاریخ عضویت: مرداد ۱۳۸۹

تشکرها : 3714
( 8171 تشکر در 2772 ارسال )
ارسال: #11
RE: مشکل با adc
نقل قول: کاش رجیستر وضعیت با خونده شدن، پاک نمیشد....
پاک شدنش کارو خیلی سخت کرده
تازه این باعث می شه کارت راحت بشه ، از خدات باشه که این قابلیت رو دارهه :)

نقل قول: میکرو های دیگه هم adc ایشون این مدلیه؟
قاعده اش اینه :)
البته AVR و ... که برای همه ی کانال ها یه رجیستر دریافت داده بیشتر ندارن :)
طبیعتا باهاشون به این مسائل نمی خوری :)

برای این کدت هم یه تابع تعریف می کردی وجه ی بهتری داشت ...

آفرین آفرین ...
خوشم اومد :)

(آخرین ویرایش در این ارسال: ۱۵-شهریور-۱۳۹۲, ۰۱:۵۴:۲۹، توسط sharin.)
۱۵-شهریور-۱۳۹۲, ۰۱:۵۲:۲۱
وب سایت ارسال‌ها
پاسخ
تشکر شده توسط : salehjg, babyy, omid_phoenix


پرش به انجمن:


کاربرانِ درحال بازدید از این موضوع: 1 مهمان

صفحه‌ی تماس | IranVig | بازگشت به بالا | | بایگانی | پیوند سایتی RSS