其他分享
首页 > 其他分享> > 使用STM32F103C8T6驱动NRF24L01具体步骤

使用STM32F103C8T6驱动NRF24L01具体步骤

作者:互联网

初始化24l01大致步骤
在这里插入图片描述
在这里插入图片描述

要控制模块需要使用“SPI”接口
C8T6有两个SPI,根据情况来选择对应的端口
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
NSS引脚可以不用.

初始化SPI

void SPI2_INIT(void)
{
	GPIO_InitTypeDef gpio_init;
	SPI_InitTypeDef spi_init;
	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  	//使能引脚
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);		//使能spi
	
	gpio_init.GPIO_Mode=GPIO_Mode_AF_PP;	//复用推挽输出
	gpio_init.GPIO_Pin=GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; //选择对应的引脚
	gpio_init.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &gpio_init);
	
	

	
	spi_init.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_256;
	spi_init.SPI_CPHA= SPI_CPHA_2Edge;						//时钟第二个跳变沿 数据被采集
	spi_init.SPI_CPOL=SPI_CPOL_High;						//SCK空闲为高电平
	spi_init.SPI_CRCPolynomial= 7; 							//CRC值为什么是7??
	spi_init.SPI_DataSize= SPI_DataSize_8b; 				//数据大小是8位结构
	spi_init.SPI_Direction=SPI_Direction_2Lines_FullDuplex;	//spi双线全双工
	spi_init.SPI_FirstBit= SPI_FirstBit_MSB;				//从MSB高位开始传输
	spi_init.SPI_Mode= SPI_Mode_Master;						//spi设为主模式
	spi_init.SPI_NSS=SPI_NSS_Soft; 							//硬件控制?
	SPI_Init(SPI2,&spi_init);
	
	SPI_Cmd(SPI2, ENABLE); //使能外设
	
	SPI2_READ_WRITE_BYTE(0xff); //发一个ff数据
}

//设置波特率
void SPI2_SET_SPEED(u8 SPI_BaudRatePrescaler)
{
	SPI2->CR1&=0XFFC7;	//3-5位清0 设置波特率
	SPI2->CR1|=SPI_BaudRatePrescaler;
	SPI_Cmd(SPI2,ENABLE);
}



u8 SPI2_READ_WRITE_BYTE(u8 txdata)
{

	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空
	
	SPI_I2S_SendData(SPI2, txdata); //通过spi发送一个byte
		
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //等待接收一个byte
 
	return SPI_I2S_ReceiveData(SPI2); //返回spi收到的数据
	
}

在这里插入图片描述

void nrf24l01_init(void)
{
	
	GPIO_InitTypeDef gpio_init;
	SPI_InitTypeDef spi_init;
	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	gpio_init.GPIO_Mode=GPIO_Mode_Out_PP; //普通io口设置
	gpio_init.GPIO_Speed=GPIO_Speed_50MHz;
	gpio_init.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_15;
	GPIO_Init(GPIOA,&gpio_init);
	//PA15和PA12是CE 和CSN
	
	gpio_init.GPIO_Mode=GPIO_Mode_IPU ;
	gpio_init.GPIO_Pin=GPIO_Pin_8;
	GPIO_Init(GPIOA, &gpio_init);
	//IRQ引脚
	
	SPI2_INIT();
	//重设spi
	SPI_Cmd(SPI2, DISABLE);
	//根据协议重新设置spi
	spi_init.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16; //
	spi_init.SPI_CPHA=SPI_CPHA_1Edge;
	spi_init.SPI_CPOL=SPI_CPOL_Low; //空闲为低电平
	spi_init.SPI_CRCPolynomial=7;
	spi_init.SPI_DataSize=SPI_DataSize_8b;
	spi_init.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	spi_init.SPI_FirstBit=SPI_FirstBit_MSB;
	spi_init.SPI_Mode=SPI_Mode_Master;
	spi_init.SPI_NSS=SPI_NSS_Soft;
	SPI_Init(SPI2,&spi_init);
	SPI_Cmd(SPI2,ENABLE);
	
	NRF24L01_CE=0;
	NRF24L01_CSN=1;
	
}

到这里spi设置完成,基本可以跟24l01通信

读写24l01函数

u8 nrf24l01_write_reg(u8 reg, u8 value)
{
	u8 status;
	NRF24L01_CSN=0;
	
	status=SPI2_READ_WRITE_BYTE(reg); //发送寄存器地址,
	
	SPI2_READ_WRITE_BYTE(value);//发送寄存器值
	
	NRF24L01_CSN=1;
	
	return(status);
}


u8 nrf24l01_read_reg(u8 reg)
{
	u8 reg_val;
	NRF24L01_CSN=0;
	
	SPI2_READ_WRITE_BYTE(reg);
	
	reg_val=SPI2_READ_WRITE_BYTE(0XFF);
	
	NRF24L01_CSN=1;
	
	return(reg_val);
}

检测24l01是否存在
返回为1则失败,0 成功

u8 nrf24l01_check(void)
{
	
	u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
	u8 i;
	
	SPI2_SET_SPEED(SPI_BaudRatePrescaler_4);
	nrf24l01_write_buf(NRF_WRITE_REG+TX_ADDR,buf,5);
	nrf24l01_read_buf(TX_ADDR,buf,5);
	for(i=0; i<5; i++)if(buf[i]!=0xA5)break;
	if(i!=5)return 1;
	return 0;
}

读写指定长度的字符串

u8 nrf24l01_read_buf(u8 reg, u8 *pbuf, u8 len)
{
	u8 s,ctr;
	
	NRF24L01_CSN=0;
	
	s=SPI2_READ_WRITE_BYTE(reg);
	
	for(ctr=0; ctr<len; ctr++)pbuf[ctr]=SPI2_READ_WRITE_BYTE(0XFF);
	
	NRF24L01_CSN=1;
	
	return s;
}




u8 nrf24l01_write_buf(u8 reg, u8 *pbuf, u8 len)
{
	u8 s,ctr;
	
	NRF24L01_CSN=0;
	
	s=SPI2_READ_WRITE_BYTE(reg);
	
	for(ctr=0; ctr<len; ctr++) SPI2_READ_WRITE_BYTE(*pbuf++);//接收指定数量数据
	
	NRF24L01_CSN=1;
	
	return s;
}

发送一个指定字符串
接收成功返回0,否则返回寄存器值

u8 nrf24l01_txpacket(u8 *txbuf)
{
	
	u8 sta;
	
	SPI2_SET_SPEED(SPI_BaudRatePrescaler_4);
	
	NRF24L01_CSN=0;
	nrf24l01_write_buf(WR_TX_PLOAD, txbuf, tx_pload_width);
	NRF24L01_CSN=1;
	
	
	while(NRF24L01_IRQ!=0);
	
	sta=nrf24l01_read_reg(STATUS);
	nrf24l01_write_reg(NRF_WRITE_REG+STATUS,sta);

	return sta;

}



u8 nrf24l01_rxpacket(u8 *rxbuf)
{
	RX_DR=0x40;	
	TX_DS=0x20;	
	MAX_RT=0x10;	//最大发送值
	TX_FIFO_MAX=0x01;
	
	
	
	
	SPI2_SET_SPEED(SPI_BaudRatePrescaler_8); 
	rx_status=nrf24l01_read_reg(STATUS);	//发送状态字,得到寄存器状态
	nrf24l01_write_reg(NRF_WRITE_REG+STATUS,rx_status);	//清除寄存器值
	
	
	if(rx_status&RX_DR)
	{
		
		nrf24l01_read_buf(RD_RX_PLOAD,rxbuf, rx_pload_width); 	//把数据放入字符串地址里
		nrf24l01_write_reg(FLUSH_RX,0xff);						//清除状态寄存器
		
		return rx_status;
	}
	return rx_status;
	
}

24l01有两个模式,需要根据状态切换
在这里插入图片描述
切换发送接收模式

u8 nrf24l01_mod(u8 m)
{
	
	if(m==1)
	{
		nrf24l01_tx_mode();
		
	}
	else
	{
		nrf24l01_rx_mode();
		
	}
	return m;
}

至此,基本设置完成,

//直接发送一个字符串
void tx_24l01(u8 *tx_buf)
{
	nrf24l01_mod(1);//设置模块为发送模式
	s=0;
	
	
	RX_DR=0x40;
	TX_DS=0x20;	//
	MAX_RT=0x10;
	TX_FIFO_MAX=0x01;
	
	s=nrf24l01_txpacket(tx_buf);	//调用函数发送	

	while(1)
	{
		
		if(s&TX_DS)
		{
			printf("发送成功");
			nrf24l01_mod(0);//发送成功后要设为接收模式
			break;
		}		
		else if(s&MAX_RT)//判断发送次数,超出最大值
		{
	
			printf("最大值");
			nrf24l01_mod(0);//
			break;
		}

		else //以上皆不是则返回错误
		{

			printf(" erro");
			
			break;	
		}		
	}		
}

接收数据
在这里插入图片描述

24l01主要关注2个寄存器,
设置寄存器
在这里插入图片描述
状态寄存器每次通信必读取的寄存器
在这里插入图片描述
在这里插入图片描述
h文件需要设置的内容
在这里插入图片描述

标签:SPI2,SPI,NRF24L01,spi,init,具体步骤,STM32F103C8T6,GPIO,u8
来源: https://blog.csdn.net/weixin_45555616/article/details/110501179