STM32基础工程生成
首先使用STM32CUBEMX生成STM32的基础工程,配置时钟到72M主频:
配置SPI前,首先查看WK2124的芯片手册,手册里面说明了WK2124的SPI最高支持到10M并且使用SPI模式0,SPI的模式0就是时钟空闲电平为低电平且在第一个时钟延采样:
所以STM32CUBEMX需要这样配置:
IO配置:
WK2124的硬件复位引脚,这个引脚最好接上,使用STM32的IO进行控制
WK2124的片选引脚
如果用WK2124的中断,那么还需要配置一个IO为外部中断
WK2124驱动代码
代码已经测试通过无问题,贴一下:
头文件
源文件
- /*
- * wk2xxx.c
- *
- * Created on: Jun 17, 2021
- * Author: hello
- */
- #include "wk2xxx.h"
- #include "spi.h"
- //
- ///
- /// 移植修改区域
- ///
- //
- /// HAL库SPI句柄
- #define WK_SPI_Handle (&hspi2)
- // 拉低RST引脚
- #define WK_GPIO_RST_L() HAL_GPIO_WritePin(WK2124_RST1_GPIO_Port, WK2124_RST1_Pin, GPIO_PIN_RESET)
- // 拉高RST引脚
- #define WK_GPIO_RST_H() HAL_GPIO_WritePin(WK2124_RST1_GPIO_Port, WK2124_RST1_Pin, GPIO_PIN_SET)
- // 片选引脚拉低
- #define WK_GPIO_SEL_L() HAL_GPIO_WritePin(WK2124_CS1_GPIO_Port, WK2124_CS1_Pin, GPIO_PIN_RESET)
- // 片选引脚拉高
- #define WK_GPIO_SEL_H() HAL_GPIO_WritePin(WK2124_CS1_GPIO_Port, WK2124_CS1_Pin, GPIO_PIN_SET)
- static void wk_delay_ms(uint32_t nms)
- {
- HAL_Delay(nms);
- }
- static uint8_t WK_SPI_ReadWriteByte(uint8_t TxData)
- {
- uint8_t RxData = 0X00;
- if (HAL_SPI_TransmitReceive(WK_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK)
- {
- RxData = 0XFF;
- }
- return RxData;
- }
- //
- ///
- /// 驱动程序代码
- ///
- //
- /// 硬件复位(拉低复位引脚最低10毫秒进行复位)
- void WK_Rst(void)
- {
- WK_GPIO_RST_L();
- wk_delay_ms(50);
- WK_GPIO_RST_H();
- wk_delay_ms(50);
- }
- void WK_WriteGReg(uint8_t reg, uint8_t value)
- {
- WK_GPIO_SEL_L();
- WK_SPI_ReadWriteByte(reg);
- WK_SPI_ReadWriteByte(value);
- WK_GPIO_SEL_H();
- }
- uint8_t WK_ReadGReg(uint8_t reg)
- {
- uint8_t value = 0X00;
- WK_GPIO_SEL_L();
- WK_SPI_ReadWriteByte(0X40 | reg);
- value = WK_SPI_ReadWriteByte(0X00);
- WK_GPIO_SEL_H();
- return value;
- }
- void WK_WriteSReg(uint8_t port, uint8_t reg, uint8_t value)
- {
- WK_GPIO_SEL_L();
- WK_SPI_ReadWriteByte(((port - 1) << 4) | reg);
- WK_SPI_ReadWriteByte(value);
- WK_GPIO_SEL_H();
- }
- uint8_t WK_ReadSReg(uint8_t port, uint8_t reg)
- {
- uint8_t value = 0X00;
- WK_GPIO_SEL_L();
- WK_SPI_ReadWriteByte(0X40 | ((port - 1) << 4) | reg);
- value = WK_SPI_ReadWriteByte(0X00);
- WK_GPIO_SEL_H();
- return value;
- }
- void WK_WriteFIFO(uint8_t port, const void* buf, uint16_t len)
- {
- const uint8_t* p = (const uint8_t *)buf;
- WK_GPIO_SEL_L();
- WK_SPI_ReadWriteByte(0X80 | ((port - 1) << 4));
- while (len--)
- {
- WK_SPI_ReadWriteByte(*p++);
- }
- WK_GPIO_SEL_H();
- }
- void WK_ReadFIFO(uint8_t port, void* buf, uint16_t len)
- {
- uint8_t* p = (uint8_t *)buf;
- WK_GPIO_SEL_L();
- WK_SPI_ReadWriteByte(0XC0 | ((port - 1) << 4));
- while (len--)
- {
- *p++ = WK_SPI_ReadWriteByte(0X00);
- }
- WK_GPIO_SEL_H();
- }
- void WK_PortCalcBaudrate(uint32_t fosc, uint32_t baudrate, uint8_t* BAUD0, uint8_t* BAUD1, uint8_t* PRES)
- {
- float value = (float)fosc / (float)(baudrate << 4);
- *BAUD0 = (((uint32_t)value) - 1) & 0XFF;
- *BAUD1 = ((((uint32_t)value) - 1) >> 8) & 0XFF;
- *PRES = ((uint32_t)(value * 10)) % 10;
- }
- uint16_t WK_PortSendData(uint8_t port, const void* buf, uint16_t len)
- {
- uint8_t state = 0;
- uint16_t nsend = 0;
- state = WK_ReadSReg(port, WK2XXX_FSR);
- if (state & WK2XXX_TFULL) // 发送FIFO满
- {
- nsend = 0;
- } else
- {
- state = WK_ReadSReg(port, WK2XXX_TFCNT); // 读取发送FIFO已用空间
- nsend = 256 - state;
- nsend = nsend >= len ? len : nsend;
- WK_WriteFIFO(port, buf, nsend); // 将待发送的数据写入FIFO
- }
- return nsend; // 返回实际发送成功的数据量
- }
- uint16_t WK_PortRecvData(uint8_t port, void* buf, uint16_t len)
- {
- uint8_t state = 0;
- uint8_t nread = 0;
- state = WK_ReadSReg(port, WK2XXX_FSR);
- if (state & WK2XXX_RDAT) // 接收FIFO非空
- {
- nread = WK_ReadSReg(port, WK2XXX_RFCNT); // 查询FIFO中的数据量
- nread = len >= nread ? nread : len;
- WK_ReadFIFO(port, buf, nread); // 读取FIFO中的数据
- }
- return nread; // 返回实际读取到的数据量
- }
- void WK_PortInit(uint8_t port, uint32_t fosc, uint32_t baudrate)
- {
- uint8_t BAUD0 = 0, BAUD1 = 0, PRES = 0, value = 0, ret = 0;
- //
- // 使能子串口时钟
- //
- value = WK_ReadGReg(WK2XXX_GENA);
- value |= (1 << (port - 1));
- WK_WriteGReg(WK2XXX_GENA, value);
- ret = WK_ReadGReg(WK2XXX_GENA);
- //
- // 软件复位子串口
- //
- value = WK_ReadGReg(WK2XXX_GRST);
- value |= (1 << (port - 1));
- WK_WriteGReg(WK2XXX_GRST, value);
- ret = WK_ReadGReg(WK2XXX_GRST);
- //
- // 使能子串口总中断
- //
- value = WK_ReadGReg(WK2XXX_GIER);
- value |= (1 << (port - 1));
- WK_WriteGReg(WK2XXX_GIER, value);
- ret = WK_ReadGReg(WK2XXX_GIER);
- //
- // 使能子串口FIFO相关中断
- //
- value = WK_ReadSReg(port, WK2XXX_SIER);
- value |= WK2XXX_RFTRIG_IEN; // 接收FIFO触点中断
- // value |= WK2XXX_TFTRIG_IEN; // 发送FIFO触点中断
- // value |= WK2XXX_RXOUT_IEN; // 接收FIFO超时中断
- WK_WriteSReg(port, WK2XXX_SIER, value);
- ret = WK_ReadSReg(port, WK2XXX_SIER);
- //
- // 设置FCR寄存器
- //
- value = 0;
- value |= (1 << 0); // 复位接收FIFO
- value |= (1 << 1); // 复位发送FIFO
- value |= (1 << 2); // 使能接收FIFO(这一步必须)
- value |= (1 << 3); // 使能发送FIFO(这一步必须)
- value |= (0 << 4); // 设置接收FIFO触点固定为8字节
- value |= (0 << 6); // 设置发送FIFO触点固定为8字节
- WK_WriteSReg(port, WK2XXX_FCR, value);
- ret = WK_ReadSReg(port, WK2XXX_FCR);
- //
- // 切换到page1设置中断触点和波特率
- //
- WK_WriteSReg(port, WK2XXX_SPAGE, 1);
- ret = WK_ReadSReg(port, WK2XXX_SPAGE);
- WK_WriteSReg(port, WK2XXX_RFTL, 10); // 设置接收触点为10个字节
- ret = WK_ReadSReg(port, WK2XXX_RFTL);
- WK_WriteSReg(port, WK2XXX_TFTL, 10); // 设置发送触点为10个字节
- ret = WK_ReadSReg(port, WK2XXX_TFTL);
- WK_PortCalcBaudrate(fosc, baudrate, &BAUD0, &BAUD1, &PRES); // 计算波特率
- WK_WriteSReg(port, WK2XXX_BAUD1, BAUD1); // 设置BAUD1
- ret = WK_ReadSReg(port, WK2XXX_BAUD1);
- WK_WriteSReg(port, WK2XXX_BAUD0, BAUD0); // 设置BAUD0
- ret = WK_ReadSReg(port, WK2XXX_BAUD0);
- WK_WriteSReg(port, WK2XXX_PRES, PRES); // 设置PRES
- ret = WK_ReadSReg(port, WK2XXX_PRES);
- //
- // 切换回page0
- //
- WK_WriteSReg(port, WK2XXX_SPAGE, 0);
- ret = WK_ReadSReg(port, WK2XXX_SPAGE);
- //
- // 使能子串口收发
- //
- value = WK_ReadSReg(port, WK2XXX_SCR);
- value |= WK2XXX_TXEN;
- value |= WK2XXX_RXEN;
- WK_WriteSReg(port, WK2XXX_SCR, value);
- ret = WK_ReadSReg(port, WK2XXX_SCR);
- }
- // 如果irq引脚接入了单片机的外部中断引脚,将该函数放入外部中断处理函数内。
- // 对于WK2124所开启的中断可以这么处理:
- void WK_IRQHandler(void)
- {
- int i = 0;
- uint8_t GIFR = 0, SIFR = 0;
- // 读取子串口全局中断寄存器
- GIFR = WK_ReadGReg(WK2XXX_GIFR);
- // 查询4个子串口是否发生中断
- for (i = 0; i < 4; i++)
- {
- if ((GIFR >> i) & 0X01)
- {
- SIFR = WK_ReadSReg((i + 1), WK2XXX_SIFR);
- // 有接收FIFO触点中断
- if (SIFR & WK2XXX_RFTRIG_INT)
- {
- // 调用WK_PortRecvData接收数据
- }
- // 有接收FIFO超时中断
- if (SIFR & WK2XXX_RXOVT_INT)
- {
- }
- // 有发送FIFO触点中断
- if (SIFR & WK2XXX_TFTRIG_INT)
- {
- }
- // 有发送FIFO空中断
- if (SIFR & WK2XXX_TFEMPTY_INT)
- {
- }
- // 有接收FIFO数据错误中断
- if (SIFR & WK2XXX_FERR_INT)
- {
- }
- }
- }
- }
- /*
- int main()
- {
- int nrecv = 0;
- uint8_t buffer[256];
-
- // 硬件复位一下
- WK_Rst();
-
- // 初始化四个端口
- WK_PortInit(1, 11059200, 9600); // WK2124晶振我用的是11.0592MHz的,这个值根据实际进行修改
- WK_PortInit(2, 11059200, 9600);
- WK_PortInit(3, 11059200, 9600);
- WK_PortInit(4, 11059200, 9600);
-
- // 发送数据
- WK_PortSendData(1, "helloworld\r\n", 12);
- WK_PortSendData(2, "helloworld\r\n", 12);
- WK_PortSendData(3, "helloworld\r\n", 12);
- WK_PortSendData(4, "helloworld\r\n", 12);
-
- // 接收数据,轮训方式
- nrecv = WK_PortRecvData(1, buffer, sizeof(buffer));
-
- if(nrecv != 0)
- {
- // 处理数据
- }
-
- }
- */
复制代码
|