IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片 -> 正文阅读

[嵌入式]STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片

STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片


STM32基础工程生成

首先使用STM32CUBEMX生成STM32的基础工程,配置时钟到72M主频:

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

所以STM32CUBEMX需要这样配置:

IO配置:

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

WK2124驱动代码

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

头文件
/*
 * wk2xxx.h
 *
 *  Created on: Jun 17, 2021
 *      Author: hello
 */

#ifndef SRC_WK2XXX_H_
#define SRC_WK2XXX_H_

#include "main.h"


#define 	WK2XXX_GENA     0X00
#define 	WK2XXX_GRST     0X01
#define		WK2XXX_GMUT     0X02
#define 	WK2XXX_GIER     0X10
#define 	WK2XXX_GIFR     0X11
#define 	WK2XXX_GPDIR    0X21
#define 	WK2XXX_GPDAT    0X31
//wkxxxx  slave uarts  rigister address defines

#define 	WK2XXX_SPAGE    0X03
//PAGE0
#define 	WK2XXX_SCR      0X04
#define 	WK2XXX_LCR      0X05
#define 	WK2XXX_FCR      0X06
#define 	WK2XXX_SIER     0X07
#define 	WK2XXX_SIFR     0X08
#define 	WK2XXX_TFCNT    0X09
#define 	WK2XXX_RFCNT    0X0A
#define 	WK2XXX_FSR      0X0B
#define 	WK2XXX_LSR      0X0C
#define 	WK2XXX_FDAT     0X0D
#define 	WK2XXX_FWCR     0X0E
#define 	WK2XXX_RS485    0X0F
//PAGE1
#define 	WK2XXX_BAUD1    0X04
#define 	WK2XXX_BAUD0    0X05
#define 	WK2XXX_PRES     0X06
#define 	WK2XXX_RFTL     0X07
#define 	WK2XXX_TFTL     0X08
#define 	WK2XXX_FWTH     0X09
#define 	WK2XXX_FWTL     0X0A
#define 	WK2XXX_XON1     0X0B
#define 	WK2XXX_XOFF1    0X0C
#define 	WK2XXX_SADR     0X0D
#define 	WK2XXX_SAEN     0X0E
#define 	WK2XXX_RTSDLY   0X0F

//WK串口扩展芯片的寄存器的位定义
//wkxxx register bit defines
// GENA
#define 	WK2XXX_UT4EN	0x08
#define 	WK2XXX_UT3EN	0x04
#define 	WK2XXX_UT2EN	0x02
#define 	WK2XXX_UT1EN	0x01
//GRST
#define 	WK2XXX_UT4SLEEP	0x80
#define 	WK2XXX_UT3SLEEP	0x40
#define 	WK2XXX_UT2SLEEP	0x20
#define 	WK2XXX_UT1SLEEP	0x10
#define 	WK2XXX_UT4RST	0x08
#define 	WK2XXX_UT3RST	0x04
#define 	WK2XXX_UT2RST	0x02
#define 	WK2XXX_UT1RST	0x01
//GIER
#define 	WK2XXX_UT4IE	0x08
#define 	WK2XXX_UT3IE	0x04
#define 	WK2XXX_UT2IE	0x02
#define 	WK2XXX_UT1IE	0x01
//GIFR
#define 	WK2XXX_UT4INT	0x08
#define 	WK2XXX_UT3INT	0x04
#define 	WK2XXX_UT2INT	0x02
#define 	WK2XXX_UT1INT	0x01
//SPAGE
#define 	WK2XXX_SPAGE0	  0x00
#define 	WK2XXX_SPAGE1   0x01
//SCR
#define 	WK2XXX_SLEEPEN	0x04
#define 	WK2XXX_TXEN     0x02
#define 	WK2XXX_RXEN     0x01
//LCR
#define 	WK2XXX_BREAK	  0x20
#define 	WK2XXX_IREN     0x10
#define 	WK2XXX_PAEN     0x08
#define 	WK2XXX_PAM1     0x04
#define 	WK2XXX_PAM0     0x02
#define 	WK2XXX_STPL     0x01
//FCR
//SIER
#define 	WK2XXX_FERR_IEN      0x80
#define 	WK2XXX_CTS_IEN       0x40
#define 	WK2XXX_RTS_IEN       0x20
#define 	WK2XXX_XOFF_IEN      0x10
#define 	WK2XXX_TFEMPTY_IEN   0x08
#define 	WK2XXX_TFTRIG_IEN    0x04
#define 	WK2XXX_RXOUT_IEN     0x02
#define 	WK2XXX_RFTRIG_IEN    0x01
//SIFR
#define 	WK2XXX_FERR_INT      0x80
#define 	WK2XXX_CTS_INT       0x40
#define 	WK2XXX_RTS_INT       0x20
#define 	WK2XXX_XOFF_INT      0x10
#define 	WK2XXX_TFEMPTY_INT   0x08
#define 	WK2XXX_TFTRIG_INT    0x04
#define 	WK2XXX_RXOVT_INT     0x02
#define 	WK2XXX_RFTRIG_INT    0x01


//TFCNT
//RFCNT
//FSR
#define 	WK2XXX_RFOE     0x80
#define 	WK2XXX_RFBI     0x40
#define 	WK2XXX_RFFE     0x20
#define 	WK2XXX_RFPE     0x10
#define 	WK2XXX_RDAT     0x08
#define 	WK2XXX_TDAT     0x04
#define 	WK2XXX_TFULL    0x02
#define 	WK2XXX_TBUSY    0x01
//LSR
#define 	WK2XXX_OE       0x08
#define 	WK2XXX_BI       0x04
#define 	WK2XXX_FE       0x02
#define 	WK2XXX_PE       0x01
//FWCR

uint16_t WK_PortSendData(uint8_t port, const void* buf, uint16_t len);
uint16_t WK_PortRecvData(uint8_t port, void* buf, uint16_t len);
void WK_PortInit(uint8_t port, uint32_t fosc, uint32_t baudrate);
void WK_IRQHandler(void);
void WK_Rst(void);

#endif /* SRC_WK2XXX_H_ */

源文件
/*
 * 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)
	{
		// 处理数据
	}
	
}

*/




  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-13 17:37:47  更:2021-07-13 17:38:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 1:58:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码