در قسمت قبلی راه اندازی ماژول شتاب ینج را فرا گرفتیم و در این قسمت قرار است راهاندازی و استفاده از کارت حافظه SD را به صورت کلی به شما آموزش بدهیم.
بهرهگیری از کارت حافظه SD در کنار حافظههای موجود در میکرو، میتواند درزمینههای بسیاری کاربرد داشته باشد. برای اینکه مدیرت حافظه و فایلها با سهولت هر چه بیشتر انجام شود، میتوانیم از سیستم فایل استفاده کنیم. با استفاده از کتابخانه ff نوشتهشده توسط ChaN که با عنوان ELM by ChAN شناخته میشود، انجام این کار بسیار سادهتر خواهد شد. در ادامه روند ایجاد یک پروژه، اضافه کردن این فایلهای کتابخانهای و استفاده از کارت حافظه را باهم بررسی میکنیم. با سیسوگ همراه باشید.
ایجاد پروژه
برای ایجاد پروژه مثل همیشه تنظیمات دیباگ و کلاک و USART1 را انجام میدهیم. مسیر و نام را مشخص میکنیم و درایورهای LL را انتخاب میکنیم. توجه کنید که در این مرحله نیازی به انتخاب FATfs نیست، زیرا این فایلها را پس از ایجاد پروژه بهصورت دستی اضافه خواهیم کرد (به دلیل اینکه آخرین نسخه کتابخانه را اضافه کنیم و بتوانیم از توابع آماده و بیشتری استفاده کنیم). در مرحله بعد وارد برنامه Keil میشویم.
اضافه کردن فایلهای مورد نیاز
آخرین ورژن کتابخانه ff را میتوانید از سایت elm-chan، قسمت Softwares و سپس صفحه FatFs Module دانلود کنید. در زمان نوشتن این مقاله آخرین ورژن منتشرشده، FatFs R0.14b بوده است. از درون این فایل، به فایلهای ff.h، ff.c، ffconf، ffsystem و ffunicode نیاز داریم. یه پوشه به اسم fatfs، در مسیر پروژه بسازیم و این فایلها را درون آن کپی کنیم. در قسمت دانلود در لینک پروژههای نمونه (زیر لینک دانلود آخرین ورژن) میتوانیم بقیهی فایلهای موردنیاز را دانلود کنیم. در فایل دانلود شده از پوشه stm32، فایلهای diskio.h، mmc_stm32f1_spi.c و STM32F100.h را در پوشه fatfs که ساختیم کپی میکنیم.
در این مرحله باید محتویات پوشه ما شبیه به تصویر زیر باشد:
فایل mmc_stm32f1_spi را برای ویرایش باز میکنیم و در قسمت تعریف پینها پین مربوط به CS را تصحیح میکنیم، همچنین مقدار MMC_CD را 1 تعریف میکنیم؛
1 2 3 4 | #define CS_HIGH() GPIOB_BSRR = _BV(0) #define CS_LOW() GPIOB_BSRR = _BV(0+16) #define MMC_CD (1) |
سپس در محیط Keil از قسمت Project -> Manage -> Project items… یا دکمه میانبر آن وارد قسمت مدیرت فایلها میشویم. از قسمت Groups و کلید New(insert) یک گروه جدید میسازیم و نام آن را FatFS میگذاریم. سپس فایلهای با پسوند .c پوشه fatfs که در مسیر پروژه ساخته بودیم را به این گروه اضافه میکنیم. در پایان کار این منو نیز باید شبیه به تصویر زیر باشد:
در مرحله بعد از قسمت Project -> Options for target و از تب C/C++، مسیر پوشه fatfs را به Include Paths اضافه میکنیم؛
در این پروژه نیز میتوانیم مانند پروژه قبلی، اعمال مربوط به ریدایرکت کردن USART1 را انجام دهیم. اکنون همه فایلهای موردنیاز به پروژه اضافهشدهاند. به سراغ نوشتن کد میرویم.
نوشتن کد پروژه
قبل از هر چیز، یک بار پروژه را کامپایل میکنیم تا اگر اشتباهی رخداده است در همین مرحله متوجه شویم. در صورت نبود خطا ادامه میدهیم. در فایل main.c کتابخانههای موردنیاز را اضافه و ثابت کلاک سیستم را تعریف میکنیم؛
1 2 3 4 5 | #include <string.h> #include <ff.h> #include <diskio.h> #include "stdio_usart1.h" #include "stdio.h" |
1 | #define SystemCoreClock 8000000 |
در ادامه باید متغیرهای مورداستفاده برای ایجاد فایل و نوشتن و خواندن را تعریف کنیم؛
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* USER CODE BEGIN 0 */ FATFS FatFs; /* File system */ FIL fil; /* File object */ FRESULT fr; /* FatFs return code */ FILINFO filinf; /* File info object */ UINT br, bw; //file read/write count char readBuffer[100]; // to store data /* capacity related variables */ FATFS *pfs; DWORD fre_clust; float total, free_space; /* USER CODE END 0 */ |
سپس برای استفاده از تابع تنظیم زمانبندی، که در فایل mmc_stm32f1_spi.c و بانام disk_timerproc موجود است، باید وقفه SysTick را روی یک میلیثانیه تنظیم کنیم. با استفاده از کد زیر این کار را انجام میدهیم:
1 2 3 4 5 | printf("begin\n\r"); SysTick_Config(SystemCoreClock / 1000); LL_SYSTICK_SetClkSource(LL_SYSTICK_CLKSOURCE_HCLK); LL_SYSTICK_EnableIT(); |
حالا میتوانیم در فایل stm32f1xx_it.c تابع گفتهشده را اعلان و در روال وقفه سیستیک فراخوانی کنیم؛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void disk_timerproc (void); /** * @brief This function handles System tick timer. */ void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ disk_timerproc(); /* USER CODE END SysTick_IRQn 0 */ /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ } |
در مرحله بعد باید دیسک را آماده به کار کنیم. یک متغیر برای دریافت وضعیت عملیات انجامشده تعریف میکنیم و با توابع آمادهای که اضافه کردهایم دیسک را آماده میکنیم و وضعیت را به ترمینال سریال میفرستیم؛
1 2 3 4 5 6 7 8 | int stat = f_mount(&FatFs, "", 0); if(stat) printf("failed to mount the SD Card \r\n"); else printf("successfully mounted the SD Card\r\n"); stat = disk_initialize(0); printf("initialization status: %d\r\n", stat); |
کتابخانه ff امکانات زیادی برای مدیریت فایل و خواندن و نوشتن به ما میدهد، که در اینجا از بعضی از آنها استفاده خواهیم کرد. برای مثال میتوانیم فضای کل موجود روی کارت حافظه SD و فضای خالی آن را با استفاده از توابع موجود در کتابخانه دریافت کنیم؛
1 2 3 4 5 6 7 8 9 | /* Check free space */ f_getfree("0:", &fre_clust, &pfs); total = (float)((pfs->n_fatent - 2) * pfs->csize * 0.5 / (1024)); printf("SD CARD Total Size: \t%2.2f Mega Bytes\r\n", total); free_space = (float)(fre_clust * pfs->csize * 0.5 / (1024)); printf("SD CARD Free SPACE: \t%2.2f Mega Bytes\r\n", free_space); |
همچنین امکان باز کردن یک فایل (ایجاد فایل در صورت موجود نبود آن) و نوشتن در آن یا خواندن اطلاعات آن وجود دارد. برای این کار میتوانیم مشابه کد زیر از توابع موردنیاز استفاده کنیم؛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /********** Creating a new file if does not exist, and writing to it **********/ fr = f_open(&fil, "message.txt", FA_CREATE_ALWAYS | FA_WRITE | FA_READ); if (fr) { printf("Can not open file\r\n -> %d",fr); while(1) LL_mDelay(100); } else printf("Successfully opened the file\r\n"); char simpletext[] = "Hello World"; fr = f_write(&fil, simpletext, strlen(simpletext), &bw); if (fr) { printf("Can not write to the file\r\n -> %d",fr); while(1) LL_mDelay(100); } else printf("Successfully writed to the file\r\n"); f_close(&fil); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /******************** Read data from the file ********************/ fr = f_open(&fil, "message.txt", FA_READ); fr = f_stat("message.txt", &filinf); fr = f_read(&fil, readBuffer, filinf.fsize, &br); if (fr) { printf("Can not read the file\r\n -> %d",fr); while(1) LL_mDelay(100); } else printf("Contents of the file is :\r\n\t\"(/begin)\n%s\n(/end)\"\r\n",readBuffer); f_close(&fil); |
علاوه بر اینها، امکان تغییر محتویات یک فایل و بهعنوانمثال اضافه کردن اطلاعات به آن نیز وجود دارد؛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /*********************** Updating an existing file ***********************/ /* Open the file with write access */ fr = f_open(&fil, "message.txt", FA_OPEN_ALWAYS | FA_WRITE); /* Move to offset to the end of the file */ fr = f_lseek(&fil, filinf.fsize); /* write the string to the file */ fr = f_write(&fil, "/r/n ...and good day to you\r\n", 27, &bw); f_close(&fil); fr = f_open(&fil, "message.txt", FA_READ); fr = f_stat("message.txt", &filinf); fr = f_read(&fil, readBuffer, filinf.fsize, &br); if (fr) { printf("Can not read the file\r\n -> %d",fr); while(1) LL_mDelay(100); } else printf("Contents of the file is :\r\n\t\"(/begin)\n%s\n(/end)\"\r\n",readBuffer); f_close(&fil); |
در صورت نیاز توابعی برای پاک کردن فایلهای ساختهشده وجود دارد؛
1 2 3 4 5 6 7 8 9 10 | /*********************** Removing an existing file ***********************/ fr = f_unlink("message.txt"); if(fr == FR_OK) printf("message.txt removed successfully...\r\n"); /* Unmount SD Card */ fr = f_mount(NULL, "", 1); if(fr == FR_OK) printf("SD Card unmounted successfully...\r\n"); |
برای پایان کار یک مرحله دیگر نیاز است. در نرمافزار Keil بهطور پیشفرض بهینهسازی کد در حداکثر سطح ممکن یعنی Level3 تنظیمشده است. این مقدار را در تنظیمات Project -> Options for target و تب C/C++، روی مقدار Level0 قرار میدهیم و سپس کد را کامپایل میکنیم.
اگر همه مراحل را بهدرستی طی کرده باشیم و کارت حافظه SD را با فرمت fat32 به میکرو متصل کنیم -شماتیک بورد بهکاررفته در این پروژه و اتصالات مربوط به آن را میتوانید از این لینک از سایت سیسوگ دریافت کنید- پس از اتصال پورت سریال به بورد و دانلود برنامه روی میکرو و ریست کردن آن، میتوانیم نتیجه اجرا را روی ترمینال سریال ببینیم؛
همچنین در صورت اتصال این کارت حافظه به یک memory card reader و باز کردن محتویات آن در کامپیوتر (در صورت اجرا نکردن دستورات مربوط به حذف کردن فایل) میتوانیم فایل ایجادشده و اطلاعات درون آن را مشاهده کنیم؛