当前位置:   article > 正文

RK3568笔记五十:SPI通信-回环测试

RK3568笔记五十:SPI通信-回环测试

若该文为原创文章,转载请注明原文出处。

一、SPI引脚关系

其中SPI1的引脚关系如下表所示

SPI

引脚

功能

MOSI

GPIO3_C1

主设备输出/从设备输入

MISO

GPIO3_C2

主设备输入/从设备输出

CLOCK

CPIO3_C3

时钟信号线

CS0

GPIO3_A1

片选信号线0

CS1

NC

片选信号线1

二、内核和设备树配置

正点原子的内核已经配置了SPI设备驱动,可以不在配置内核但需要配置设备树。

为了学习和了解,还是要知道SPI设备驱动内核是如何配置的。

1、内核支持

进入kenel目录,make menuconfig

具体路径如下所示:

> Device Drivers

 > SPI support

2、设备树配置

修改/home/alientek/rk3568_linux_sdk/kernel/arch/arm64/boot/dts/rockchip/目录下的rk3568-atk-evb1-ddr4-v10.dtsi文件,在文件末添加代码,在spi1设备树下添加w25q64节点。

  1. &spi1 {
  2. status = "okay";
  3. pinctrl-0 = <&spi1m1_cs0 &spi1m1_pins>;
  4. pinctrl-1 = <&spi1m1_cs0 &spi1m1_pins_hs>;
  5. // 向 spi1 节点追加 w25q64 设备节点
  6. w25q64: w25q64@0 {
  7. compatible = "rockchip,spidev";
  8. reg = <0>; // 设置 reg 属性为 0, 表示 spi 连接到 spi1 的通道 0
  9. spi-max-frequency = <24000000>; // 设置 SPI 传输的最大频率
  10. status = "okay";
  11. };
  12. };

和上一篇有点区别,上一篇的compatible是自己写的,驱动需要自己编写,这里使用内核自带的,所以改成内核支持的,在linux/drivers/spi/spidev.c 可以看出是rockchip,spidev.

修改完成以后,重新编译一下内核,并烧写boot.img文件

重启板子后,查询,可以看到spidev1.0,其中1是spi1,0是cs0

三、回环测试

1、接线

根据ioctl相关参数即可编写spi相关测试程序,为了简单仅做回环测试实验, 只需要将SPI1的 MIOS与MOSI引脚使用跳线帽短接即可。即7和9短路。

2、测试程序

  1. #include <sys/ioctl.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <linux/spi/spidev.h>
  10. #define SPI_DEV_PATH "/dev/spidev1.0"
  11. /*SPI 接收 、发送 缓冲区*/
  12. unsigned char tx_buffer[100] = "hello the world !";
  13. unsigned char rx_buffer[100];
  14. int fd; // SPI 控制引脚的设备文件描述符
  15. static unsigned mode = SPI_MODE_2; //用于保存 SPI 工作模式
  16. static uint8_t bits = 8; // 接收、发送数据位数
  17. static uint32_t speed = 10000000; // 发送速度
  18. static uint16_t delay; //保存延时时间
  19. void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
  20. {
  21. int ret;
  22. struct spi_ioc_transfer tr = {
  23. .tx_buf = (unsigned long)tx,
  24. .rx_buf = (unsigned long)rx,
  25. .len = len,
  26. .delay_usecs = delay,
  27. .speed_hz = speed,
  28. .bits_per_word = bits,
  29. .tx_nbits = 1,
  30. .rx_nbits = 1
  31. };
  32. ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
  33. if (ret < 1)
  34. printf("can't send spi message\n");
  35. }
  36. void spi_init(int fd)
  37. {
  38. int ret = 0;
  39. // spi mode 设置SPI 工作模式
  40. ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
  41. if (ret == -1)
  42. printf("can't set spi mode\n");
  43. // bits per word 设置一个字节的位数
  44. ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
  45. if (ret == -1)
  46. printf("can't set bits per word\n");
  47. // max speed hz 设置SPI 最高工作频率
  48. ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
  49. if (ret == -1)
  50. printf("can't set max speed hz\n");
  51. // 打印
  52. printf("spi mode: 0x%x\n", mode);
  53. printf("bits per word: %d\n", bits);
  54. printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
  55. }
  56. int main(int argc, char *argv[])
  57. {
  58. int fd;
  59. if(argc < 2){
  60. printf("Wrong use !!!!\n");
  61. printf("Usage: %s [dev]\n",argv[0]);
  62. return -1;
  63. }
  64. /*打开 SPI 设备*/
  65. fd = open(argv[1], O_RDWR); // open file and enable read and write
  66. if (fd < 0){
  67. printf("Can't open %s \n",argv[1]); // open i2c dev file fail
  68. exit(1);
  69. }
  70. /*初始化SPI */
  71. spi_init(fd);
  72. /*执行发送*/
  73. transfer(fd, tx_buffer, rx_buffer, sizeof(tx_buffer));
  74. /*打印 tx_buffer 和 rx_buffer*/
  75. printf("tx_buffer: \n %s\n ", tx_buffer);
  76. printf("rx_buffer: \n %s\n ", rx_buffer);
  77. close(fd);
  78. return 0;
  79. }

编译

/opt/atk-dlrk356x-toolchain/bin/aarch64-buildroot-linux-gnu-gcc spi_selftest.c -o spi_selftest

在板子上运行测试:

 ./spi_selftest /dev/spidev1.0

此实验弥补了上一篇的遗憾,接下来编写W25Q64的测试程序,使用SPI测试,另GPIO模拟SPI要怎么处理?

如有侵权,或需要完整代码,请及时联系博主。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/921874
推荐阅读
相关标签
  

闽ICP备14008679号