STM32 SPI NRF24L01复习整理



/********** mySpi.h****************/

#ifndef __MY_SPI_H
#define __MY_SPI_H

#include "stm32f10x.h"
#include <stdio.h>

#define SPI1_CSN_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_1);
#define SPI1_CSN_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_1);

#define SPI2_CSN_HIGH() GPIO_SetBits(GPIOB,GPIO_Pin_12);
#define SPI2_CSN_LOW() GPIO_ResetBits(GPIOB,GPIO_Pin_12);

void mySpi1Config(void);
u8 mySpi1SendByte(u8 byte);
void mySpi2Config(void);
u8 mySpi2SendByte(u8 byte);

#endif

/**********mySpi.c************/

#include "mySpi.h"

void mySpi1Config(void)

{

  SPI_InitTypeDef  SPI_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  //SCK,MISO,MOSI  GPIOA^5,GPIOA^6,GPIOA^7 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能
  GPIO_Init(GPIOA, &GPIO_InitStructure);  

  //CSN   GPIOA^1
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  SPI1_CSN_HIGH(); 

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟空闲时为低
 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第一个边沿有效
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由软件产生
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;  //8分频=9MHz
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //高位在前
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);

  SPI_Cmd(SPI1, ENABLE);
}

void mySpi2Config(void)

{

  SPI_InitTypeDef  SPI_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI2, ENABLE);

  //SCK,MISO,MOSI  GPIOB^13,GPIOB^14 GPIOB^15 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能
  GPIO_Init(GPIOB, &GPIO_InitStructure);  

  //CSN   GPIOB^12
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  SPI2_CSN_HIGH(); 

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;  //主机模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟空闲时为低
 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第一个边沿有效
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由软件产生
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;  //8分频=9MHz
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //高位在前
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI2, &SPI_InitStructure);

  SPI_Cmd(SPI2, ENABLE);
}

u8 mySpi1SendByte(u8 byte)
{  
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);// 当SPI发送缓存不为空
  SPI_I2S_SendData(SPI1, byte);//通过SPI发送数据
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //当SPI接收缓存不为空

  return SPI_I2S_ReceiveData(SPI1);  //读取缓存数据
}

u8 mySpi2SendByte(u8 byte)
{  
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);// 当SPI发送缓存不为空
  SPI_I2S_SendData(SPI2, byte);//通过SPI发送数据
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //当SPI接收缓存不为空

  return SPI_I2S_ReceiveData(SPI2);  //读取缓存数据

}


/***********myNRF24L01.h********************/

#ifndef __MY_NRF24L01_H
#define __MY_NRF24L01_H

#include "stm32f10x.h"
#include <stdio.h>

/**********  NRF24L01寄存器操作指令 ***********/
#define nRF_READ_REG    0x00  //读配置寄存器-低5位是寄存器地址
#define nRF_WRITE_REG   0x20  // 写配置寄存器-低5位是寄存器地址
#define RD_RX_PLOAD     0x61  //读RX有效数据 1~32字节
#define WR_TX_PLOAD     0xA0  //写TX有效数据 1~32字节
#define FLUSH_TX        0xE1  // 清除TX的FIFO寄存器-发送模式使用
#define FLUSH_RX        0xE2  // 清除RX的FIFO寄存器-接收模式使用
#define REUSE_TX_PL     0xE3  //重新使用上一包数据-CE为高时数据包被不断发送
#define NOP             0xFF  // 空操作-用于读状态寄存器

/**********  NRF24L01寄存器地址   *************/
#define CONFIG          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  // RF寄存器
#define STATUS          0x07  //状态寄存器
#define OBSERVE_TX      0x08  //发送检测寄存器
#define CD              0x09  // 载波检测寄存器
#define RX_ADDR_P0      0x0A  //数据通道0接收地址
#define RX_ADDR_P1      0x0B  // 数据通道1接收地址
#define RX_ADDR_P2      0x0C  // 数据通道2接收地址
#define RX_ADDR_P3      0x0D  //数据通道3接收地址
#define RX_ADDR_P4      0x0E  //数据通道4接收地址
#define RX_ADDR_P5      0x0F  //数据通道5接收地址
#define TX_ADDR         0x10  // 发送地址寄存器
#define RX_PW_P0        0x11  // 接收数据通道0有效数据宽度(1~32字节) 
#define RX_PW_P1        0x12  // 接收数据通道1有效数据宽度(1~32字节) 
#define RX_PW_P2        0x13  // 接收数据通道2有效数据宽度(1~32字节) 
#define RX_PW_P3        0x14  // 接收数据通道3有效数据宽度(1~32字节) 
#define RX_PW_P4        0x15  // 接收数据通道4有效数据宽度(1~32字节) 
#define RX_PW_P5        0x16  // 接收数据通道5有效数据宽度(1~32字节) 
#define FIFO_STATUS     0x17  // FIFO状态寄存器

/******   STATUS寄存器BIT位定义     *******/
#define MAX_TX   0x10    //达到最大发送次数中断
#define TX_OK   0x20    //TX发送完成中断
#define RX_OK   0x40    //接收到数据中断

void myNrfConfig(void);
u8 myNrfWriteReg(u8 reg,u8 dat);
u8 myNrfReadReg(u8 reg);
u8 myNrfWriteBuf(u8 reg,u8 *pBuf,u8 byte);
u8 myNrfReadBuf(u8 reg,u8 *pBuf,u8 byte);
u8 myNrfCheck(void);
void myNrfRxMode(void);
void myNrfTxMode(void);
u8 myNrfTxDat(u8 *txbuf);
u8 myNrfRxDat(u8 *rxbuf);

#endif

/*******************myNRF24L01.c*********************/

#include "myNRF24L01.h"
#include "mySpi.h"

#define NRF_CE_HIGH()  GPIO_SetBits(GPIOA,GPIO_Pin_2);
#define NRF_CE_LOW()   GPIO_ResetBits(GPIOA,GPIO_Pin_2);
#define NRF_READ_IRQ() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)  //IRQ

#define myNrfSpiConfig   mySpi1Config   //替换NRF的SPI配置函数
#define myNrfSpiSendByte mySpi1SendByte //替换NRF的SPI读写函数
#define NRF_CSN_LOW  SPI1_CSN_LOW //替换NRF的SPI的CSN宏定义
#define NRF_CSN_HIGH SPI1_CSN_HIGH

#define CHANAL 0 //频道选择

#define TX_ADR_WIDTH    5     //5字节地址宽度
#define RX_ADR_WIDTH    5     //5字节地址宽度
#define TX_PLOAD_WIDTH  32    //32字节有效数据宽度

#define RX_PLOAD_WIDTH  32    //32字节有效数据宽度

 u8 RX_BUF[RX_PLOAD_WIDTH]; //接收数据缓存
 u8 TX_BUF[TX_PLOAD_WIDTH]; //发送数据缓存
 u8 TX_ADDRESS[TX_ADR_WIDTH] = {0xFF,0xFF,0xFF,0xFF,0xFF};  //静态地址
 u8 RX_ADDRESS[RX_ADR_WIDTH] = {0xFF,0xFF,0xFF,0xFF,0xFF};

void myNrfConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

  //NRF CE
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

 //NRF IRQ 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;  //上拉输入
  GPIO_Init(GPIOA, &GPIO_InitStructure); 

 //NRF SPI配置
 myNrfSpiConfig();
}

//指定寄存器写入指定数据
u8 myNrfWriteReg(u8 reg,u8 dat)
{
  u8 status;

  NRF_CE_LOW();
  NRF_CSN_LOW();

  status = myNrfSpiSendByte(reg);//
  myNrfSpiSendByte(dat); //
   
  NRF_CSN_HIGH();
  return(status);
}


//从指定寄存器读取数据

u8 myNrfReadReg(u8 reg)
{
  u8 reg_val;

NRF_CE_LOW();
  NRF_CSN_LOW();

myNrfSpiSendByte(reg); //
reg_val = myNrfSpiSendByte(NOP); //

NRF_CSN_HIGH();
   
return reg_val;
}

//从指定寄存器读取一串数据
u8 myNrfReadBuf(u8 reg,u8 *pBuf,u8 bytes)
{
  u8 status, byte_cnt;

NRF_CE_LOW();
NRF_CSN_LOW();

status = myNrfSpiSendByte(reg); //

for(byte_cnt=0;byte_cnt<bytes;byte_cnt++)  
{
pBuf[byte_cnt] = myNrfSpiSendByte(NOP); //
}

NRF_CSN_HIGH();

  return status; //
}

//向指定寄存器写入一串数据
u8 myNrfWriteBuf(u8 reg ,u8 *pBuf,u8 bytes)
{
u8 status,byte_cnt;

NRF_CE_LOW();
NRF_CSN_LOW();

status = myNrfSpiSendByte(reg); 

for(byte_cnt=0;byte_cnt<bytes;byte_cnt++)
{
myNrfSpiSendByte(*pBuf++); //
}  

NRF_CSN_HIGH();

return (status); //
}

//检测NRF与MCU连接与否
u8 myNrfCheck(void)
{
u8 buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
u8 buf1[5];
u8 i; 
 
myNrfWriteBuf(nRF_WRITE_REG+TX_ADDR,buf,5); //дÈë5¸ö×ֽڵĵØÖ· 
myNrfReadBuf(TX_ADDR,buf1,5); //¶Á³öдÈëµÄµØÖ·
 
//±È½Ï             
for(i=0;i<5;i++)
{
if(buf1[i]!=0xC2)
break;

      
if(i==5)
return SUCCESS ;        //MCUÓëNRF³É¹¦Á¬½Ó 
else
return ERROR ;        //MCUÓëNRF²»Õý³£Á¬½Ó
}

//配置NRF进入发送模式
void myNrfRxMode(void)
{
NRF_CE_LOW();

myNrfWriteBuf(nRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);设置RX节点地址
myNrfWriteReg(nRF_WRITE_REG+EN_AA,0x01);    //使能通道0的自动应答
myNrfWriteReg(nRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的自动应答
myNrfWriteReg(nRF_WRITE_REG+RF_CH,CHANAL);      //设置RF通道
myNrfWriteReg(nRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//设置通道0 的有效数据宽度
myNrfWriteReg(nRF_WRITE_REG+RF_SETUP,0x0f);//设置发射参数 -0db增益,2Mbps,低噪音增益开启
myNrfWriteReg(nRF_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式-PWR_UP, EN_CRC,  16BIT_CRC 接收模式 开启所有中断

  NRF_CE_HIGH();
}    

//配置NRF进入接收模式
void myNrfTxMode(void)
{  
NRF_CE_LOW();
myNrfWriteBuf(nRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //设置TX节点地址

myNrfWriteBuf(nRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//设置RX节点地址-使能ACK

myNrfWriteReg(nRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答

myNrfWriteReg(nRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址

myNrfWriteReg(nRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔

myNrfWriteReg(nRF_WRITE_REG+RF_CH,CHANAL);       //设置RF通道

myNrfWriteReg(nRF_WRITE_REG+RF_SETUP,0x0f);//设置发射参数 -0db增益,2Mbps,低噪音增益开启

myNrfWriteReg(nRF_WRITE_REG+CONFIG,0x0e);//配置基本工作模式-PWR_UP, EN_CRC,  16BIT_CRC 发射模式 开启所有中断

  NRF_CE_HIGH();
}

//向NRF的发送缓存写入数据
u8 myNrfTxDat(u8 *txbuf)
{
u8 state; 

NRF_CE_LOW(); //进入发送模式

myNrfWriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); //写数据到发送缓存

NRF_CE_HIGH(); //CE为高 发送缓存不为空 则发送数据包

while(NRF_READ_IRQ()!=0); //等待发送完成

state = myNrfReadReg(STATUS); //读取状态寄存器

myNrfWriteReg(nRF_WRITE_REG+STATUS,state); //清除中断标志

myNrfWriteReg(FLUSH_TX,NOP);    //清除TX FIFO寄存器

if(state&MAX_TX)    //达到最大重发次数
{
return MAX_TX; 
}
else if(state&TX_OK)   //发送完成
{
return TX_OK;
}
else  
{
return ERROR;     //其它原因失败
}


//从NRF接收缓存读取数据
u8 myNrfRxDat(u8 *rxbuf)
{
u8 state;
u16 ii = 2000; 
NRF_CE_HIGH(); //进入接收模式
 
while(ii && NRF_READ_IRQ()!=0) //等待接收数据
{
ii--;
}

NRF_CE_LOW();   //进入待机状态
 
state=myNrfReadReg(STATUS); //读取状态寄存器

myNrfWriteReg(nRF_WRITE_REG+STATUS,state); //清除中断标志

if(state&RX_OK)                                 //接收到数据
{
myNrfReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
myNrfWriteReg(FLUSH_RX,NOP);          //清除FIFO寄存器

return RX_OK; 
}
else    
{
return ERROR;                    //
}
}


/************main.c********************/myNrfConfig();

int main(void)

{
    myNrfConfig();
    status = myNrfCheck(); //检测
    if(status == SUCCESS)
     printf("SUCCES\r\n");
    else
        printf("ERROR\r\n");

    while (1)
    {
        myNrfRxMode();              //进入接收模式
        status = myNrfRxDat(rxbuf);         //等待接收数据
        switch(status)
        {
            case RX_OK:
            myNrfTxMode();    //进入发送模式
            status = myNrfTxDat(rxbuf); //将接收到的数据发送出去
            break;

         }

    }

}































  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值