STM32
直播中

李凤津

7年用户 985经验值
私信 关注
[问答]

如何利用STM32把两个2.4G放在一起进行通信呢

如何利用STM32把两个2.4G放在一起进行通信呢?有哪些基本步骤?

回帖(1)

王峰

2021-12-16 09:38:23
利用STM32,把两个2.4G放在一起进行通信。
前段时间,因为闲暇无事,就玩起了2.4G,利用两个2.4G进行相互通信,我用的2.4G是nRF2401芯片,原理图如下:




下面是主函数代码,头文件在这里省略;
有关2.4G的代码我全部放在了nRF2401.c文件里
int main(void)
{
delay_init();       //延时函数初始化   
LED_Init();    //初始化与LED连接的硬件接口
Key_Init();
uart_init(9600);
SPI_GPIO_Init();
SPI2_Init();
NRF24L01_Init();


printf("nrf24l01 start!rn");
while (NRF24L01_Check())//检测
{


printf("nrf24l01 02 failed!rn");
}
printf("nrf24l01s are ok!rn");


NRF24L01_TX_Mode();
while(NRF24L01_TX_Packet(txbuf)==TX_OK)
{
NRF24L01_RX_Mode();
}


while(1)
{
Key_Scan();
if(mode==0)
{
RX_Mode();
}
  if(mode==1)
{
TX_Mode();
    }
     }
}
main.c中交代了两个模式,TX_Mode,和RX_Mode;这两个模式是我在nRF2401.c里进行定义的,主要是分开接收和发送两种模式。
除此之外!!!
在这里需要注意的一点是:(特别注意)
nRF2401在发送和接收信息的时候一定要有空闲时间,不能同时进行,否则会堵塞,信息无法发送,故此我在main.c中初始化之余,加了以下函数防止造成堵塞而无法发送信息:
    NRF24L01_TX_Mode();
while(NRF24L01_TX_Packet(txbuf)==TX_OK)
{
NRF24L01_RX_Mode();
}


1,打开NRF24L01_TX_Mode2发送函数
2,判断发送函数是否成功
3,打开NRF24L01_RX_Mode2接收函数
这样就不会造成两个同时打开造成信息堵塞而无法发送信息的情况。
这个情况困扰我很久,一直无法成功发送信息,最后在网上查阅资料的时候看到这个知识点时,才恍然大悟,按照上面这个逻辑,才成功发送信息。
下面是NRF24L01.c文件,这个程序在网上或者视频教学时带的源码里有很多,由于很长所以在此只写和上面有关的一些主要代码,如下:
/*****************************************************************************
* 函  数:void NRF24L01_TX_Mode(void)
* 功  能:NRF24L01发送模式配置
* 参  数:无
* 返回值:无
* 备  注:无
*****************************************************************************/
void NRF24L01_TX_Mode(void)
{
NRF_CE_LOW;
NRF24L01_Write_Buf(W_REGISTER+TX_ADDR,TX_ADR_WIDTH,(uint8_t *)TX_ADDRESS_Y);//写TX节点地址
NRF24L01_Write_Buf(W_REGISTER+RX_ADDR_P0,RX_ADR_WIDTH, (uint8_t *) RX_ADDRESS_Y);//写RX节点地址,为了自动使能ACK
NRF24L01_Write_Reg(W_REGISTER+EN_AA, 0x01);//使能通道0自动应答
NRF24L01_Write_Reg(W_REGISTER+EN_RXADDR, 0x01);//使能通道0接收地址
NRF24L01_Write_Reg(W_REGISTER+SETUP_PETR, 0x1a);//设置自动重发间隔时间:500us+86us,最大重大次数:10次
NRF24L01_Write_Reg(W_REGISTER+RF_CH, 40);//设置通道为40
NRF24L01_Write_Reg(W_REGISTER+RF_SETUP, 0x0f);//设置发射参数:0dB增益;2Mnps;低噪声增益开启
NRF24L01_Write_Reg(W_REGISTER+NRF24L01_CONFIG,0x0e);//基本参数:PWR_UP;EN_CRC;16BIT_CRC;发送模式;开启所有中断
NRF_CE_HIGH;//NRF_CE为高,10us后启动发送数据
delay_us(12);
}
/*****************************************************************************
* 函  数:void NRF24L01_TX_Mode(void)
* 功  能:NRF24L01发送模式配置
* 参  数:无
* 返回值:无
* 备  注:无
*****************************************************************************/
void NRF24L01_RX_Mode(void)
{
NRF_CE_LOW;
NRF24L01_Write_Buf(W_REGISTER+RX_ADDR_P0, RX_ADR_WIDTH, (uint8_t *) RX_ADDRESS_X);//写RX地址节点
NRF24L01_Write_Reg(W_REGISTER+EN_AA,0x01);//使能通道0自动应答
NRF24L01_Write_Reg(W_REGISTER+EN_RXADDR,0x01);//使能通道0接收地址
NRF24L01_Write_Reg(W_REGISTER+RF_CH, 40);//设置RF通信频率
NRF24L01_Write_Reg(W_REGISTER+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0有效数据宽度
NRF24L01_Write_Reg(W_REGISTER+RF_SETUP, 0x0f);//设置TX发射参数:0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(W_REGISTER+NRF24L01_CONFIG, 0x0f);//基本参数:PWR_UP;EN_CRC;16BIT_CRC;接收模式;开启所有中断
NRF_CE_HIGH;//CE为高,进入接收模式
}


/*****************************************************************************
* 函  数:uint8_t NRF24L01_TX_Packet(uint8_t *txbuf)
* 功  能:NRF24L01发送一次数据
* 参  数:*txbuf:等待发送数据的首地址
* 返回值:MAX_TX:最大重发次数;TX_OK:发送完成;0xFF:发送失败
* 备  注:无
*****************************************************************************/
uint8_t NRF24L01_TX_Packet(uint8_t *txbuf)
{
uint8_t ret;


NRF_CE_LOW;
NRF24L01_Write_Buf(W_TX_PAYLOAD, TX_PLOAD_WIDTH, txbuf);//写数据到txbuf,32字节
NRF_CE_HIGH;//启动发送
while (NRF_IRQ_STATUS);//等待发送完成
ret = NRF24L01_Read_Reg(NRF24L01_STATUS);//读取状态寄存器的值
NRF24L01_Write_Reg(W_REGISTER+NRF24L01_STATUS, ret);//清除TX_DS or MAX_RT的中断标志
if(ret&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX, 0XFF);//清除TX FIFO 寄存器
return MAX_TX;
}
if(ret&TX_OK) //发送完成
{


return TX_OK;
}
return 0xFF;//发送失败


}


/*****************************************************************************
* 函  数:uint8_t NRF24L01_RX_Packet(uint8_t *rxbuf)
* 功  能:NRF24L01接收一次数据
* 参  数:*rxbuf:等待接收数据的首地址
* 返回值:0:接收成功;1:接收数据失败
* 备  注:无
*****************************************************************************/
uint8_t NRF24L01_RX_Packet(uint8_t *rxbuf)
{
uint8_t ret;




NRF_CE_HIGH;
while(NRF_IRQ_STATUS);
NRF_CE_LOW;


ret = NRF24L01_Read_Reg(NRF24L01_STATUS);//读取状态寄存器的值
NRF24L01_Write_Reg(W_REGISTER+NRF24L01_STATUS, ret);//清除TX_DS or MAX_RT的中断标志
if(ret&RX_OK)//接收到数据
{
NRF24L01_Read_Buf(R_RX_PAYLOAD,RX_PLOAD_WIDTH,rxbuf);//读取数据
NRF24L01_Write_Reg(FLUSH_RX,0xFF);//清除RX FIFO寄存器
return 0;
}
return 1;//没有接收到数据
}


这里主要是一些源码,无多大改动;
下面是我自己加的TX_Mode,和RX_Mode函数
void TX_Mode(void)
{
uint8_t ret,i;
delay_ms(500);
NRF24L01_TX_Mode();
while(NRF24L01_TX_Packet(txbuf)==TX_OK)
{
printf("nrf1 send is sucessed!rn");
printf("rn");
for(i=0;i<5;i++)
{
printf("nrf1 send data is %d rn",txbuf);
}
delay_ms(500);  //延时300ms
mode=0;
LED2=~LED2;
break;
}
}


void RX_Mode(void)
{
uint8_t ret,i;
delay_ms(500);
NRF24L01_RX_Mode();
while(NRF24L01_RX_Packet(rxbuf)==0)
{
ret = NRF24L01_RX_Packet2(rxbuf);
for(i=0;i<5;i++)
{
   printf("nrf2 recieve data is %d rn",rxbuf);
}
printf("nrf recieves data sucessed!rn");
if(text_buf[4]==8)
{
delay_ms(500);  //延时300ms
mode=1;
LED1=~LED1;
}
break;
}
}
其中主函数里的mode=0/1的值就是从这里来的
在这两个函数最后判断是否接收完数据,我利用的是直接判断的数组的最后一位text_buf[4]的值,其中我对数组的定义如下:



const uint8_t TX_ADDRESS_X[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};//发送端地址
const uint8_t RX_ADDRESS_X[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};//接收端地址


const uint8_t TX_ADDRESS_Y[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x02};//发送端地址
const uint8_t RX_ADDRESS_Y[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x02};//接收端地址


extern uint8_t txbuf[5]={5,2,3,4,9};
extern uint8_t rxbuf[5]={0,0,0,0,0};


extern int mode=0;
extern uint8_t text_buf[5]={0,0,0,0,0};
发送数组里的最后一位是9所以我这里直接判断最后一位数组的值来确定是否接收完全。
缺点:
在这里我判断数据是否接收完成的放法是不够严谨的,无法保证数据准确性
改进:
后面可以用协议的方式来保证数据的准确性。
以上为个人观点以及从网上借鉴而来,如有不足及错误,希望多多指教。
举报

更多回帖

×
20
完善资料,
赚取积分