قبلا درباره ماژول RC522 را در مقاله ای تحت عنوان “راهاندازی پروژه RFID RC522 با آردوینو” راهاندازی کردیم. اکنون در این مقاله قصد داریم به راهاندازی ماژول RC522 با STM32 بپردازیم. ابتدا در رابطه با خود RFID توضیحاتی خواهیم داد و در ادامه به راهاندازی آن با STM32 میپردازیم.
RFID (Radio Frequency Identification)
همانطور که از اسم RFID پیداست، میتواند با استفاده از فرکانسهای رادیویی عمل شناسایی را انجام دهد.
به طور ساده میتوان گفت که RFID با استفاده از امواج مغناطیس و بدون تماس مستقیم عمل شناسایی را انجام میدهد.
نحوهی عملکرد RFID
نحوهی عملکرد به این گونه است که وقتی کارت دارای UID در مجاورت ماژول RC522 قرار میگیرد، میدان مغناطیسی تولید شده توسط ماژول باعث فعال شدن تگ RFID میگردد. در ادامه تگ پیوسته اقدام به ارسال داده میکند و این دادهها توسط کارتخوانی که در قسمت ماژول است خوانده میشود.
بررسی انواع تگهای RFID
تگهای RFID دارای انواع متفاوتی هستند و امکانات آنها تا حدودی متفاوت است، اما همگی آنها حداقل دارای یک تراشه و یک آنتن هستند.
بعضی از این تگها دارای حافظههایی نیز هستند که این حافظه میتواند فقط خواندنی و یا خواندنی/نوشتنی باشد.
در بعضی از این تگها باتری هم وجود دارد که کاربرد این باتری تامین توان لازم برای ارسال داده به کارتخوان میباشد که به این تگها، تگهای فعال گفته میشود و وجودهمین باتری باعث میشود که تگ بتواند با کارتخوانهای که قدرت کمتری دارند نیز ارتباط برقرار کند.
توجه شود که تگهای غیر فعال توان خود برای فعال شدن و ارسال داده را از کارتخوان دریافت میکنند.
ماژول RC522
ماژول کارتخوان با قابلیت خواندن و نوشتن RC522 به منظور خواندن کارتهای RFID مورد استفاده قرار میگیرد. همچنین این ماژول با فرکانس کاری 13.56 مگاهرتز قابلیت خواندن و نوشتن بر روی تگها را دارد.
این ماژول قابلیتهایی دارد که مختصرا به شرح زیر میباشند:
- پشتیبانی از پروتوکلهای I2C ,SPI و UART
- دارای یک بافر 64 بیتی
- ولتاژ کاری 2.5 تا 3.5 ولت DC
- جریان مصرفی 13 تا26 میلی آمپر
- دارای اسیلاتور خارجی 27.12 مگاهرتز
- قابلیت خواندن و نوشتن بدون تماس در فاصله 8 تا 10 سانتی متر
همانطور که در قابیلتهای این ماژول ذکر شد، از سه پروتکل برای انتقال دیتا پشتیبانی میکند. اما پروتکلی که ما قصد داریم از آن برای راهاندازی این ماژول استفاده کنیم، پروتکل SPI است. در ادامه به شرح این پروتکل میپردازیم.
پروتکل SPI
این پروتکل، یک پروتکل سریال میباشد که توسط شرکت موتورولا طراحی شده است و به صورت Master و Slave کار میکند، بدین صورت که فقط میتواند یک Master و چندین Slave داشته باشد.
در حالت تئوری تعداد Slaveها هیچ محدودیتی ندارد اما در عمل به دلیل یک سری نکات فنی تعداد Slaveها محدود است.
به تصویر زیر دقت کنید:
در حالت کلی پروتکل SPI شامل چهار سیم زیر میباشد:
- SCLK: Serial Clock (output from master)
- MOSI: Master Output Slave Input, or Master Out Slave In (data output from master)
- MISO: Master Input Slave Output, or Master In Slave Out (data output from slave)
- SS: Slave Select (often active low, output from master)
توضیحات بالا به خوبی عملکرد هر پایه را نشان میدهد و نیازی به توضیحات اضافی نیست. پس همانطور که گفتیم در این پروتکل چهار سیم وجود دارد اما این تا زمانی است که تنها یک Master و یک Slave داشته باشیم. به ازای اضافه شدن هر Slave یک سیم SS دیگر به Master اضافه میشود.
در واقع هر سیم SS برای انتخاب یکی از Slaveها به کار میرود.
در پروژه موردنظر ما چون یک Slave داریم پس Master هم همان چهار سیم را دارد.
در پروتکل SPI چهار مد عملیاتی مختلف وجود دارد که این چهار مد عملیاتی به وسیلهی دو پارامتر CPOL و CPHA تعیین میشوند. ابتدا به تصاویر زیر دقت کنید تا پس از آن این مدهای عملیاتی را توضیح بدهیم.
با توجه به تصاویر بالا پارامتر CPOL مشخص میکند که حالت اولیه کلاک صفر منطقی است یا یک منطقی. اگر صفر منطقی باشد پس اولین لبهی کلاک، لبهی بالارونده خواهد بود و اگر حالت اولیه کلاک یک منطقی باشد پس اولین لبهی کلاک، لبهی پایین رونده خواهد بود.
همچنین پارامتر CPHA مشخص میکند که دیتا در اولین یا دومین لبهی کلاک نمونهبرداری شود. اینکه پارامتر CPOL چه باشد اولین لبه میتواند لبهی بالارونده یا پایینرونده باشد، دومین لبه نیز به همین صورت میتواند بالا رونده باشد یا پایین رونده.
با توضیحات بالا چهار مد عملیاتی متفاوت میتواند وجود داشته باشد که ما در این پروژه از مد صفر استفاده میکنیم. یعنی کلاک در حالت بیکاری یا همان حالت اولیه صفر منطقی است و نمونهبرداری در لبهی اول که همان لبهی بالارونده صورت میگیرد.
راهاندازی ماژول RC522 با STM32
اکنون میخواهیم که این ماژول را با استفاده از برد Bluepill که میکروکنترلر آن STM32F1 میباشد راهاندازی کنیم.
نحوهی کار به این صورت است که ما ID تگ RFID را با استفاده از پروتکل SPI میخوانیم و پس از اینکه دیتای تگ ثبت شد آن را با استفاده از پروتکل UART بر روی پورت سریال ارسال خواهیم کرد و ID کارت را در کامپیوتر مشاهده خواهیم کرد.
ماژول را طبق اتصالات زیر به SPI1 برد Bluepill وصل خواهیم کرد.
RC522 | Bluepill |
SDA | PA4 |
SCK | PA5 |
MOSI | PA7 |
MISO | PA6 |
IRQ | unconnected |
GND | GND |
RST | 3.3V |
3.3V | 3.3V |
همچنین یک مبدل USB به سریال به UART1 برد Bluepill وصل خواهیم کرد تا دادهها را مانند شکل زیر در کامپیوتر مشاهده کنیم. پایه RX ماژول به A9 (TX USART1) متصل می شود. همچنین بهتر است پایه ریست RC522 را هم به پایه ریست بلوپیل متصل کنید تا وقتی که به وسیله دکمه بلوپیل را ریست می کنیم، ماژول هم ریست شود.
توضیحاتی در رابطه با کتابخانه و main برنامه
ابتدا دیتاشیت ماژول را میخوانیم و با توجه به رجیسترها، مد کاری، نحوهی انتقال دیتا، پروتکلی که دیتا با آن انتقال پیدا میکند و … یک کتابخانه برای ماژول درست میکنیم.
در پروژه، ما تنها یک کتابخانه نوشته شده توسط کاربر به اسم rc522 داریم. در فایل rc522.h یک سری ثوابت، رجیسترها و همچنین اسم توابع را تعریف کردیم. در فایل rc522.c هم نحوهی انتقال دیتا و کار با ماژول با استفاده از توابع توصیف شده است.
در فایل rc522.c حدود بیست تابع برای کارهای مختلف با ماژول موجود میباشد که ما به توضیح تک تک این توابع نخواهیم پرداخت و در ادامه فقط مختصرا توابعی که در main برنامه استفاده کردیم را بررسی میکنیم.
البته با توجه به اسم هر تابع و بررسی کد آن شما به سادگی میتوانید متوجه عملکرد و کارایی تابع شوید.
مثلا ما هنگام توسعه برنامه از تابع MFRC522_ReadRegister استفاده کردیم و همانطور که از اسمش مشخص است مقدار یک رجیستر را به ما برمیگرداند. ما با استفاده از این تابع مقدار رجیستر مربوط به ورژن RFID را خواندیم و با مقداری که در دیتا شیت داریم چک کردیم تا ببینیم ارتباط به درستی صورت گرفته است یا خیر.
البته چون ابتدا ولتاژ 3.3 ولت روی برد قطع بود، به نظر میرسید که کتابخانه نوشته شده به درستی کار نمیکند و عملیات انتقال دیتا با استفاده از پروتکل SPI به درستی صورت نمیگیرد. که پس از چک کردن ولتاژ 3.3 ولت و برقرار کردن آن کشف شد که کتابخانه به درستی با ماژول ارتباط برقرار میکند و مشکل از تغذیه است.
همچنین توجه شود که ما در کتابخانه rc522 برای پروتکل SPI و UART از توابع HAL استفاده کردیم.
ابتدا به main برنامه توجه کنید تا در ادامه توضیحاتی را بیان کنیم.
int main(void) { const char intorstr[] = "STM32F103 Mifare RC522 RFID Card reader 13.56 MHz\r\n"; /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); MX_SPI1_Init(); /* USER CODE BEGIN 2 */ MFRC522_Init(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); HAL_Delay(100); HAL_UART_Transmit(&huart1, (uint8_t*)intorstr,strlen(intorstr), 500); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { if (!MFRC522_Request(PICC_REQIDL, CardID)) { if (!MFRC522_Anticoll(CardID)) { if(memcmp(CardID,LastCardID,4)) { memcpy(LastCardID,CardID,4); char ID_Str[20] = {0}; sprintf(ID_Str,"Card ID: %X\r\n",*((uint32_t*)CardID)); HAL_UART_Transmit(&huart1, ID_Str, strlen(ID_Str), 500); } } } else { t++; if (t > 4 ) { memset(LastCardID,0,4); t = 0; } } HAL_Delay(200); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
ابتدا کلاک سیستم، ورودی-خروجی، پروتکل UART و پروتکل SPI را انشیالایز میکنیم.
همانطور که میدانید زمانی که قرار است با پروتکل SPI ارتباط برقرار کنیم باید ابتدا پایه CS را صفر کنیم و زمانی که دیتا منتقل شد و کاری نداشتیم دوباره این پایه را به مقدار یک منطقی برگردانیم.
چون CS به پایه PA4 متصل است ما PA4 را صفر و یک میکنیم.
ابتدا PA4 را در main برنامه در حالت یک قرار میدهیم تا زمانی که بخواهیم در while دیتا را از SPI انتقال بدهیم آن را صفر میکنیم.
پس از ایجاد کمی تاخیر یک پیام بر روی پورت سریال برای راهنمای کاربر میفرستیم و ادامه برنامه در while قرار دارد.
کل برنامهی نوشته شده در while به شرح زیر است:
در ابتدای while توسط دستورات شرطی بررسی میشود که کارتی تشخیص داده شده است یا خیر، اگر تشخیص داده شد، ID آن را بر روی پورت سریال بفرستد. تواما بررسی میشود تا مادامی که همان کارت در مجاورت ماژول قرار دارد مقدار ID همان باشد و چیز دیگری روی پورت سریال فرستاده نشود مگر اینکه کارت را کلا برداریم و دوباره بزنیم تا همان ID برای بار دوم روی پورت سریال فرستاده شود.
همچنین در این برنامه اشکال اینکه اگر کارت در فاصلهای از ماژول قرار بگیرد که در لحظهای بسیار کوتاه خوانده شود و سپس خوانده نشود و به همین ترتیب ادامه پیدا کند، برطرف شده است.
سورس برنامه را میتوانید از طریق لینک زیر دانلود کنید:
لینکهای دانلود
دانلود سورس برنامه– حجم 0.8 مگابایت
اسم فایل
RC522.zip
منبع:سیسوگ