CH32V003软件模拟SPI驱动XL2400P

XL2400P芯片引脚

 选用的模块,CH32V003与此模块连接

 芯领XL2422开发板作为发送测试数据用

 

 SPI接口注意

SPI接口采用3线制,DATA引脚既是输出引脚又是输入引脚。目前我还没有用硬件SPI实现驱动测试,只实现了软件模拟驱动测试。

软件模拟参考压缩包里的驱动文件。

 

 CH32V003工程结构

 XL2400.h代码

#ifndef	XL2400P_H
#define	XL2400P_H#include <ch32v00x.h>extern u8 Rec_Buff[16];
extern u8 Data_Len;
/***************************************************************************************************/
/********************************* XL2400P引脚定义 **************************************************/
/***************************************************************************************************/
#define SPI_GPIO_CLK    RCC_APB2Periph_GPIOC
#define SPI_PORT        GPIOC#define CSN_PIN         GPIO_Pin_3
#define SCK_PIN         GPIO_Pin_2
#define DATA_PIN        GPIO_Pin_1#define SCK_High         GPIO_SetBits(SPI_PORT,SCK_PIN)
#define SCK_Low          GPIO_ResetBits(SPI_PORT,SCK_PIN)#define DATA_High        GPIO_SetBits(SPI_PORT,DATA_PIN)
#define DATA_Low         GPIO_ResetBits(SPI_PORT,DATA_PIN)#define CSN_High         GPIO_SetBits(SPI_PORT,CSN_PIN)
#define CSN_Low		     GPIO_ResetBits(SPI_PORT,CSN_PIN)#define  DATA_READ()     GPIO_ReadInputDataBit(SPI_PORT, DATA_PIN)
/***************************************************************************************************/
/************************************ 操作函数声明 **************************************************/
/***************************************************************************************************/
void DATA_Mode(GPIOMode_TypeDef Mode);
void RF_GPIO_Init(void);
void RF_SPI_Init(void);
void SPI_Write_Byte(u8 buff);
u8 SPI_Read_Byte(void);
void SPI_Write_Reg(u8 RfAdress,u8 RfData);
u8 SPI_Read_Reg(u8 RfAdress);
void Write_RF_Buff(u8 RFAdress , u8 *pBuff , u8 Len);
void Read_RF_Buff(u8 RFAdress , u8 *pBuff , u8 Len);
void RF_Init(void);
void RF_CE_High(void);
void RF_CE_Low(void);
void RF_Clear_Buf(void);
void RF_Reset(void);
void RF_Set_Chn(u8 Chn);
void RF_Set_Address(u8 * AddrBuff);
void RF_Set_Power(u8 Power);
void RF_Sleep(void);
void RF_Tx_Mode(void);
void RF_Rx_Mode(void);
void RFAPIChannelNext(void);
void RFAPIChannelNext_RX(void);u8 Rec_Data(u8 * rec_buff);/***************************************************************************************************/
/************************************ XL2400P相关指令 ***********************************************/
/***************************************************************************************************/#define TRIPLE             1
#define DUAL               0#define setbit(x,y) ((x) |= (1<<(y)))
#define clrbit(x,y) ((x) &= ~(1<<(y)))
#define setbit_array(x,y) (setbit((x)[(y)/8],(y)%8))
#define clrbit_array(x,y) (clrbit((x)[(y)/8],(y)%8))/******************************* 寄存器宏定义 ********************************/
#define CFG_TOP				(0X00)//配置寄存器
#define	EN_AA				(0X01)//使能自动应答寄存器
#define	EN_RXADDR			(0X02)//接收地址允许寄存器
#define	SETUP_AW			(0X03)//设置地址宽度(所有数据管道)
#define	SETUP_RETR			(0X04)//
#define	RF_CH				(0X05)//频点 RF通道 工作通道频率
#define	RF_SETUP			(0X06)
#define	RF_STATUS			(0X07)//状态寄存器
#define	OBSERVE_TX			(0X08)
#define	RSSI				(0X09)
#define	RX_ADDR_P0			(0X0A)
#define	RX_ADDR_P1			(0X0B)
#define	RX_ADDR_P2			(0X2)
#define	RX_ADDR_P3			(0X3)
#define	RX_ADDR_P4			(0X4)
#define	RX_ADDR_P5			(0X5)
#define	RX_ADDR_P2TOP5		(0X0C)
#define	BER_RESULT			(0X0D)
#define	AGC_SETTING			(0X0E)
#define	PGA_SETTING			(0X0F)
#define	TX_ADDR				(0X10)
#define	RX_PW_PX			(0X11)
#define	ANALOG_CFG0			(0X12)
#define	ANALOG_CFG1			(0X13)
#define	ANALOG_CFG2			(0X14)
#define	ANALOG_CFG3			(0X15)
#define	STATUS_FIFO			(0X17)
#define	RSSIREC				(0X18)
#define	TXPROC_CFG			(0X19)
#define	RXPROC_CFG			(0X1A)	
#define	DYNPD				(0X1C)
#define	FEATURE				(0X1D)
#define	RAMP_CFG			(0X1E)
/******************************** 寄存器操作指令 **************************************/
#define R_REG					0x00//读寄存器指令
#define	R_REGISTER				0x00//读寄存器指令
#define W_REG 					0x20//写寄存器指令
#define	W_REGISTER				0x20//写寄存器指令
#define R_RX_PLOAD 			0x61//读 RX 有效数据
#define W_TX_PLOAD			0xA0//写 TX 有效数据
#define FLUSH_TX			0xE1//清除TX FIFO    1110 0001
#define FLUSH_RX			0xE2//清除RX FIFO    1110 0010
#define REUSE_TX_PL			0xE3//应用于发射端。重新使用上一包发射的有效数据
#define R_RX_PL_WID			0x60//0110 0000
#define W_ACK_PLOAD			0xA8//
#define W_TX_PLOAD_NOACK	0xB0//@
#define CMD_NOP				0xFF//空操作。可用来操作状态寄存器#define TX_ADDR_3BYTE			 (0x1 << 2)//@
#define TX_ADDR_4BYTE			 (0x2 << 2)//@
#define TX_ADDR_5BYTE			 (0x3 << 2)//@#define RX_ADDR_3BYTE			 (0x1)//@
#define RX_ADDR_4BYTE			 (0x2)//@
#define RX_ADDR_5BYTE			 (0x3)//@/* STATUS Interrupt status */
#define RX_DR    		(0x40)//接收到数据中断标志位
#define TX_DS    		(0x20)//发送数据完成中断标志位
#define MAX_RT   		(0x10)//达到最大发送次数中断标志位/* FIFO Status */
#define TX_REUSE        		(0x1 << 6)//@
#define TX_FULL            		(0x1 << 5)//@
#define TX_EMPTY        		(0x1 << 4)//@
#define RX_FULL            		(0x2)//@
#define RX_EMPTY        		(0x1)//@
/************************ 射频功率 ****************************/
//1Mpbs只能使用0dBm
//250Kpbs可以用以下功率:
#define	C_RF10dBm               0x3f                            				// 10dBm
#define	C_RF9dBm                0x38                            				// 9dbm
#define	C_RF8dBm                0x34                            				// 8dbm
#define	C_RF7dBm                0x30                            				// 7dbm
#define	C_RF6dBm                0x2c                            				// 6dbm
#define	C_RF5dBm                0x28                            				// 5dbm
#define	C_RF4dBm                0x24                            				// 4dbm
#define	C_RF3dBm                0x20                            				// 3dbm
#define	C_RF2dBm                0x14                            				// 2dbm
#define	C_RF0dBm                0x10                            				// 0dBm
#define	C_RF_2dBm               0x0c                            				// -2dBm
#define	C_RF_6dBm               0x08                            				// -6dBm
#define	C_RF_12dBm              0x04                            				// -12dBm
#define	C_RF_18dBm              0x02                            				// -18dBm
#define	C_RF_24dBm              0x01                            				// -24dBm/*********************** 通讯速率 *****************************************/
#define C_DR_1M                 0x02						//1Mpbs					
#define C_DR_250K               0x22					   //250Kpbs			//----------------------------------------------------------
#define RF_PACKET_SIZE			8//数据长度
#define ADD_WIDTH				5//
#define	C_MAX_CHN_INDEX			4//
//==========================================================#endif

 XL2400.c代码

#include "XL2400P.h"
u8   gRFChnl;//跳频变量
const u8 CHANNELTABLE[] = {05, 76, 19};//频点
u8 RF_Test_Adrress[5]={0xcc,0xcc,0xcc,0xcc,0xcc};//RF地址
/*********************************************************************************************/
/******************************  XL2400P_SPI通讯  ********************************************/
/*********************************************************************************************///射频GPIO引脚初始化
void RF_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure = {0};RCC_APB2PeriphClockCmd(SPI_GPIO_CLK , ENABLE);GPIO_InitStructure.GPIO_Pin = CSN_PIN|SCK_PIN|DATA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SPI_PORT, &GPIO_InitStructure);
}
void DATA_Mode(GPIOMode_TypeDef Mode)//
{GPIO_InitTypeDef  GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin    = DATA_PIN;    //引脚13GPIO_InitStruct.GPIO_Mode   = Mode;       //输出模式GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz; //50MHZGPIO_Init(SPI_PORT, &GPIO_InitStruct);
}//SPI通讯初始化
void RF_SPI_Init(void)
{CSN_High;SCK_Low;
}//SPI写数据(1字节)
//参数 需要写入的数据
void SPI_Write_Byte(u8 buff)
{u8 i;DATA_Mode(GPIO_Mode_Out_PP);for(i = 0; i < 8; i++){SCK_Low;if(buff & 0x80){DATA_High;}else{DATA_Low;}buff = buff << 1;SCK_High;}DATA_High;SCK_Low;
}//SPI读数据(1字节)
//返回 读取到的数据
u8 SPI_Read_Byte(void)
{u8 i;u8  buff = 0;DATA_Mode(GPIO_Mode_IN_FLOATING);for(i = 0; i < 8; i++){SCK_Low;buff = buff << 1;SCK_High;if(DATA_READ()){buff |= 0x01;}         }SCK_Low;return buff;
}//SPI写数据到寄存器
//参数1 寄存器地址+写指令
//参数2 需要写入的数据
void SPI_Write_Reg(u8 RfAdress,u8 RfData)
{CSN_Low;//拉低片选SPI_Write_Byte(RfAdress);//1写入地址SPI_Write_Byte(RfData);//2写入数据CSN_High;//写入完成拉高片选
}//SPI从寄存器读取数据
//参数 寄存器地址+读指令
//返回 读取到的数据
u8 SPI_Read_Reg(u8 RfAdress)
{u8 rTemp;CSN_Low;SPI_Write_Byte(RfAdress);//写入地址+读取指令rTemp = SPI_Read_Byte();//读取数据CSN_High;return rTemp;
}//写入多个数据到寄存器
//参数1 寄存器地址+指令
//参数2 需要写入的数据地址
//参数3 写入次数
void Write_RF_Buff(u8 RFAdress , u8 *pBuff , u8 Len)
{u8 i;u8 rTemp;CSN_Low;SPI_Write_Byte(RFAdress);for(i = 0 ; i < Len ; i++){rTemp = pBuff[i];SPI_Write_Byte(rTemp);}CSN_High;
}//从寄存器读取多个数据
//参数1 寄存器地址+指令
//参数2 读取到的数据存放地址
//参数3 读取的次数
void Read_RF_Buff(u8 RFAdress , u8 *pBuff , u8 Len)
{u8 i;CSN_Low;SPI_Write_Byte(RFAdress);for(i = 0 ; i < Len ; i++){pBuff[i] = SPI_Read_Byte();}CSN_High;
}/*********************************************************************************************/
/***********************************  XL2400P  ***********************************************/
/*********************************************************************************************///射频初始化
void RF_Init(void)
{u8 RF_Init_Buff[16]={0};SPI_Write_Reg(W_REG+CFG_TOP,0x02);Delay_Ms(2);SPI_Write_Reg(W_REG+CFG_TOP,0x3E);Delay_Ms(2);/* 配置模拟寄存器 */Read_RF_Buff(ANALOG_CFG3 , RF_Init_Buff , 6);RF_Init_Buff[5] =((RF_Init_Buff[5]&0xff) | 0x6d);Write_RF_Buff(W_REG+ANALOG_CFG3 , RF_Init_Buff , 6);/* 配置应答PIPE */SPI_Write_Reg(W_REGISTER + EN_AA,     0x00);//不使用应答/* 配置使能地址 */SPI_Write_Reg(W_REGISTER + EN_RXADDR, 0x3f);/* 配置地址长度 */SPI_Write_Reg(W_REGISTER + SETUP_AW,  0xaf);/* 配置重传次数和时间间隔 */SPI_Write_Reg(W_REGISTER + SETUP_RETR,0x33);		/* 配置通讯速率 */SPI_Write_Reg(W_REGISTER + RF_SETUP, C_DR_250K);//250Kpbs/* 配置PIPE0&PIPE1接收包长度 */// RF_Init_Buff[0] = RF_PACKET_SIZE;// RF_Init_Buff[1] = RF_PACKET_SIZE;// Write_RF_Buff(W_REGISTER+RX_PW_PX, RF_Init_Buff ,2);/* 配置PIPE动态长度使能位 */SPI_Write_Reg(W_REGISTER+DYNPD, 0x3f);//使用动态长度//配置其他RF特性:
//bit7&6=00 发送寄存器地址时返回State
//bit5=0 非长数据包
//bit4=1 禁止FEC功能
//bit3=1 FEATURE 配置有效
//bit2=0 动态长度功能打开
//bit1=0 ACK不用带PL
//bit0=0 未开启W_TX_PAYLOAD_NOACK模式SPI_Write_Reg(W_REGISTER+FEATURE, 0x1c);//打开动态长度功能RF_Set_Power(C_RF6dBm);//设置发射功率RF_Set_Address(RF_Test_Adrress);//设置RF地址RF_Clear_Buf();//清除状态
}//拉高RF_CE
void RF_CE_High(void)
{SPI_Write_Reg(W_REGISTER+CFG_TOP, 0xEF);
}//拉低RF_CE
void RF_CE_Low(void)
{SPI_Write_Reg(W_REGISTER+CFG_TOP, 0xEE);
}//清除状态
void RF_Clear_Buf(void)
{SPI_Write_Reg(W_REGISTER+RF_STATUS, (SPI_Read_Reg(RF_STATUS)|RX_DR | TX_DS | MAX_RT));SPI_Write_Reg(FLUSH_TX, CMD_NOP);SPI_Write_Reg(FLUSH_RX, CMD_NOP);
}//复位RF
void RF_Reset(void)
{SPI_Write_Reg(W_REG+CFG_TOP,0xEA);Delay_Us(200);SPI_Write_Reg(W_REG+CFG_TOP,0xEE);Delay_Ms(1);
}//设置频点
void RF_Set_Chn(u8 Chn)
{SPI_Write_Reg(W_REGISTER + EN_AA, 0x00);SPI_Write_Reg(W_REGISTER + RF_CH, Chn + 0x60);SPI_Write_Reg(W_REGISTER + EN_AA, 0x40);							
}//设置地址
void RF_Set_Address(u8 *AddrBuff)
{Write_RF_Buff(W_REGISTER+TX_ADDR,AddrBuff , 5);Write_RF_Buff(W_REGISTER+RX_ADDR_P0, AddrBuff ,5);
}//设置发射功率
void RF_Set_Power(u8 Power)
{u8 Power_Buff[3]={0};Read_RF_Buff(R_REGISTER+RF_SETUP , Power_Buff, 2);Power_Buff[1] = Power;Write_RF_Buff(W_REGISTER+RF_SETUP , Power_Buff ,2);
}//RF休眠
void RF_Sleep(void)
{SPI_Write_Reg(W_REGISTER+CFG_TOP, 0x00);
}//设置为发射模式
void RF_Tx_Mode(void)
{u8 Mode_Buff[3]={0};Mode_Buff[0] = 0xee;Mode_Buff[1] = 0x80; Write_RF_Buff(W_REG+CFG_TOP, Mode_Buff ,2);RF_Clear_Buf();Delay_Ms(1);
}//设置为接收模式
void RF_Rx_Mode(void)
{u8 Mode_Buff[3]={0};Mode_Buff[0] = 0xee;Mode_Buff[1] = 0xc0; Write_RF_Buff(W_REG+CFG_TOP , Mode_Buff ,2);RF_Clear_Buf();RF_CE_High();Delay_Ms(1);
}/***********************************************************************************************/
/*************************************** 跳频 **************************************************/
/***********************************************************************************************/void RFAPIChannelNext(void)
{static u8 gChannelIndex;if(gChannelIndex < 2){gChannelIndex++ ;}else{gChannelIndex = 0;}gRFChnl = CHANNELTABLE[gChannelIndex];RF_Set_Chn(gRFChnl);
}void RFAPIChannelNext_RX(void)
{static u8 gChannelIndex;if(gChannelIndex < 2){gChannelIndex++ ;}else{gChannelIndex = 0;}gRFChnl = CHANNELTABLE[gChannelIndex];gRFChnl -= 1;RF_Set_Chn(gRFChnl);
}/***********************************************************************************************/
/************************************* 通讯测试 *************************************************/
/***********************************************************************************************/u8 Data_Len=0;//接收到的数据的长度//接收数据
u8 Rec_Data(u8 * rec_buff)
{u8 status;u8 RfPlwid;if(SPI_Read_Reg(RF_STATUS) & RX_DR)  //如果触发接收中断{   RF_CE_Low();//拉高CEstatus = SPI_Read_Reg(RF_SETUP);if((status & 0x0e) != 0x0e){RfPlwid = SPI_Read_Reg(R_RX_PL_WID);Data_Len = RfPlwid;Read_RF_Buff(R_RX_PLOAD,rec_buff,RfPlwid); //读取有效数据}SPI_Write_Reg(FLUSH_RX, CMD_NOP);//清空RX FIFOSPI_Write_Reg(W_REG+RF_STATUS,(SPI_Read_Reg(RF_STATUS)|RX_DR));RF_CE_High();//拉高CEreturn 1;}else{return 0;}
}

测试

使用芯领XL2422开发板,选用划线文件下的代码下载发送测试程序,需要在串口软件中输入字符串。

 微信扫码加好友支付2元获取完整代码资料,另有额外技术支持。加友备注:XL2400P测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/470355.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ps:统计

Ps菜单&#xff1a;文件/脚本/统计 Scripts/Statistics 统计 Statistics脚本命令提供了一种高效的方法来处理和分析大量图像&#xff0c;使用户能够自动执行复杂的图像分析任务&#xff0c;并在多个图像间应用统计学方法。这个功能极大地扩展了 Photoshop 在科学研究、图像编辑…

【机器学习】全网最全模型评价指标(性能指标、YOLOv5训练结果分析、轻量化指标、混淆矩阵详解)【基础收藏】

&#x1f951; Welcome to Aedream同学 s blog! &#x1f951; 文章目录 模型性能指标常见指标ROC/AUCROC & PRC多分类问题——混淆矩阵 计算结果分析——以YOLO v5为例1. confusion_matrix.png(混淆矩阵)2. F1_curve&#xff1a;3. labels.jpg4. labels_corrrelogram.jpg5…

Linux-基础IO

目录 IO库函数接口fopenfwritefreadfseekfclose实例 学习系统调用IO接口探讨IO操作句柄重定向实现 IO库函数接口 fopen file *fopen(cosnt char *path, const char *mode);path:要打开的文件路径名称&#xff1b; mode:“r”,“r”,“w”,“w”,“a”,“a”,“b” r&#xff…

二维数组及函数的非函数实现

2024年2月14日 1.请编程实现二维数组的杨慧三角 #include<stdio.h> #include<stdlib.h> #include<string.h> void Yanghui(int n,int (*p)[n]) {for(int i0;i<n;i){for(int j0;j<i;j){if(j0||ij){*(*(pi)j)1;}else{*(*(pi)j)*(*(pi-1)j-1)*(*(pi-1)j)…

【网络攻防实验】【北京航空航天大学】【实验三、口令破解(Password Cracking)实验】

实验三、口令破解(Password Cracking)实验 一、 L0phtCrack破解实验 1、 注册L0phtCrack: 2、 设置口令: (1) 创建3个新账户: 帐户创建过程(以test-1为例): 帐户创建结果: (2) 使用L0phtCrack破解口令:(使用管理员账号运行程序) 口令破解结果: 正确破解口令…

GPT-4影响高度创新思维的领域(一)

GPT-4的应用范围不再局限于对现有信息的检索、整理和复述&#xff0c;而是进一步拓展到了诸如文学创作、科学假设生成、教育辅导、商业策略建议等需要高度创新思维的领域。这种独立思考和创新能力赋予了GPT-4作为虚拟助手时更加丰富多元的角色定位&#xff0c;使其成为一种强大…

类加载过程介绍

一、类的生命周期 类被加载到jvm虚拟机内存开始&#xff0c;到卸载出内存为止&#xff0c;他的生命周期可以分为&#xff1a;加载->验证->准备->解析->初始化->使用->卸载。 其中验证、准备、解析统一称为链接阶段 1、加载 将类的字节码载入方法区中&#xf…

【教3妹学编程-算法题】子集中元素的最大数量

2哥 : 3妹&#xff0c;今年过年收到压岁钱了没呢。 3妹&#xff1a;切&#xff0c;我都多大了啊&#xff0c;肯定没收了啊 2哥 : 俺也一样&#xff0c;不仅没收到&#xff0c;小侄子小外甥都得给&#xff0c;还倒贴好几千 3妹&#xff1a;哈哈哈哈&#xff0c;2叔叔&#xff0c…

嵌入式Qt Qt 中的坐标系统

一.Qt中的坐标系统 实验1&#xff1a;窗口坐标大小 #include <QtGui/QApplication> #include <QPushButton> #include <QDebug> #include "widget.h" int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();qDebug()&…

VC++ 绘制折线学习

win32 有三个绘制折线的函数&#xff1b; Polyline&#xff0c;根据给定点数组绘制折线&#xff1b; PolylineTo&#xff0c;除了绘制也更新当前位置&#xff1b; PolyPolyline&#xff0c;绘制多条折线&#xff0c;第一个参数是点数组&#xff0c;第二个参数是一个数组、指…

[GYCTF2020]Blacklist

感觉是[强网杯 2019]随便注 的加强版&#xff0c;之前做的是最后可以通过prepare和execute实现对select的绕过&#xff0c;但是这题把这两个关键字也过滤了。 前面堆叠注入没啥问题&#xff0c;卡在了最后读取flag 查看其他师傅的wp&#xff0c;发现这个handler的可以当作丐版s…

【java苍穹外卖项目实战三】nginx反向代理和负载均衡

文章目录 1、nginx反向代理2、nginx 反向代理的好处3、nginx 反向代理的配置方式5、nginx 负载均衡的配置方式6、nginx 负载均衡策略 我们思考一个问题&#xff1a; 前端发送的请求&#xff0c;是如何请求到后端服务的&#xff1f; 前端请求地址&#xff1a;http://localhost/…