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;    //引脚13
    GPIO_InitStruct.GPIO_Mode   = Mode;       //输出模式
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz; //50MHZ
    GPIO_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();//拉高CE
		status = 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 FIFO
		SPI_Write_Reg(W_REG+RF_STATUS,(SPI_Read_Reg(RF_STATUS)|RX_DR));
		RF_CE_High();//拉高CE
		return 1;
	}
	else
	{
		return 0;
	}
}

测试

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

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

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

armcsdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值