راه اندازی مموری کارت

شنبه 29 شهرویور 1393  •  دسته بندی: پروژه های آماده با میکروکنترلر AVR  •  بازدیدها: 7267  •  برچسب ها: | |

هدف پروژه: کار کردن با مموری کارت و آشنایی با واحد spi میکرو. روال برنامه به این صورت است که بعد از شناسایی مموری کارت، اطلاعاتی را در آن نوشته و همان را می خوانیم و در ترمینال نامینیک نمایش می دهیم. (نحوه کار با ترمینال نامینیک در سایت توضیح داده شده است.)

سخت افزار استفاده شده: در اینجا از برد آموزشی avr شرکت نامینیک مبتنی بر تراشه ATMEGA32 استفاده شده است. این برد در روی خود یک کانکتور micro cd دارد که به 4 پایه واحد spi میکرو را اشغال کرده است (یعنی پایه های 4 تا 7 پورت b). پایه sw1 کانکتور هم برای تشخیص وجود و یا عدم وجود مموری کارت به پین 2 پورت d یعنی وقفه خارجی صفر متصل شده است.

کتابخانه های مورد نیاز: کتابخانه اصلی مورد استفاده در این مثال برای راه اندازی مموری کارت در خط 2 فراخوانی شده است یعنی sdcard.h  سایر کتابخانه ها هم معرف حضور بوده و در خط 1 تا 4 ردیف شده اند.

تشریح کد:

sd کارت ها معمولا با فرمت FAT32 کار می کنند. پس اگر بخواهید فایل ها را کامپیوتر از مموری کارت می خواند یا در آن می نویسد را شما هم با میکرو انجام دهید از کتابخانه ff.h کدویژن استفاده کنید. کتابخانه این مثال فقط برای خواندن و نوشتن عادی در مموری کارت کاربرد دارد و کار با فایل ها و FAT32 را نمی فهمد. مموری کارت ها توسط روش های متنوعی با دستگاه های دیگر ارتباط برقرار می کنند. یکی از متداول ترین روش های فعلی، (که البته در سال های آینده کم کم کاهش می یابد) روش ارتباط از طریق درگاه spi است. پروتکل spi یک پروتکل انتقال اطلاعات به روش سریال بوده و جزء روش های سنکرون محسوب می شود. برای برقراری ارتباط توسط این پروتکل حداقل به 4 سیم نیاز داریم. دو سیم برای ارسال و دریافت اطلاعات، یک سیم برای کلاک و یک سیم برای فعال کردن یا غیر فعال کردن وسیله مورد ارتباط. در این پروتکل یکی از وسیله ها  مدیر باس است. مدیر باس کلاک را تولید کرده و سایرین را برای برقراری ارتباط فعال یا غیر فعال می کند. جزییات آن در دیتاشیت میکرو هست.

در تابع main و در خط 43 تا 45 ابتدا تایمر 2 در مد CTC قرار گرفته و هر 0.01 ثانیه یک وقفه تولید می کند. (در باره تایمر قبلا صحبت شده است) داخل وقفه تایمر و در خط 10، تابع disk_timerproc()  فراخوانی شده است. توجه کنید که با توجه به توضیحات کتابخانه sdcard.h این تابع حتما باید هر 10 میلی ثانیه فراخوانی شود. این تابع تایمینگ توابع این کتابخانه را مدیریت می کند.

همانطور که در بالا گفته شد، برای کارهای سطح بالاتر و کار با سیتم فایل FAT32 کتابخانه ff.h در کدویژن وجود دارد که خود کدویژن هم در فایلی توابع آن را توضیح داده است.

در خط 49 تابع usart_init() ، درگاه سریال usart میکرو را برای ارتباط با ترمینال نامینیک و نشان دادن نتایج فراخوانی شده است. بدنه تابع در خطوط 12 تا 24 نوشته شده است.

در خط 51 تابع disk_initialize(0) فراخوانی شده است. این تابع کارهای مقدماتی را برای ارتباط با مموری کارت انجام می دهد. مقدار صفر در آرگومان این تابع همان آدرس سخت افزار مموری کارت است که از صفر شروع می شود. در اینجا فقط یک کانکتور sd card در بورد داشتیم. این تابع بعد از تنظیمات اولیه و تلاش برای ارتباط با مموری کارت، نتیجه را به صورت یک بایت بر می گرداند که در خط 51 نتیجه در متغییری به نام r ریخته شده است. در خطوط 53 تا 59 مقدار r با چند مقدار عددی تعریف شده در کتابخانه sdcard.h مقایسه می شود و نتیجه در ترمینال نمایش داده می شود. اگر تمام مراحل موفقیت آمیز باشد، تابع مقدار صفر را در متغییر r می ریزد. در خط 63 تا 65 ، تعداد 101 خانه از یک آرایه 512 بایتی به نام buffer را با مقدار 0 تا 100 پر می شود. دلیل اینکه این بافر 512 بایتی است این است که همانطور که قبلا در بحث حافظه های eeprom توضیح دادیم، حافظه های مبتنی بر فلش (مثل همین sd card ها) را نمی توان بایت بایت نوشت یا خواند، و فقط صفحه صفحه خوانده و نوشته می شوند که اکثرا صفحات (بجز بعضی حافظه های جدید) 512 بایتی هستند. یعنی مثلا اگر یک حافظه فلشی 128 کیلو بایت باشد، حدود 256 صفحه دارد که در دیتاشیت آن ها به طور کامل و کافی و وافی و مبسوط! سخن رانده شده است.  دیتای شما حداقل باید 512 بایتی باشد و مضارب 512 را از حافظه اشغال می کند. حتی اگر یک بایت باشد.

در خط 66 در آرگومان تابع status تابعی به نام  disck_write صدا زده شده است. این تابع 4 آرگومان دارد. آرگومان اول، آدرس سخت افزار مموری کارت است که از صفر شروع می شود. آرگومان دوم متغییری است که دیتا را در خود نگه می دارد که در برنامه ما همان buffer است. در آرگومان سوم، باید مشخص کرد که از چه بلوکی در مموری کارت نوشتن دیتا شروع شود و آرگومان آخر نیز مشخص می کند متغییر شما چند سکتور جا می گیرد(حداکثر 256). (تذکر اینکه، هر سکتور 32 بلوک و هر بلوک 8 صفحه است. سکتور ها ، بلوک ها و صفحات علاوه بر اینکه آدرس مجزا دارند، آدرس آفست هم دارند. مثلا صفحه سوم از بلوک چهارم از سکتور اول که اگر آدرس مجزای این صفحه را بخواهیم می شود بیست و ششمین صفحه از اول حافظه. ما در برنامه صفحه هزارم را نوشتیم). تابع  disc_write یک بایت را به عنوان نتیجه کار بر می گرداند. تابع status برای نمایش نتیجه نوشتن در حافظه بهینه شده است.

در خط 68 تا 70 مقادیری را که در بافر ریخته بودیم پاک می کنیم. و در خط 72 با تابع disk_read همان اطلاعاتی را که نوشته بودیم می خوانیم و در متغییر buffer می ریزیم. نتایج را نیز توسط تابع status نتایج را نمایش می دهیم. در خط آخر هم مقدار خانه 20 متغییر بافر را در ترمینال چاپ می کنیم.

این کتابخانه توابع دیگری نیز دارد. مثلا تابعی که وضعیت مموری کارت، از قبیل داشتن یا نداشتن اجازه نوشتن را برای ما می خواند که برای اطلاعات بیشتر، شما را به خواندن فایل user manual  کدویژن ارجاع می دهم.

 

#include <mega32.h>
#include <sdcard.h>
#include <stdio.h>
#include <delay.h>


interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
disk_timerproc();    /* Drive timer procedure of low level disk I/O module */
}
void usart_init(){
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x08;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;
} 
void status(unsigned char st){
if(st & RES_OK) printf("successnr");
else
if(st & RES_ERROR) printf("a write error occurednr");
else
if(st & RES_WRPRT) printf("the MMC/SD/SD HC card is write protectednr");
else
if(st & RES_NOTRDY) printf("the disk drive has not been initializednr");
else
if(st & RES_PARERR) printf("invalid parameters were passed to the functionnr");
}
    
//Drv mmc;
unsigned char r;
unsigned char buffer[512];
unsigned char i;
unsigned long int sector_count;
void main(){
    OCR1A = 7813;        // Timer1: 100Hz interval (OCR1A)
    TCCR1A = 0x00;
    TCCR1B = 0x0D;
    TIMSK=0x10;    
    DDRB=1;

    #asm("sei") 
    usart_init();
    r=disk_initialize(0);    
   
   if (r & STA_NOINIT) printf("nDisk init failednr"); 
   else
   if (r & STA_NODISK) printf("nCard not presentnr");
   else
   if (r & STA_PROTECT) printf("nCard writenprotectednr");
   /* all status flags are 0, disk initialization OK */
   else printf("nInit OKnr");
   delay_ms(2000); 
   //while(1);
   
   for(i=0;i<=100;i++){
    buffer[i]=i;
    }
   status(disk_write(0,buffer,1000,1)); 
   
   for(i=0;i<=100;i++){
    buffer[i]=0;
    }                       
    
   status(disk_read(0,buffer,1000,1));
   
   printf("ndata=%dn",buffer[20]);

   
   while(1);
   
}

دانلود سورس کد

در  اینجا شما میتوانید سورس برنامه را دریافت ،کامپایل و پروگرم نمایید و شاهد عملکرد برنامه باشید.

با کلیک بر روی عکس زیر فیلم راه اندازی این پروژه را مشاهده کیند.

این مطلب را به اشتراک بگذارید:

در این باره 1 نظر وجود دارد، شما هم نظر خود را ثبت کنید.
نام:
ایمیل:
نظر:

تعداد کل نظرها: 1

رضااسدی:
چهار شنبه 08 مهر 1394 ساعت 23:30:21
سلام.مرسی از آموزش خوبتون.ممکنه راجع به نمایش یک تصویر از مموری روی lcd نیز مطلبی بگذارید؟