C8T6通过2.4G(NRF24L01)模块实现双向通信

实现功能: 两个C8T6单片机通过2.4G模块进行通信,实现数据的收发,并执行相应的操作。

所需材料: C8T6单片机( 两个) 2.4G模块( 两个) USB转TTL (一个,用于在PC端观察收到的数据)

一、2.4G引脚及引脚配置

在这里插入图片描述

简要说明:

CE: 2.4G 片选信号

CSN:SPI 片选信号

其中片选信号的作用大致是:使能器件

SCK、MOSI、MISO是SPI的通信引脚

//-------------------
IRQ:中断信号线(现在理解为标志位,检查数据是否发送完成、有效时为低电平,)当IRQ引脚为低电平时,即数据传输完成。

在本实验例程中用到的引脚

CE: B12
CSN:B10
SCK:B13
MOSI:B15
MISO:B14
IRQ:B11

二、2.4G通信方式

(1)SPI通信

2.4G模块是用的是SPI通信方式 首先你要知道SPI通信的特点

SPI特点: 全双工(可以同时完成发送和接收,也就是主给从发送数据的同时,从也给主返回一个应答信号)

所以在程序设计时:

如果只进行写操作,主机忽略接收到的字节;反之,

若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

(2)SPI通信的一些介绍

(2.1)SPI采用4线传输

①CE:片选信号,由片选引脚可以使我们的单片机可以和多个SPI外设进行通信,

比如: 外设0---->PA0 外设1------>PA1 外设2------>PA2等等,当我们单片机将上述的引脚选择性拉低时,就可以和对应的外设
进行通信。(应该最多是一对六) == ???==

②SCK: 时钟线,输出串行同步时钟,可以改变其时钟极性(CHOL)和时钟相位(CPHA)

如果 CPOL=1,串行同步时钟的空闲状态为高电平。

如果 CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样

注意:SPI主模块和从模块时钟配置要一样。

在这里插入图片描述

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//第二个跳变沿数据被采样

③MISO 主设备数据输入,从设备数据输出。

④MOSI 主设备数据输出,从设备数据输入。

(2.2)SPI通信清楚这几点

当我们要配置SPI通信的时候,头脑中应该有以下几点内容:

①SPIX引脚

SPI1

在这里插入图片描述
SPI2

在这里插入图片描述
注意: SPIX_NSS是SPI的硬件片选引脚,而我们采用的是软件片选(即引脚可以自己设置)

②SPI引脚模式配置:
在这里插入图片描述

具体代码实现:
在这里插入图片描述

三、SPI重点掌握这一点

重点需要掌握的是SPI中的读写函数:

// SPI读写一个字节
// TxData:要写入的字节
// 返回值:读取到的字节
//-----------------------------------------------------------------------
u8 SPI2_ReadWriteByte(u8 TxData)
{		
	u8 TxWait = 0;
	u8 RxWait = 0;
	
	// 等待发送缓存为空
	while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
	{
		TxWait++;
		if(TxWait>250)	// 等待时间过长则放弃本次读写
		return 0;
	}	

	SPI_I2S_SendData(SPI2, TxData); // SPI2写一个字节
	
	// 等待接收缓存为空
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
	{
		RxWait++;
		if(RxWait>250)	// 等待时间过长则放弃本次读写
		return 0;
	}	  	
	
	return SPI_I2S_ReceiveData(SPI2); // 将读到的字节返回					    
}

①功能及分析:
功能:发送一个字节,并且返回一个字节

在这个函数里面,其中有两个是判断语句(等待语句)

发送等待------->数据是否发送成功

接受等待------->是否接受到发送的数据

在正常情况下,这个语句中有效的语句其实就是下面两句:

SPI_I2S_SendData(SPI2, TxData); //发送一个数据
return SPI_I2S_ReceiveData(SPI2); //返回一个数据

下面我们将用代码来具体实现两个单片机之间的数据收发,并且通过判断收发数据是否正确来执行相应的操作。

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: stm32f103c8t6是一款单片机,具有丰富的外设资源和较强的处理能力。而2.4G NRF24L01无线模块可以实现低功耗、高速、长距离的无线通信。下面是一份包含发送和接收代码的示例: 发送端代码: 1. 首先,需要包含stm32f10x.h和nrf24l01.h头文件。 2. 初始化SPI接口和NRF24L01模块。 3. 设置NRF24L01工作模式为发送模式。 4. 通过SPI接口写入要发送的数据到NRF24L01发送缓冲区。 5. 发送数据。 接收端代码: 1. 首先,需要包含stm32f10x.h和nrf24l01.h头文件。 2. 初始化SPI接口和NRF24L01模块。 3. 设置NRF24L01工作模式为接收模式。 4. 在一个循环中检查NRF24L01接收缓冲区是否有数据可读。 5. 如果有数据可读,通过SPI接口从NRF24L01接收缓冲区读取数据。 在这份代码中,发送端和接收端的初始化和设置过程是相同的,只有在发送和接收数据的时候稍有不同。 这只是一份简单的示例代码,实际上,还需要进行一些参数配置,如频道选择、数据速率、发送接收地址等。同时,还需要根据具体需求对代码进行修改和完善。 希望以上回答能够满足您的需求,如果还有其他问题,欢迎继续提问! ### 回答2: 下面是一个基本的STM32F103C8T6和NRF24L01无线模块通信代码示例,包含发送和接收代码。 发送端代码: #include "stm32f10x.h" #include "nrf24l01.h" void NRF24L01_CE(uint8_t level) { if(level) GPIO_SetBits(GPIOB, GPIO_Pin_0); // 设置CE端口为高 else GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 设置CE端口为低 } uint8_t NRF24L01_RW(uint8_t data) { while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) ; // 等待发送完成 USART_SendData(USART1, data); // 发送数据 while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) ; // 等待接收完成 return USART_ReceiveData(USART1); // 返回接收到的数据 } void NRF24L01_Delay_us(uint32_t n) { uint32_t i; for(i=0; i<n; i++); } int main() { uint8_t txData[32] = "Hello, NRF24L01!"; // 初始化USART1和PB0 USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); NRF24L01_Init(); while(1) { NRF24L01_SendData(txData, 32); // 发送数据 NRF24L01_Delay_us(1000); // 延时1ms } } 接收端代码: #include "stm32f10x.h" #include "nrf24l01.h" void NRF24L01_CE(uint8_t level) { if(level) GPIO_SetBits(GPIOB, GPIO_Pin_0); // 设置CE端口为高 else GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 设置CE端口为低 } uint8_t NRF24L01_RW(uint8_t data) { while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) ; // 等待发送完成 USART_SendData(USART1, data); // 发送数据 while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) ; // 等待接收完成 return USART_ReceiveData(USART1); // 返回接收到的数据 } void NRF24L01_Delay_us(uint32_t n) { uint32_t i; for(i=0; i<n; i++); } int main() { uint8_t rxData[32]; // 初始化USART1和PB0 USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); NRF24L01_Init(); while(1) { NRF24L01_ReceiveData(rxData, 32); // 接收数据 } } 请注意,以上仅为代码示例,具体使用时还要根据自己的需求进行修改和适配。还需要在此代码的基础上完成NRF24L01的初始化、数据发送和接收等函数的定义和实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值