RC 522模組在LINUX平台調試筆記

來源:互聯網
上載者:User

標籤:

硬體平台:

1 主控:SMDK Exynos4412 POP S5M8767A

2 RFID模組:君盾集團提供的RC522模組

3 通訊介面:SPI

軟體平台:Android ICS & kernel version 3.0.15

 

一,使能主控端SPI

1 硬體使能:

從SMDK原理圖上可以看到SPI0與I2C共用,SPI1已經串連到其它裝置,SPI2未用,故這裡選用SPI2。

 

2 軟體使能:

SMDK Exynos4412 主控端已經配置好了SPI介面,使用時只需開啟宏CONFIG_S3C64XX_DEV_SPI即可。

         開啟檔案:make menuconfigàDevice DriversàSPI supportàSamsung S3C64XX series type SPI.

編譯後產生zImage,燒錄進開發板。

 

二,測試主控端SPI

主控端SPI已經開啟,接下來可以用一個通用的SPI驅動來測試主控端SPI硬體是否能正常工作。

以模組的方式編譯:drivers/spi/spidev.c,產生spidev.ko,便是通用的裝置端SPI驅動程式。

編譯測試程式:Documentation/spi/spidev_test.c,先修改第32行: static const char *device = "/dev/spidev1.1"的裝置為“/dev/spidev2.0”,然後再以應用程式的方式來編譯,產生spidev_test,即為對應SPI的測試程式。

通過串口,賦予root許可權和系統可讀寫權限:

[email protected]:/ $ su root

[email protected]:/ # mount -o remount -rw /system

[  391.423930] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)

[email protected]:/ #

通過adb把spidev.ko和spidev_test push到開發板:

 

載入驅動:

[email protected]:/system # insmod spidev.ko

把MISO和MOSI短路,即自發自收,然後再執行測試程式:

 

如所示,說明能通過SPI收發資料;如果全部顯示為0,則說明SPI未正常工作。接下來可以放心地去調試我們的RC522模組了。

 

三,RC522裝置端驅動調試

上面的實驗已經證明了主控的SPI可以正常工作,接下來可以正式調試RC522了。――這裡假設你的rfid_rc522驅動已經寫好,現在只需要去調試――如果驅動沒有寫好,請看另一篇Blog。

1 開啟與開發板相關的檔案:arch/arm/mach-exynos/mach-smdk4x12.c

由於使用的spi2,故要修改board_info裡的modalias = “rfid_rc522”,與驅動裡的spi_drviver.name相匹配,否則probe函數不成功。

 

點擊(此處)摺疊或開啟

  1. 988 static struct spi_board_info spi2_board_info[] __initdata = { 
  2.  989 { 
  3.  990 .modalias = "rfid_rc522", 
  4.  991 .platform_data = NULL, 
  5.  992 .max_speed_hz = 10*1000*1000, 
  6.  993 .bus_num = 2, 
  7.  994 .chip_select = 0, 
  8.  995 .mode = SPI_MODE_0, 
  9.  996 .controller_data = &spi2_csi[0], 
  10.  997 } 
  11.  998 };


2 重新編譯核心,並燒錄到開發板。

 

3 編譯rc522驅動程式,並通過adb usb把產生的rfid_rc522.ko copy到開發板系統的/system目錄下,然後 insmod rfid_rc522.ko, 這樣驅動就以模組的形式載入進了核心系統。載入成功後,在/dev 目錄下就會有rfid_rc522_dev這個目錄。

 

 

四,應用程式

驅動中的write函數為:

rc522_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos);

使用者空間的應用程式write函數為:

write(rc522_fd, bufpw1, sizeof(bufpw1));

二者如何聯絡的呢?

其實應用程式中的write函數通過叫用作業系統中的核心函數sys_write(unsigned int fd, const char * buf, size_t count)來實現,而sys_write()函數又對驅動中的rc522_write()進行了封裝。

//摘自論壇開始

下面以字元裝置驅動來具體說明:

1,insmod驅動程式。驅動程式申請次裝置名稱和主裝置號,這些可以在/proc/devieces中獲得。

2,從/proc/devices中獲得主裝置號,並使用mknod命令建立裝置節點檔案。這是通過主裝置號將裝置節點檔案和裝置驅動程式聯絡在一起。裝置節點檔案中的file屬性中指明了驅動程式中fops方法實現的函數指標。

3,使用者程式使用open開啟裝置節點檔案,這時作業系統核心知道該驅動程式工作了,就調用fops方法中的open函數進行相應的工作。open方法一般返回的是檔案標示符,實際上並不是直接對它進行操作的,而是有作業系統的系統調用在背後工作。

4,當使用者使用write函數操作裝置檔案時,作業系統調用sys_write函數,該函數首先通過檔案標示符得到裝置節點檔案對應的inode指標和flip指標。inode指標中有裝置號資訊,能夠告訴作業系統應該使用哪一個裝置驅動程式,flip指標中有fops資訊,可以告訴作業系統相應的fops方法函數在那裡可以找到。

5,然後這時sys_write才會調用驅動程式中的write方法來對裝置進行寫的操作。

其中1-3都是在使用者空間進行的,4-5是在核心空間進行的。使用者的write函數和作業系統的write函數通過系統調用sys_write聯絡在了一起。

注意:

對於塊裝置來說,還存在寫的模式的問題,這應該是由GNU C庫來解決的,這裡不予討論,因為我沒有看過GNU C庫的原始碼。

//摘自論壇結束

 

         應用程式源碼如下:

 

 

點擊(此處)摺疊或開啟

  1. #include <stdio.h> 
  2. #include <string.h> 
  3. #include <stdlib.h> 
  4. #include <sys/types.h> 
  5. #include <unistd.h> 
  6. #include <errno.h> 
  7. #include <arpa/inet.h> 
  8. #include <sys/time.h> 
  9. #include <sys/types.h> 
  10. #include <sys/stat.h> 
  11. #include <fcntl.h> 
  12. #include <sys/ioctl.h> 
  13. #include <math.h> 
  14. static enum IO_CMD { 
  15.     READ_CARD = 0, 
  16.     CHANGE_PASSWD = 1, 
  17.     CHANGE_BLOCK = 3, 
  18.     SET_RW_TIME = 4, 
  19.     WRITE_CARD = 5, 
  20. }; 
  21. int main(int argc, char** argv) 
  22.          int rc522_fd; 
  23.          int i, read_num; 
  24.          char r[256]; 
  25.          printf("test: rc522 %s %s\n", __DATE__, __TIME__); 
  26.          
  27.          printf("test: before open rc522_fd\n"); 
  28.          rc522_fd = open("/dev/rfid_rc522_dev", O_RDWR); 
  29.          
  30.          printf("test: rc522_fd=%d\n", rc522_fd); 
  31.          if(rc522_fd == -1) 
  32.          { 
  33.                    printf("test: Error Opening rc522\n"); 
  34.                    return(-1); 
  35.          } 
  36. printf("test: wait 01\n"); 
  37.          sleep(1); //wait 
  38. printf("test: wait 02\n"); 
  39. /******* Never to open ********/ 
  40. #if 0 
  41. // change password as:020202020202 
  42.          ioctl(rc522_fd, CHANGE_BLOCK, 0);//參數3:選第0塊 
  43.          ioctl(rc522_fd, CHANGE_PASSWD, 0); 
  44.          char bufpw1[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; 
  45.          
  46.          write(rc522_fd, bufpw1, sizeof(bufpw1)); 
  47. #endif 
  48.          ioctl(rc522_fd, CHANGE_BLOCK, 0);//參數3:選第0塊 
  49.          ioctl(rc522_fd, READ_CARD, 0);//參數3沒用 
  50.          for(i = 0; i < 3; i++) //讀三次卡號 
  51.          { 
  52.                             read_num = read(rc522_fd, r, 0); 
  53.                             printf("test: i=%d read_num=%d ", i, read_num); 
  54.                             if(read_num > 0){ 
  55.                                      printf("r=[0x%.2X]", r[0]); 
  56.                             } 
  57.                             
  58.                             printf("\n"); 
  59.                             sleep(1); 
  60.          } 
  61.          
  62. // write something to the card 
  63.          ioctl(rc522_fd, CHANGE_BLOCK, 1);//參數3:選第2塊 
  64.          ioctl(rc522_fd, WRITE_CARD, 1); 
  65.          printf("before write card!\n"); 
  66.          
  67.          char buf[11] = "186653803xx"; 
  68.          if(write(rc522_fd, buf,sizeof(buf))) 
  69.          { 
  70.                    printf("write error\n"); 
  71.          } 
  72. // read block[1], just writed with 
  73.          ioctl(rc522_fd, CHANGE_BLOCK, 1);//參數3:選第1塊 
  74.          ioctl(rc522_fd, READ_CARD, 0);//參數3沒用 
  75.          read_num = read(rc522_fd, r, 0); 
  76.          printf("read block[1]\n\n\n The number you just writed is: %s\n\n\n", r); 
  77.          printf("test: close rc522_fd\n"); 
  78.          close(rc522_fd); 
  79.          printf("test: exit rc522_fd\n"); 
  80.          return 0; 
  81. }


應用程式編譯的Makefile 如下:

 

 

點擊(此處)摺疊或開啟

  1. # Comment/uncomment the following line to disable/enable debugging 
  2. #DEBUG = y 
  3. DEST_BIN_DIR= drivers/ 
  4. EXTRA_CFLAGS += -D_V3 
  5. #TESTFLAGS = -D_V3 
  6. # Add your debugging flag (or not) to CFLAGS 
  7. ifeq ($(DEBUG),y) 
  8.   DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines 
  9. else 
  10.   DEBFLAGS = -O2 
  11. endif 
  12. EXTRA_CFLAGS += $(DEBFLAGS) 
  13. EXTRA_CFLAGS += -I$(LDDINC) 
  14. EXTRA_CFLAGS += -DREV_VERSION=$(REV_VERSION) 
  15. LDFLAGS += --static 
  16. all: test 
  17. clean: 
  18.          rm -rf test_rc522 
  19.          
  20. cp: 
  21.          cp -f test_rc522 $(DEST_BIN_DIR) 
  22. mv: 
  23.          mv -f test_rc522 $(DEST_BIN_DIR) 
  24. test: 
  25.          arm-linux-gcc $(CFLAGS) $(LDFLAGS) -O2 test_rc522.c -o test_rc522 
  26. depend .depend dep: 
  27.          $(CC) $(CFLAGS) -M *.c > .depend 
  28. ifeq (.depend,$(wildcard .depend)) 
  29. include .depend 
  30. endif


測試時,把卡靠近RC522的天線地區,即可正常讀到卡ID。

 

 

 

五,總結

本次調試比較順利,遇到幾個比較大的問題如下:

1 SMDK開發板SPI0通訊有問題,開始一直以為驅動的問題,也不知道應該如何測試開發板SPI介面是否OK,在網上找了一些資料後發現SPI驅動可以通過核心內建的驅動模組和應用程式進行測試。

2 應用程式(測試程式)無法在開發板系統上運行,原因是連結庫未設定成靜態。

3 RC522中的VCC供電需要3.3V,MOSI,CLK等TTL高電平也是3.3V。但4412主控的GPIO輸出的高電平全部是1.8V,故模組無法正常工作。由於是調試,故不可能加一個TTL電平轉換的IC了。後來試著把VCC調低到2.6V,結果模組可以正常工作了。

 

                                          (轉載)

RC 522模組在LINUX平台調試筆記

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.