一、软硬件版本及技术点
二、STM32CubeIDE的工程创建及软件配置
1.打开软件后,点击File→newSTM32Project
2.选择芯片类型 3.输入项目名、选择为C++目标语言,完成
4.添加头文件路径、源文件路径等
可以直接做第三节的内容,之后再添加头文件路径,源文件路径等,随着工程的增加要随时添加这部分内容
右击工程名,点击最后的属性propertise 后得到如下图 点击Add 增加头文件的路径,没有C++的头文件路径 这里的C++头文件路径可以照着工程中的Includes添加,如下图,把框出的路径添加到头文件路径。
添加的头文件路径会在这个文件夹中显示**(但是不知道为什么上面的几个文件夹的路径虽然创建工程就显示但是还需要挨个手动添加??)** 增加的源文件路径也要添加
三、STM32CubeIDE配置系统参数
3.1系统时钟配置
采用外部高速晶振和低速外部晶振
3.2时基配置
debug选用串口线,时基由于使用了FreeRTOS,不建议使用systick
3.3配置SPI2
采用STM32的SPI2,全双工主机(master)模式
射频芯片的最高为10MHz,SPI速度设置为以下
根据射频芯片的时序图特征更改CPOL以及CPHA
配置如图
需要增加射频芯片使用的CSN、CE和IRQ引脚,这里要做对应的设置
3.4配置串口1
配置重点是需要重定向printf函数,<stdio.h>中的printf默认是输出到终端,对于嵌入式设备需要对其重定向,此处重定向到串口1
#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch,1,HAL_MAX_DELAY);
return ch;
}
3.5配置FreeRTOS
3.6其他设置
每次修改.ioc文件后都要保存后重新生成代码
四、nRF24L01功能实现
#ifndef NRF2401_NRF24L01_H_
#define NRF2401_NRF24L01_H_
#include <stdint.h>
#define nRF_ASSERT
#ifdef nRF_ASSERT
#define nRF_assert(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define nRF_assert(expr) ((void)0U)
#endif
extern "C" void nRF24L01_wrapper();
extern "C" void nRF24L01_receive();
extern "C" void call_onIRQ();
extern "C" void nRF24L01_callRXmode();
namespace nRF {
#define nRF_SINGLE_MAXLEN 32
#define ADDRESS_LENGTH 5
#define MAX_TX 0x10
#define TX_OK 0x20
#define RX_OK 0x40
#define TX_ERROR 0x01
#define RX_ERROR 0x02
#define NO_PACKET 0x04
#define NOT_EXIST 0x08
#define NRF_READ_REG 0x00
#define NRF_WRITE_REG 0x20
#define RD_RX_PLOAD 0x61
#define WR_TX_PLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
class nRF24L01 final {
#define RX_ADDRESS 0
#define TX_ADDRESS 1
public:
nRF24L01();
virtual ~nRF24L01();
void onIRQ();
uint8_t nRFSendMsg(uint8_t* msg, uint8_t msglen);
uint8_t nRFRecvMsg(uint8_t* msg, uint8_t msglen, uint32_t timeout);
uint8_t nRFexistDev();
void setEnableCE(void(*func)());
void setDisableCE(void(*func)());
void setEnableCSN(void(*func)());
void setDisableCSN(void(*func)());
void setIrq(uint8_t (*func)());
void setAddress(uint8_t txorrx, uint8_t* addr, uint8_t len);
void getAddress(uint8_t txorrx, uint8_t* addr, uint8_t len);
void setRxMode();
void setTxMode();
private:
uint8_t nRFWriteReg(uint8_t reg, uint8_t val);
uint8_t nRFReadReg(uint8_t reg);
uint8_t nRFWriteBuf(uint8_t reg, uint8_t* msg, uint8_t msglen);
uint8_t nRFReadBuf(uint8_t reg, uint8_t* msg, uint8_t msglen);
void nRFSPIInit();
uint8_t nRFSendPacket(uint8_t* packet, uint8_t len);
uint8_t nRFRecvPacket(uint8_t* packet, uint8_t len);
void (*enableCE)();
void (*disableCE)();
void (*enableCSN)();
void (*disableCSN)();
uint8_t (*getIRQ)();
uint8_t rx_address[5];
uint8_t tx_address[5];
};
extern nRF24L01* g_nrf;
}
#endif
#ifndef NRF2401_NRF24L01_H_
#define NRF2401_NRF24L01_H_
#include <stdint.h>
#define nRF_ASSERT
#ifdef nRF_ASSERT
#define nRF_assert(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define nRF_assert(expr) ((void)0U)
#endif
extern "C" void nRF24L01_wrapper();
extern "C" void nRF24L01_receive();
extern "C" void call_onIRQ();
extern "C" void nRF24L01_callRXmode();
namespace nRF {
#define nRF_SINGLE_MAXLEN 32
#define ADDRESS_LENGTH 5
#define MAX_TX 0x10
#define TX_OK 0x20
#define RX_OK 0x40
#define TX_ERROR 0x01
#define RX_ERROR 0x02
#define NO_PACKET 0x04
#define NOT_EXIST 0x08
#define NRF_READ_REG 0x00
#define NRF_WRITE_REG 0x20
#define RD_RX_PLOAD 0x61
#define WR_TX_PLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
class nRF24L01 final {
#define RX_ADDRESS 0
#define TX_ADDRESS 1
public:
nRF24L01();
virtual ~nRF24L01();
void onIRQ();
uint8_t nRFSendMsg(uint8_t* msg, uint8_t msglen);
uint8_t nRFRecvMsg(uint8_t* msg, uint8_t msglen, uint32_t timeout);
uint8_t nRFexistDev();
void setEnableCE(void(*func)());
void setDisableCE(void(*func)());
void setEnableCSN(void(*func)());
void setDisableCSN(void(*func)());
void setIrq(uint8_t (*func)());
void setAddress(uint8_t txorrx, uint8_t* addr, uint8_t len);
void getAddress(uint8_t txorrx, uint8_t* addr, uint8_t len);
void setRxMode();
void setTxMode();
private:
uint8_t nRFWriteReg(uint8_t reg, uint8_t val);
uint8_t nRFReadReg(uint8_t reg);
uint8_t nRFWriteBuf(uint8_t reg, uint8_t* msg, uint8_t msglen);
uint8_t nRFReadBuf(uint8_t reg, uint8_t* msg, uint8_t msglen);
void nRFSPIInit();
uint8_t nRFSendPacket(uint8_t* packet, uint8_t len);
uint8_t nRFRecvPacket(uint8_t* packet, uint8_t len);
void (*enableCE)();
void (*disableCE)();
void (*enableCSN)();
void (*disableCSN)();
uint8_t (*getIRQ)();
uint8_t rx_address[5];
uint8_t tx_address[5];
};
extern nRF24L01* g_nrf;
}
#endif
#include <nRF24L01.h>
#include "spi.h"
#include "gpio.h"
#include <string>
#include <stdio.h>
namespace nRF {
nRF24L01* g_nrf = nullptr;
nRF24L01::nRF24L01() {
tx_address[0] = 0xE1;
tx_address[1] = 0xE2;
tx_address[2] = 0xE3;
tx_address[3] = 0xE4;
tx_address[4] = 0xE5;
rx_address[0] = 0xE1;
rx_address[1] = 0xE2;
rx_address[2] = 0xE3;
rx_address[3] = 0xE4;
rx_address[4] = 0xE5;
nRFSPIInit();
}
nRF24L01::~nRF24L01() {
}
void nRF24L01::setAddress(uint8_t txorrx, uint8_t* addr, uint8_t len) {
nRF_assert(len >= ADDRESS_LENGTH + 1);
if (txorrx == TX_ADDRESS) {
tx_address[0] = addr[0];
tx_address[1] = addr[1];
tx_address[2] = addr[2];
tx_address[3] = addr[3];
tx_address[4] = addr[4];
} else {
rx_address[0] = addr[0];
rx_address[1] = addr[1];
rx_address[2] = addr[2];
rx_address[3] = addr[3];
rx_address[4] = addr[4];
}
}
void nRF24L01::getAddress(uint8_t txorrx, uint8_t* addr, uint8_t len) {
nRF_assert(len >= ADDRESS_LENGTH + 1);
if (txorrx == TX_ADDRESS) {
addr[0] = tx_address[0];
addr[1] = tx_address[1];
addr[2] = tx_address[2];
addr[3] = tx_address[3];
addr[4] = tx_address[4];
addr[5] = 0;
} else {
addr[0] = rx_address[0];
addr[1] = rx_address[1];
addr[2] = rx_address[2];
addr[3] = rx_address[3];
addr[4] = rx_address[4];
addr[5] = 0;
}
}
void nRF24L01::setRxMode() {
disableCE();
nRFWriteBuf(NRF_WRITE_REG + RX_ADDR_P0, rx_address, ADDRESS_LENGTH);
nRFWriteReg(NRF_WRITE_REG + EN_AA, 0x01);
nRFWriteReg(NRF_WRITE_REG + EN_RXADDR, 0x01);
nRFWriteReg(NRF_WRITE_REG + RF_CH, 40);
nRFWriteReg(NRF_WRITE_REG + RX_PW_P0, nRF_SINGLE_MAXLEN);
nRFWriteReg(NRF_WRITE_REG + RF_SETUP, 0x0F);
nRFWriteReg(NRF_WRITE_REG + CONFIG, 0x0F);
nRFWriteReg(FLUSH_TX, 0XAA);
nRFWriteReg(FLUSH_RX, 0XAA);
enableCE();
HAL_Delay(1);
}
void nRF24L01::setTxMode() {
disableCE();
nRFWriteBuf(NRF_WRITE_REG + TX_ADDR, tx_address, ADDRESS_LENGTH);
nRFWriteBuf(NRF_WRITE_REG + RX_ADDR_P0, rx_address, ADDRESS_LENGTH);
nRFWriteReg(NRF_WRITE_REG + EN_AA, 0x01);
nRFWriteReg(NRF_WRITE_REG + EN_RXADDR, 0x01);
nRFWriteReg(NRF_WRITE_REG + SETUP_RETR, 0x1a);
nRFWriteReg(NRF_WRITE_REG + RF_CH, 40);
nRFWriteReg(NRF_WRITE_REG + RF_SETUP, 0x0F);
nRFWriteReg(NRF_WRITE_REG + CONFIG, 0x0E);
nRFWriteReg(FLUSH_TX, 0XAA);
nRFWriteReg(FLUSH_RX, 0XAA);
enableCE();
HAL_Delay(1);
}
void nRF24L01::onIRQ() {
uint8_t msg[33] = {0};
nRF::g_nrf->nRFRecvMsg(msg, 32 , 60*1000);
msg[32] = 0;
printf("irq get msg: %s\r\n", msg);
}
extern "C" void call_onIRQ() {
nRF::g_nrf->onIRQ();
}
void nRF24L01::setIrq(uint8_t (*func)()) {
getIRQ = func;
}
uint8_t nRF24L01::nRFSendMsg(uint8_t* msg, uint8_t msglen) {
uint8_t packetnum = msglen / nRF_SINGLE_MAXLEN;
uint8_t txresult;
for (int i = 0; i < packetnum; i++) {
txresult = nRFSendPacket(msg + i * nRF_SINGLE_MAXLEN, nRF_SINGLE_MAXLEN);
if (txresult != TX_OK) return txresult;
}
if (msglen % nRF_SINGLE_MAXLEN) {
txresult = nRFSendPacket(msg + packetnum * nRF_SINGLE_MAXLEN, nRF_SINGLE_MAXLEN);
if (txresult != TX_OK) return txresult;
}
return SUCCESS;
}
uint8_t nRF24L01::nRFSendPacket(uint8_t* packet, uint8_t len) {
disableCE();
nRFWriteBuf(WR_TX_PLOAD , packet, len);
nRFWriteReg(NRF_WRITE_REG + CONFIG, 0x0E);
enableCE();
HAL_Delay(1);
while(getIRQ() != DISABLE);
disableCE();
HAL_Delay(1);
uint8_t status = nRFReadReg(NRF_READ_REG + STATUS);
nRFWriteReg(NRF_WRITE_REG + STATUS, status);
nRFWriteReg(FLUSH_TX, 0xff);
if (status & MAX_TX) {
return MAX_TX;
}
if (status & TX_OK) {
return TX_OK;
}
return TX_ERROR;
}
uint8_t nRF24L01::nRFRecvPacket(uint8_t* packet, uint8_t len) {
uint8_t status = nRFReadReg(NRF_READ_REG + STATUS);
nRFWriteReg(NRF_WRITE_REG + STATUS, status);
if (status & RX_OK) {
nRFReadBuf(RD_RX_PLOAD, packet, len);
return SUCCESS;
}
return NO_PACKET;
}
uint8_t nRF24L01::nRFRecvMsg(uint8_t* msg, uint8_t msglen, uint32_t timeout) {
uint8_t packetnum = msglen / nRF_SINGLE_MAXLEN;
uint8_t cnt = 0;
uint32_t tickstart = HAL_GetTick();
while (HAL_GetTick()-tickstart < timeout) {
if (cnt < packetnum) {
int ret = nRFRecvPacket(msg + cnt * nRF_SINGLE_MAXLEN, nRF_SINGLE_MAXLEN);
if (ret == SUCCESS) cnt++;
} else {
if (msglen % nRF_SINGLE_MAXLEN == 0) return SUCCESS;
int ret = nRFRecvPacket(msg + packetnum * nRF_SINGLE_MAXLEN, msglen % nRF_SINGLE_MAXLEN);
if (ret == SUCCESS) return SUCCESS;
}
}
return RX_ERROR;
}
uint8_t nRF24L01::nRFWriteBuf(uint8_t reg, uint8_t* msg, uint8_t msglen) {
uint8_t status;
uint8_t nouse;
nRF_assert(msglen <= nRF_SINGLE_MAXLEN);
disableCSN();
HAL_SPI_TransmitReceive(&hspi2, ®, &status,1, 10);
for (int i = 0; i < msglen; i++) HAL_SPI_TransmitReceive(&hspi2, msg+i, &nouse , 1, 10);
enableCSN();
return status;
}
uint8_t nRF24L01::nRFReadBuf(uint8_t reg, uint8_t* msg, uint8_t msglen) {
uint8_t status;
uint8_t nouse;
nRF_assert(msglen <= nRF_SINGLE_MAXLEN);
disableCSN();
HAL_SPI_TransmitReceive(&hspi2, ®, &status, 1, 10);
for (int i = 0; i < msglen; i++) HAL_SPI_TransmitReceive(&hspi2, &nouse, msg+i, 1, 10);
enableCSN();
return status;
}
uint8_t nRF24L01::nRFWriteReg(uint8_t reg, uint8_t val) {
uint8_t status;
uint8_t nouse;
disableCSN();
HAL_SPI_TransmitReceive(&hspi2, ®, &status, 1, 10);
HAL_SPI_TransmitReceive(&hspi2, &val, &nouse, 1, 10);
enableCSN();
return status;
}
uint8_t nRF24L01::nRFReadReg(uint8_t reg) {
uint8_t regval;
uint8_t nouse;
disableCSN();
HAL_SPI_TransmitReceive(&hspi2, ®, &nouse, 1, 10);
HAL_SPI_TransmitReceive(&hspi2, &nouse, ®val, 1, 10);
enableCSN();
return regval;
}
uint8_t nRF24L01::nRFexist() {
uint8_t buf[5] = {0,0,0,0,0};
disableCE();
nRFWriteBuf(NRF_WRITE_REG+TX_ADDR, tx_address, ADDRESS_LENGTH);
nRFReadBuf(NRF_READ_REG+TX_ADDR, buf, ADDRESS_LENGTH);
for (int i = 0; i < ADDRESS_LENGTH; i++) {
if (buf[i] != tx_address[i]) return NOT_EXIST;
}
return SUCCESS;
}
void nRF24L01::nRFSPIInit() {
__HAL_SPI_DISABLE(&hspi2);
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi2);
__HAL_SPI_ENABLE(&hspi2);
}
void nRF24L01::setEnableCE(void(*func)()) {
enableCE = func;
}
void nRF24L01::setDisableCE(void(*func)()) {
disableCE = func;
disableCE();
}
void nRF24L01::setEnableCSN(void(*func)()) {
enableCSN = func;
enableCSN();
}
void nRF24L01::setDisableCSN(void(*func)()) {
disableCSN = func;
}
}
extern "C" void nRF24L01_callSend() {
std::string msg = "hello nrf24 hello nrf24 hello nrf24 hello nrf24";
printf("send msg begin\r\n");
nRF::nRF24L01 nrf1;
nrf1.setEnableCE(setCE);
nrf1.setDisableCE(resetCE);
nrf1.setEnableCSN(setCSN);
nrf1.setDisableCSN(resetCSN);
nrf1.setIrq(getIrq);
HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
if (nrf1.nRFexistDev() == 0) {
nrf1.setTxMode();
uint8_t ret = nrf1.nRFSendMsg((uint8_t*)msg.c_str(), msg.length());
if (ret == SUCCESS) printf("send result = %d\r\n", ret);
else {
printf("send failed [errorcode:0X%X]\r\n", ret);
}
} else {
printf("no device!\r\n");
}
printf("send msg end\r\n");
}
extern "C" void nRF24L01_callRXmode() {
nRF::g_nrf = new nRF::nRF24L01;
nRF::g_nrf->setEnableCE(setCE);
nRF::g_nrf->setDisableCE(resetCE);
nRF::g_nrf->setEnableCSN(setCSN);
nRF::g_nrf->setDisableCSN(resetCSN);
printf("rx mode wait interrupt\r\n");
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
nRF::g_nrf->setRxMode();
}
extern "C" void nRF24L01_receiveTimout() {
uint8_t msg[50] = {0};
nRF::nRF24L01 nrf1;
nrf1.setEnableCE(setCE);
nrf1.setDisableCE(resetCE);
nrf1.setEnableCSN(setCSN);
nrf1.setDisableCSN(resetCSN);
nrf1.setIrq(getIrq);
printf("waiting msg...\r\n");
nrf1.setRxMode();
nrf1.nRFRecvMsg(msg, 32 , 60*1000);
printf("msg : %s\r\n", msg);
}
extern "C" void call_onIRQ() {
nRF::g_nrf->onIRQ();
}
五、代码的使用方式
-
生成的main.c文件要更名为main.cpp (每次更改ioc重新生成代码之前先改回main.c,生成后再改为main.cpp,如果不改,则会另外生成一个main.c) main.c改为main.cpp 后要把 void MX_FREERTOS_Init(void) 前加上 extern "C" ,因为这个函数本身是freertos.c文件中定义的,main.c更名为main.cpp找不到对应的符号,因为C和C++编译为不同的符号 -
无论发送还是接收都要进行如下的函数的处理,即绑定使用的引脚对应的GPIO nRF::g_nrf->setEnableCE(setCE); nRF::g_nrf->setDisableCE(resetCE); nRF::g_nrf->setEnableCSN(setCSN); nRF::g_nrf->setDisableCSN(resetCSN);
//gpio.c中设置了这几个函数,也可以直接传入HAL_GPIO_WritePIN()
void setCE() {HAL_GPIO_WritePin(GPIOG, GPIO_PIN_8, GPIO_PIN_SET);}
void resetCE() {HAL_GPIO_WritePin(GPIOG, GPIO_PIN_8, GPIO_PIN_RESET);}
void setCSN() {HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET);}
void resetCSN() {HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_RESET);}
uint8_t getIrq() { return HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_6);}
3. C和C++混合编程,采用的FreeRTOS创建任务,可以在对应的任务中增加Cwrapper后的代码
作为发送:
可以开辟一个缓冲区,用于填入发送的数据,然后调用nRF24L01_callSend 函数,进行发送。
作为接收:
-
nRF24L01_receiveTimout 这个可以设置为在一定时间内接收一定大小的数据 -
或者采用中断的方式,收到数据后存储到指定的缓冲区,收集一定的数据后进行数据的处理 中断函数尽量处理不高耗时的任务,中断可只做数据接收后放到指定的开辟的缓冲区 处理缓冲区的工作在工作线程中执行,中断只负责转移数据
六、遇到的问题
问题1
-
不能够正确的写入到nRF24L01的寄存器,或者部分写入 -
读取数据超时 -
每次读取的错误数据是相同的,问题可复现
send msg begin
txbuf : 0xE5 0xB5 0xE2 0xA0 0xB2
rxbuf : 0xE5 0xB5 0xE2 0xA0 0xB2
enaa :0x7
enrxaddr :0x7
setup :0x46
rfch :0x88
rfsetup :0x1
config = 0x2A
status = 0xE
send msg end
txbuf : 0xb2 0xe5 0xb5 0xe2 0xa0
rxbuf : 0xb2 0xe5 0xb5 0xe2 0xa0
EN_AA = 7
EN_RXADDR = 7
SETUP RETRY = 46
RF_CH = 88
RF_SETUP = F
CONFIG = 2A
STAUTS = E
send msg begin
txbuf : 0xE7 0xE7 0xE7 0xE7 0xE7
rxbuf : 0xE7 0xE7 0xE7 0xE7 0xE7
enaa :0x3F
enrxaddr :0x3
setup :0x3
rfch :0x2
rfsetup :0x0
config = 0x8
status = 0xE
send msg end
txbuf : 0xe7 0xe7 0xe7 0xe7 0xe7
rxbuf : 0xe7 0xe7 0xe7 0xe7 0xe7
EN_AA = 3F
EN_RXADDR = 3
SETUP RETRY = 3
RF_CH = 2
RF_SETUP = F
CONFIG = 8
STAUTS = E
send msg begin
txbuf : 0x43 0x10 0x10 0x1 0x34
rxbuf : 0x43 0x10 0x10 0x1 0x34
enaa :0x1
enrxaddr :0x1
setup :0x1A
rfch :0x40
rfsetup :0x0
config = 0xE
status = 0xE
send msg end
txbuf : 0x34 0x43 0x10 0x10 0x1
rxbuf : 0x34 0x43 0x10 0x10 0x1
EN_AA = 1
EN_RXADDR = 1
SETUP RETRY = 1A
RF_CH = 40
RF_SETUP = F
CONFIG = E
STAUTS = E
解决方法
-
更改了disable CRC -
项目中更改了HAL_SPI_Transmit 为 HAL_SPI_TransmitReceive ,可能是由于前者仅发送处理接收区,导致SPI同步收到的数据未被清除(仅猜测)
问题2
硬件错误,按下按键后发送第一次之后即发生Hard_Fault
解决方式:
增加线程栈空间为512
问题3
接收不到数据,发送端表示已经重发引起中断
解决方式:
-
经过测试发现,每次写给TX_FIFO必须写入32字节,否则nRF24L0不会发送!! -
每次进入发送或者接收状态要清除缓冲区,防止错误导致缓冲区存在数据
七、建议
没事干的话改成纯c吧,C++没啥必要哈哈哈
参考资料
STM32—cubeMX+HAL库的SPI接口使用_夜风~的博客-CSDN博客_cubemx spi
正点原子库函数手册
nRF24L01的手册
STM32CubeIDE使用技巧(FreeRTOS点亮一盏灯)_重拾十年梦的博客-CSDN博客_cubeide自动补全
STM32L051C8T6 HAL库 + nRF24L01 收发案例(硬件SPI通讯)_Ch_champion的博客-CSDN博客_hal spi实例
使用STM32CubeMX开发三:按键中断实验 - 无网不进 - 博客园 (cnblogs.com)
attribute((weak)) 简介及作用_侵蚀昨天的博客-CSDN博客___attribute__((weak))
使用stm32cubeIDE git代码(gitee)_violet1714的博客-CSDN博客
stm32 FreeRTOS 某个任务一直不被运行_zhuimeng_ruili的博客-CSDN博客_freertos任务不运行
STM32CubeMX FreeRTOS堆栈分配、调试技巧 - 云+社区 - 腾讯云 (tencent.com)
|