你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】基于STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片

[复制链接]
STMCU小助手 发布时间:2022-4-9 22:59
STM32基础工程生成
首先使用STM32CUBEMX生成STM32的基础工程,配置时钟到72M主频:

20210712163230798.png

配置SPI前,首先查看WK2124的芯片手册,手册里面说明了WK2124的SPI最高支持到10M并且使用SPI模式0,SPI的模式0就是时钟空闲电平为低电平且在第一个时钟延采样:

9W47%D}PLND[Y8HO8C05BXS.png

所以STM32CUBEMX需要这样配置:

W]TW7XP@HG4%Q1V_Q{{B.png

IO配置:
WK2124的硬件复位引脚,这个引脚最好接上,使用STM32的IO进行控制
WK2124的片选引脚
如果用WK2124的中断,那么还需要配置一个IO为外部中断
WK2124驱动代码

代码已经测试通过无问题,贴一下:

头文件
  1. /*
  2. * wk2xxx.h
  3. *
  4. *  Created on: Jun 17, 2021
  5. *      Author: hello
  6. */

  7. #ifndef SRC_WK2XXX_H_
  8. #define SRC_WK2XXX_H_

  9. #include "main.h"


  10. #define         WK2XXX_GENA     0X00
  11. #define         WK2XXX_GRST     0X01
  12. #define                WK2XXX_GMUT     0X02
  13. #define         WK2XXX_GIER     0X10
  14. #define         WK2XXX_GIFR     0X11
  15. #define         WK2XXX_GPDIR    0X21
  16. #define         WK2XXX_GPDAT    0X31
  17. //wkxxxx  slave uarts  rigister address defines

  18. #define         WK2XXX_SPAGE    0X03
  19. //PAGE0
  20. #define         WK2XXX_SCR      0X04
  21. #define         WK2XXX_LCR      0X05
  22. #define         WK2XXX_FCR      0X06
  23. #define         WK2XXX_SIER     0X07
  24. #define         WK2XXX_SIFR     0X08
  25. #define         WK2XXX_TFCNT    0X09
  26. #define         WK2XXX_RFCNT    0X0A
  27. #define         WK2XXX_FSR      0X0B
  28. #define         WK2XXX_LSR      0X0C
  29. #define         WK2XXX_FDAT     0X0D
  30. #define         WK2XXX_FWCR     0X0E
  31. #define         WK2XXX_RS485    0X0F
  32. //PAGE1
  33. #define         WK2XXX_BAUD1    0X04
  34. #define         WK2XXX_BAUD0    0X05
  35. #define         WK2XXX_PRES     0X06
  36. #define         WK2XXX_RFTL     0X07
  37. #define         WK2XXX_TFTL     0X08
  38. #define         WK2XXX_FWTH     0X09
  39. #define         WK2XXX_FWTL     0X0A
  40. #define         WK2XXX_XON1     0X0B
  41. #define         WK2XXX_XOFF1    0X0C
  42. #define         WK2XXX_SADR     0X0D
  43. #define         WK2XXX_SAEN     0X0E
  44. #define         WK2XXX_RTSDLY   0X0F

  45. //WK串口扩展芯片的寄存器的位定义
  46. //wkxxx register bit defines
  47. // GENA
  48. #define         WK2XXX_UT4EN        0x08
  49. #define         WK2XXX_UT3EN        0x04
  50. #define         WK2XXX_UT2EN        0x02
  51. #define         WK2XXX_UT1EN        0x01
  52. //GRST
  53. #define         WK2XXX_UT4SLEEP        0x80
  54. #define         WK2XXX_UT3SLEEP        0x40
  55. #define         WK2XXX_UT2SLEEP        0x20
  56. #define         WK2XXX_UT1SLEEP        0x10
  57. #define         WK2XXX_UT4RST        0x08
  58. #define         WK2XXX_UT3RST        0x04
  59. #define         WK2XXX_UT2RST        0x02
  60. #define         WK2XXX_UT1RST        0x01
  61. //GIER
  62. #define         WK2XXX_UT4IE        0x08
  63. #define         WK2XXX_UT3IE        0x04
  64. #define         WK2XXX_UT2IE        0x02
  65. #define         WK2XXX_UT1IE        0x01
  66. //GIFR
  67. #define         WK2XXX_UT4INT        0x08
  68. #define         WK2XXX_UT3INT        0x04
  69. #define         WK2XXX_UT2INT        0x02
  70. #define         WK2XXX_UT1INT        0x01
  71. //SPAGE
  72. #define         WK2XXX_SPAGE0          0x00
  73. #define         WK2XXX_SPAGE1   0x01
  74. //SCR
  75. #define         WK2XXX_SLEEPEN        0x04
  76. #define         WK2XXX_TXEN     0x02
  77. #define         WK2XXX_RXEN     0x01
  78. //LCR
  79. #define         WK2XXX_BREAK          0x20
  80. #define         WK2XXX_IREN     0x10
  81. #define         WK2XXX_PAEN     0x08
  82. #define         WK2XXX_PAM1     0x04
  83. #define         WK2XXX_PAM0     0x02
  84. #define         WK2XXX_STPL     0x01
  85. //FCR
  86. //SIER
  87. #define         WK2XXX_FERR_IEN      0x80
  88. #define         WK2XXX_CTS_IEN       0x40
  89. #define         WK2XXX_RTS_IEN       0x20
  90. #define         WK2XXX_XOFF_IEN      0x10
  91. #define         WK2XXX_TFEMPTY_IEN   0x08
  92. #define         WK2XXX_TFTRIG_IEN    0x04
  93. #define         WK2XXX_RXOUT_IEN     0x02
  94. #define         WK2XXX_RFTRIG_IEN    0x01
  95. //SIFR
  96. #define         WK2XXX_FERR_INT      0x80
  97. #define         WK2XXX_CTS_INT       0x40
  98. #define         WK2XXX_RTS_INT       0x20
  99. #define         WK2XXX_XOFF_INT      0x10
  100. #define         WK2XXX_TFEMPTY_INT   0x08
  101. #define         WK2XXX_TFTRIG_INT    0x04
  102. #define         WK2XXX_RXOVT_INT     0x02
  103. #define         WK2XXX_RFTRIG_INT    0x01


  104. //TFCNT
  105. //RFCNT
  106. //FSR
  107. #define         WK2XXX_RFOE     0x80
  108. #define         WK2XXX_RFBI     0x40
  109. #define         WK2XXX_RFFE     0x20
  110. #define         WK2XXX_RFPE     0x10
  111. #define         WK2XXX_RDAT     0x08
  112. #define         WK2XXX_TDAT     0x04
  113. #define         WK2XXX_TFULL    0x02
  114. #define         WK2XXX_TBUSY    0x01
  115. //LSR
  116. #define         WK2XXX_OE       0x08
  117. #define         WK2XXX_BI       0x04
  118. #define         WK2XXX_FE       0x02
  119. #define         WK2XXX_PE       0x01
  120. //FWCR

  121. uint16_t WK_PortSendData(uint8_t port, const void* buf, uint16_t len);
  122. uint16_t WK_PortRecvData(uint8_t port, void* buf, uint16_t len);
  123. void WK_PortInit(uint8_t port, uint32_t fosc, uint32_t baudrate);
  124. void WK_IRQHandler(void);
  125. void WK_Rst(void);

  126. #endif /* SRC_WK2XXX_H_ */
复制代码

源文件
  1. /*
  2. * wk2xxx.c
  3. *
  4. *  Created on: Jun 17, 2021
  5. *      Author: hello
  6. */

  7. #include "wk2xxx.h"
  8. #include "spi.h"


  9. //
  10. ///
  11. ///                            移植修改区域
  12. ///
  13. //

  14. /// HAL库SPI句柄
  15. #define WK_SPI_Handle (&hspi2)

  16. // 拉低RST引脚
  17. #define WK_GPIO_RST_L()    HAL_GPIO_WritePin(WK2124_RST1_GPIO_Port, WK2124_RST1_Pin, GPIO_PIN_RESET)

  18. // 拉高RST引脚
  19. #define WK_GPIO_RST_H()    HAL_GPIO_WritePin(WK2124_RST1_GPIO_Port, WK2124_RST1_Pin, GPIO_PIN_SET)

  20. // 片选引脚拉低
  21. #define WK_GPIO_SEL_L()    HAL_GPIO_WritePin(WK2124_CS1_GPIO_Port, WK2124_CS1_Pin, GPIO_PIN_RESET)

  22. // 片选引脚拉高
  23. #define WK_GPIO_SEL_H()    HAL_GPIO_WritePin(WK2124_CS1_GPIO_Port, WK2124_CS1_Pin, GPIO_PIN_SET)


  24. static void wk_delay_ms(uint32_t nms)
  25. {
  26.         HAL_Delay(nms);
  27. }

  28. static uint8_t WK_SPI_ReadWriteByte(uint8_t TxData)
  29. {
  30.         uint8_t RxData = 0X00;
  31.         if (HAL_SPI_TransmitReceive(WK_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK)
  32.         {
  33.                 RxData = 0XFF;
  34.         }
  35.         return RxData;
  36. }




  37. //
  38. ///
  39. ///                            驱动程序代码
  40. ///
  41. //



  42. /// 硬件复位(拉低复位引脚最低10毫秒进行复位)
  43. void WK_Rst(void)
  44. {
  45.         WK_GPIO_RST_L();
  46.         wk_delay_ms(50);
  47.         WK_GPIO_RST_H();
  48.         wk_delay_ms(50);
  49. }

  50. void WK_WriteGReg(uint8_t reg, uint8_t value)
  51. {
  52.         WK_GPIO_SEL_L();
  53.         WK_SPI_ReadWriteByte(reg);
  54.         WK_SPI_ReadWriteByte(value);
  55.         WK_GPIO_SEL_H();
  56. }

  57. uint8_t WK_ReadGReg(uint8_t reg)
  58. {
  59.         uint8_t value = 0X00;
  60.         WK_GPIO_SEL_L();
  61.         WK_SPI_ReadWriteByte(0X40 | reg);
  62.         value = WK_SPI_ReadWriteByte(0X00);
  63.         WK_GPIO_SEL_H();
  64.         return value;
  65. }

  66. void WK_WriteSReg(uint8_t port, uint8_t reg, uint8_t value)
  67. {
  68.         WK_GPIO_SEL_L();
  69.         WK_SPI_ReadWriteByte(((port - 1) << 4) | reg);
  70.         WK_SPI_ReadWriteByte(value);
  71.         WK_GPIO_SEL_H();
  72. }

  73. uint8_t WK_ReadSReg(uint8_t port, uint8_t reg)
  74. {
  75.         uint8_t value = 0X00;
  76.         WK_GPIO_SEL_L();
  77.         WK_SPI_ReadWriteByte(0X40 | ((port - 1) << 4) | reg);
  78.         value = WK_SPI_ReadWriteByte(0X00);
  79.         WK_GPIO_SEL_H();
  80.         return value;
  81. }

  82. void WK_WriteFIFO(uint8_t port, const void* buf, uint16_t len)
  83. {
  84.         const uint8_t* p = (const uint8_t *)buf;
  85.         WK_GPIO_SEL_L();
  86.         WK_SPI_ReadWriteByte(0X80 | ((port - 1) << 4));
  87.         while (len--)
  88.         {
  89.                 WK_SPI_ReadWriteByte(*p++);
  90.         }
  91.         WK_GPIO_SEL_H();
  92. }

  93. void WK_ReadFIFO(uint8_t port, void* buf, uint16_t len)
  94. {
  95.         uint8_t* p = (uint8_t *)buf;
  96.         WK_GPIO_SEL_L();
  97.         WK_SPI_ReadWriteByte(0XC0 | ((port - 1) << 4));
  98.         while (len--)
  99.         {
  100.                 *p++ = WK_SPI_ReadWriteByte(0X00);
  101.         }
  102.         WK_GPIO_SEL_H();
  103. }

  104. void WK_PortCalcBaudrate(uint32_t fosc, uint32_t baudrate, uint8_t* BAUD0, uint8_t* BAUD1, uint8_t* PRES)
  105. {
  106.         float value = (float)fosc / (float)(baudrate << 4);
  107.         *BAUD0 = (((uint32_t)value) - 1) & 0XFF;
  108.         *BAUD1 = ((((uint32_t)value) - 1) >> 8) & 0XFF;
  109.         *PRES  = ((uint32_t)(value * 10)) % 10;
  110. }

  111. uint16_t WK_PortSendData(uint8_t port, const void* buf, uint16_t len)
  112. {
  113.         uint8_t  state = 0;
  114.         uint16_t nsend = 0;
  115.         state = WK_ReadSReg(port, WK2XXX_FSR);
  116.         if (state & WK2XXX_TFULL)                    // 发送FIFO满
  117.         {
  118.                 nsend = 0;
  119.         } else
  120.         {
  121.                 state = WK_ReadSReg(port, WK2XXX_TFCNT); // 读取发送FIFO已用空间
  122.                 nsend = 256 - state;
  123.                 nsend = nsend >= len ? len : nsend;
  124.                 WK_WriteFIFO(port, buf, nsend);          // 将待发送的数据写入FIFO
  125.         }
  126.         return nsend;                                // 返回实际发送成功的数据量
  127. }

  128. uint16_t WK_PortRecvData(uint8_t port, void* buf, uint16_t len)
  129. {
  130.         uint8_t state = 0;
  131.         uint8_t nread = 0;
  132.         state = WK_ReadSReg(port, WK2XXX_FSR);
  133.         if (state & WK2XXX_RDAT)                      // 接收FIFO非空
  134.         {
  135.                 nread = WK_ReadSReg(port, WK2XXX_RFCNT);  // 查询FIFO中的数据量
  136.                 nread = len >= nread ? nread : len;
  137.                 WK_ReadFIFO(port, buf, nread);            // 读取FIFO中的数据
  138.         }
  139.         return nread;                                 // 返回实际读取到的数据量
  140. }

  141. void WK_PortInit(uint8_t port, uint32_t fosc, uint32_t baudrate)
  142. {
  143.         uint8_t BAUD0 = 0, BAUD1 = 0, PRES = 0, value = 0, ret = 0;

  144.         //
  145.         // 使能子串口时钟
  146.         //
  147.         value = WK_ReadGReg(WK2XXX_GENA);
  148.         value |= (1 << (port - 1));
  149.         WK_WriteGReg(WK2XXX_GENA, value);
  150.         ret = WK_ReadGReg(WK2XXX_GENA);

  151.         //
  152.         // 软件复位子串口
  153.         //
  154.         value = WK_ReadGReg(WK2XXX_GRST);
  155.         value |= (1 << (port - 1));
  156.         WK_WriteGReg(WK2XXX_GRST, value);
  157.         ret = WK_ReadGReg(WK2XXX_GRST);

  158.         //
  159.         // 使能子串口总中断
  160.         //
  161.         value = WK_ReadGReg(WK2XXX_GIER);
  162.         value |= (1 << (port - 1));
  163.         WK_WriteGReg(WK2XXX_GIER, value);
  164.         ret = WK_ReadGReg(WK2XXX_GIER);

  165.         //
  166.         // 使能子串口FIFO相关中断
  167.         //
  168.         value = WK_ReadSReg(port, WK2XXX_SIER);
  169.         value |= WK2XXX_RFTRIG_IEN;                  // 接收FIFO触点中断
  170. //        value |= WK2XXX_TFTRIG_IEN;                  // 发送FIFO触点中断
  171. //        value |= WK2XXX_RXOUT_IEN;                   // 接收FIFO超时中断
  172.         WK_WriteSReg(port, WK2XXX_SIER, value);
  173.         ret = WK_ReadSReg(port, WK2XXX_SIER);

  174.         //
  175.         // 设置FCR寄存器
  176.         //
  177.         value = 0;
  178.         value |= (1 << 0);  // 复位接收FIFO
  179.         value |= (1 << 1);  // 复位发送FIFO
  180.         value |= (1 << 2);  // 使能接收FIFO(这一步必须)
  181.         value |= (1 << 3);  // 使能发送FIFO(这一步必须)
  182.         value |= (0 << 4);  // 设置接收FIFO触点固定为8字节
  183.         value |= (0 << 6);  // 设置发送FIFO触点固定为8字节
  184.         WK_WriteSReg(port, WK2XXX_FCR, value);
  185.         ret = WK_ReadSReg(port, WK2XXX_FCR);

  186.         //
  187.         // 切换到page1设置中断触点和波特率
  188.         //
  189.         WK_WriteSReg(port, WK2XXX_SPAGE, 1);
  190.         ret = WK_ReadSReg(port, WK2XXX_SPAGE);

  191.         WK_WriteSReg(port, WK2XXX_RFTL, 10);      // 设置接收触点为10个字节
  192.         ret = WK_ReadSReg(port, WK2XXX_RFTL);

  193.         WK_WriteSReg(port, WK2XXX_TFTL, 10);      // 设置发送触点为10个字节
  194.         ret = WK_ReadSReg(port, WK2XXX_TFTL);

  195.         WK_PortCalcBaudrate(fosc, baudrate, &BAUD0, &BAUD1, &PRES);  // 计算波特率

  196.         WK_WriteSReg(port, WK2XXX_BAUD1, BAUD1);  // 设置BAUD1
  197.         ret = WK_ReadSReg(port, WK2XXX_BAUD1);

  198.         WK_WriteSReg(port, WK2XXX_BAUD0, BAUD0);  // 设置BAUD0
  199.         ret = WK_ReadSReg(port, WK2XXX_BAUD0);

  200.         WK_WriteSReg(port, WK2XXX_PRES, PRES);    // 设置PRES
  201.         ret = WK_ReadSReg(port, WK2XXX_PRES);

  202.         //
  203.         // 切换回page0
  204.         //
  205.         WK_WriteSReg(port, WK2XXX_SPAGE, 0);
  206.         ret = WK_ReadSReg(port, WK2XXX_SPAGE);

  207.         //
  208.         // 使能子串口收发
  209.         //
  210.         value = WK_ReadSReg(port, WK2XXX_SCR);
  211.         value |= WK2XXX_TXEN;
  212.         value |= WK2XXX_RXEN;
  213.         WK_WriteSReg(port, WK2XXX_SCR, value);
  214.         ret = WK_ReadSReg(port, WK2XXX_SCR);
  215. }


  216. // 如果irq引脚接入了单片机的外部中断引脚,将该函数放入外部中断处理函数内。
  217. // 对于WK2124所开启的中断可以这么处理:
  218. void WK_IRQHandler(void)
  219. {
  220.         int i = 0;
  221.         uint8_t GIFR = 0, SIFR = 0;

  222.         // 读取子串口全局中断寄存器
  223.         GIFR = WK_ReadGReg(WK2XXX_GIFR);

  224.         // 查询4个子串口是否发生中断
  225.         for (i = 0; i < 4; i++)
  226.         {
  227.                 if ((GIFR >> i) & 0X01)
  228.                 {
  229.                         SIFR = WK_ReadSReg((i + 1), WK2XXX_SIFR);

  230.                         // 有接收FIFO触点中断
  231.                         if (SIFR & WK2XXX_RFTRIG_INT)
  232.                         {
  233.                                 // 调用WK_PortRecvData接收数据
  234.                         }

  235.                         // 有接收FIFO超时中断
  236.                         if (SIFR & WK2XXX_RXOVT_INT)
  237.                         {

  238.                         }

  239.                         // 有发送FIFO触点中断
  240.                         if (SIFR & WK2XXX_TFTRIG_INT)
  241.                         {

  242.                         }

  243.                         // 有发送FIFO空中断
  244.                         if (SIFR & WK2XXX_TFEMPTY_INT)
  245.                         {

  246.                         }

  247.                         // 有接收FIFO数据错误中断
  248.                         if (SIFR & WK2XXX_FERR_INT)
  249.                         {

  250.                         }
  251.                 }
  252.         }
  253. }

  254. /*

  255. int main()
  256. {
  257.         int nrecv = 0;
  258.         uint8_t buffer[256];
  259.         
  260.         // 硬件复位一下
  261.         WK_Rst();
  262.         
  263.         // 初始化四个端口
  264.         WK_PortInit(1, 11059200, 9600);  // WK2124晶振我用的是11.0592MHz的,这个值根据实际进行修改
  265.         WK_PortInit(2, 11059200, 9600);
  266.         WK_PortInit(3, 11059200, 9600);
  267.         WK_PortInit(4, 11059200, 9600);
  268.         
  269.         // 发送数据
  270.         WK_PortSendData(1, "helloworld\r\n", 12);
  271.         WK_PortSendData(2, "helloworld\r\n", 12);
  272.         WK_PortSendData(3, "helloworld\r\n", 12);
  273.         WK_PortSendData(4, "helloworld\r\n", 12);
  274.         
  275.         // 接收数据,轮训方式
  276.         nrecv = WK_PortRecvData(1, buffer, sizeof(buffer));
  277.         
  278.         if(nrecv != 0)
  279.         {
  280.                 // 处理数据
  281.         }
  282.         
  283. }

  284. */






复制代码


收藏 评论0 发布时间:2022-4-9 22:59

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版