• 使用STM32F030F4P6的SPI协议和NRF24L01模块进行通讯 实现无线数据的收发


    单片机这块纯属个人业余爱好, 有很多不足的地方还请大家多多指教, 代码中有些命名不规范的地方还请大家多多包涵.

    本文只实现无线模块的简单的点亮(能收发一个字节数据), 一直想diy一个无线遥控的小车, 就要使用到无线模块, 找了好久发现NRF24L01(下面简称NRF)是最便宜的一款无线模块(除过WiFi和蓝牙模块), 就买了几个, 由于stm32f103涨价, 就选择了便宜的stm32f030, 网上找了很多资料对于stm32f030的资料很少, 他和stm32f103代码大同小异, 就试着在stm32f103代码的基础上修改一下, 就是不能通讯, 只能发送成功, 不能接收到数据, 搁置了好久最后从新选择了一块 HC-12 的无线通讯模块, 这个模块比较贵首次购买一套(收发两个模块)比较便宜, 空旷视野最远通讯距离1公里(没有实测量过), 他使用的是串口通讯, 写好代码烧录进去后可以通讯, 最后成功diy了无线遥控小车, 利用HC-12感觉大材小用了, 最后闲来无事就又琢磨一下这个NRF模块, 终于可以相互通讯了, 也不知道哪里出问题了, 唯一不同的是, 之前的是在网上找的资料上修修改改, 没有使用中断, 只使用了while循环进行检测, 这次重头开始编写的时候使用了中断, 在调试了一下就可以通讯.

    遇到的一些问题:

    1.原理图上PA4 是SPI1的片选spi1_nss的复用, 配置的时候把PA4也配置成了复用模式, 发现不能成功, 需要配置成输出模式解决了问题

    2.NRF的IRQ脚配置中断的时候需要配置为下降沿触发

    3.stm32板子和NRF模块进行连接的时候数据输出和输入线不能交叉连接(MCU 的MISO 和 NRF的 MISO 相连, MOSI同理)

    以下是代码 , 适用于stm32f030

    1. spi配置

    #ifndef __bsp_spi_h
    #define __bsp_spi_h
    
    #include "stm32f0xx_gpio.h"
    
    #define SPIx SPI1                            //SPI_1
    #define SPI1_PORT GPIOA                //PA 端口
    #define PORTA_LCK RCC_AHBPeriph_GPIOA    //GPIO 时钟
    #define SPI_LCK RCC_APB2Periph_SPI1//spi 时钟
    #define SPI1_CSN GPIO_Pin_1        //PA1    NSS
    #define SPI1_SCK GPIO_Pin_5        //PA5    SCK
    #define SPI1_MISO GPIO_Pin_6    //PA6    MISO
    #define SPI1_MOSI GPIO_Pin_7    //PA7    MOSI
    
    void SPI_Config(void);
    u8 SPI_SendByte(u8 byte);
    void Pin_CSN(u8 u);
    
    #endif
    bsp_spi.h
    #include "bsp_spi.h"
    #include "stm32f0xx_gpio.h"
    
    //初始化
    void SPI_Config()
    {
        GPIO_InitTypeDef GPIO_InitStruct;
        SPI_InitTypeDef SPI_InitStruct;
        
        //端口初始化
        RCC_AHBPeriphClockCmd(PORTA_LCK , ENABLE);//开启GPIO时钟
        RCC_APB2PeriphClockCmd(SPI_LCK, ENABLE);//开启SPI_1时钟
        
        //复用模式
        GPIO_PinAFConfig(SPI1_PORT,GPIO_PinSource5,GPIO_AF_0);//SCK
        GPIO_PinAFConfig(SPI1_PORT,GPIO_PinSource6,GPIO_AF_0);//MISO
        GPIO_PinAFConfig(SPI1_PORT,GPIO_PinSource7,GPIO_AF_0);//MOSI
        
        GPIO_InitStruct.GPIO_Pin =  SPI1_SCK | SPI1_MISO | SPI1_MOSI;
      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
      GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
      GPIO_Init(SPI1_PORT, &GPIO_InitStruct);
        
        GPIO_InitStruct.GPIO_Pin = SPI1_CSN;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_Init(SPI1_PORT , &GPIO_InitStruct);
        
        //spi初始化
        //SPI_I2S_DeInit(SPIx);    //将寄存器重设为缺省值
        //SPI_Cmd(SPIx, DISABLE);
        //SPI_Direction_2Lines_FullDuplex SPI_Direction_1Line_Rx SPI_Direction_1Line_Tx
        SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        //SPI_Mode_Master 主机 SPI_Mode_Slave 从机
        SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
        SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;//SPI_CPOL_Low SPI_CPOL_High
        SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;//SPI_CPHA_1Edge SPI_CPHA_2Edge
        SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
        SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
        //SPI_FirstBit_MSB SPI_FirstBit_LSB
        SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStruct.SPI_CRCPolynomial = 7;
        SPI_Init(SPIx, &SPI_InitStruct);
        //SPI_I2S_IT_TXE SPI_I2S_IT_RXNE SPI_I2S_IT_ERR
        SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_TXE | SPI_I2S_IT_RXNE, ENABLE);//中断
        SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);    //重要,把应答数据位设置为 8 位
        SPI_Cmd(SPIx, ENABLE);//使能
    }
    
    //SPI 收发一个字节
    u8 SPI_SendByte(u8 byte)
    {
        //设置时间溢出
        u32 SPITimeout = 0xffff;
        /* 等待发送缓冲区为空,TXE 事件 */
        while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)
        {
            if ((SPITimeout--) == 0) return 0;
        }
        /* 写入数据寄存器,把要写入的数据写入发送缓冲区 */
        SPI_SendData8(SPIx, byte);//SPI_I2S_SendData16
        //设置时间溢出
        SPITimeout = 0xfffff;
        /* 等待接收缓冲区非空,RXNE 事件 */
        while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET)
        {
            if ((SPITimeout--) == 0) return 0;
        }
        /* 读取数据寄存器,获取接收缓冲区数据 */
        return SPI_ReceiveData8(SPIx);
    }
    //设置片选高低电平
    void Pin_CSN(u8 u)
    {
        if(u==0)
        {
            SPI1_PORT->BRR = SPI1_CSN;
        }
        else
        {
            SPI1_PORT->BSRR = SPI1_CSN;
        }
    }
    bsp_spi.c

    2.nrf配置

    #ifndef __bsp_nrf0241_h
    #define __bsp_nrf0241_h
    
    #include "stm32f0xx_gpio.h"
    
    #define NRF_PORT GPIOA                //PA 端口
    #define KEY0 GPIO_Pin_0        //KEY0
    #define LED0 GPIO_Pin_4        //LED0
    #define NRF_CE GPIO_Pin_2        //PA2    CE
    #define NRF_IRQ GPIO_Pin_3        //PA3    IRQ
    #define NOP 0xFF // 空操作。可以用来读 状态寄存器
    
    //设置ce置高和拉低
    void Pin_CE(u8 u);
    //获取IRQ中断的电平,(没有用到)
    u8 Get_IRQ(void);
    //写入数据
    u8 SPI_WriteBuf(u8 reg, u8 *pBuf, u8 len);
    //读取数据
    u8 SPI_ReadBuf(u8 reg, u8 *pBuf, u8 len);
    //读写一条指令
    u8 SPI_RWReg(u8 reg, u8 value);
    //配置
    void NRF_Config(void);
    //获取按键的电平(用于判断按键是否按下)
    u8 Get_KEY0(void);
    //配置测试按键和LED灯
    void KEY0_LED0_Config(void);
    //设置LED灯(低电平点亮)
    void Pin_LED0(u8 u);
    //发送数据buff为数据,len为个数
    void send_data(u8 *buff,u8 len);
    //检测NRF模块是否存在 存在返回0
    u8 nrf24l0_check(void);
    //读取状态寄存器, 用于判断发送成功, 接收成功, 发送达到最大值
    u8 Get_Status(void);
    //接收数据
    void receive_data(void);
    //获取接收到的数据 buf 存放接收的数据, len数据个数
    void Get_Data(u8 *buf,u8 len);
    //清除所有(发送, 接收, 最大发送次数)的中断
    void ClearStatus(void);
    
    #endif
    bsp_nrf0241.h
    #include "bsp_nrf0241.h"
    #include "stm32f0xx_gpio.h"
    #include "bsp_spi.h"
    #include "delay.h"
    
    void KEY0_LED0_Config()
    {
        GPIO_InitTypeDef GPIO_InitStruct;
        NVIC_InitTypeDef NVIC_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
        
        RCC_AHBPeriphClockCmd(PORTA_LCK , ENABLE);
        //用户测试的按键和LED灯
        GPIO_InitStruct.GPIO_Pin =  KEY0;//按键
        GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_UP;
      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
      GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
      GPIO_Init(NRF_PORT, &GPIO_InitStruct);
        GPIO_InitStruct.GPIO_Pin = LED0;//LED灯
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_Init(NRF_PORT , &GPIO_InitStruct);
        Pin_LED0(1);//低电平 熄灭LED灯
        //添加按键中断
        EXTI_InitStructure.EXTI_Line = KEY0;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        //EXTI_Trigger_Rising , EXTI_Trigger_Falling , EXTI_Trigger_Rising_Falling
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        //中断
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPriority = 1;        //子优先级1
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器
    }
    u8 Get_KEY0(void)
    {
        return GPIO_ReadInputDataBit(NRF_PORT, KEY0);
    }
    void Pin_LED0(u8 u)
    {
        if(u==0)
        {
            NRF_PORT->BRR = LED0;
        }
        else
        {
            NRF_PORT->BSRR = LED0;
        }
    }
    //地址
    u8 TX_ADDRESS1[5]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
    u8 RX_ADDRESS1[5]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
    //配置
    void NRF_Config()
    {
        GPIO_InitTypeDef GPIO_InitStruct;
        NVIC_InitTypeDef NVIC_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
        
        //端口初始化
        RCC_AHBPeriphClockCmd(PORTA_LCK , ENABLE);
        
        GPIO_InitStruct.GPIO_Pin =  NRF_CE;//CE 输出
        GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
      GPIO_Init(NRF_PORT, &GPIO_InitStruct);
        
        GPIO_InitStruct.GPIO_Pin =  NRF_IRQ;//IRQ 中断输入
        GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;
      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
      GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
      GPIO_Init(NRF_PORT, &GPIO_InitStruct);
        
        //中断
        EXTI_InitStructure.EXTI_Line = NRF_IRQ;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        //EXTI_Trigger_Rising , EXTI_Trigger_Falling , EXTI_Trigger_Rising_Falling
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        //中断
        NVIC_InitStructure.NVIC_IRQChannel = EXTI2_3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPriority = 1;        //子优先级1
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器
        
        //配置RNF
        Pin_CSN(1);
        Pin_CE(0);
        //0x02 发射, 0x03 接收- crc不使能 crc模式:8位效验
        //0x0e 发射, 0x0f 接收- crc使能 crc模式:16位效验
        SPI_RWReg(0x20+0x00,0x02);//0x02 发射, 0x03 接收
        SPI_RWReg(0x20+0x01,0x00);//自动应答 若通道0应答:0x01 禁止自动应答:0x00
        SPI_RWReg(0x20+0x02,0x01);//接收地址允许 通道0允许
        SPI_RWReg(0x20+0x03,0x03);//设置地址宽度 5个地址宽度
        SPI_RWReg(0x20+0x04,0x00);//建立自动重发 禁止自动重发
        SPI_RWReg(0x20+0x05,40);//射频通道
        SPI_RWReg(0x20+0x06,0x07);//射频寄存器
        SPI_RWReg(0x20+0x07,0x70);//状态寄存器
        SPI_WriteBuf(0x20+0x0A,RX_ADDRESS1,5);//通道0接收地址
        SPI_WriteBuf(0x20+0x10,TX_ADDRESS1,5);//发送地址
        SPI_RWReg(0x20+0x11,32);//接收数据通道0有效数据宽度 1-32 字节
    }
    //发送
    void TX_MODE()
    {
        //配置RNF
        Pin_CSN(1);
        Pin_CE(0);
        //0x02 发射, 0x03 接收- crc不使能 crc模式:8位效验
        //0x0e 发射, 0x0f 接收- crc使能 crc模式:16位效验
        SPI_RWReg(0x20+0x00,0x02);
        SPI_RWReg(0x20+0x01,0x00);//自动应答 若通道0应答:0x01 禁止自动应答:0x00
        SPI_RWReg(0x20+0x02,0x01);//接收地址允许 通道0允许
        SPI_RWReg(0x20+0x03,0x03);//设置地址宽度 5个地址宽度
        SPI_RWReg(0x20+0x04,0x00);//建立自动重发 禁止自动重发
        SPI_RWReg(0x20+0x05,40);//射频通道
        SPI_RWReg(0x20+0x06,0x07);//射频寄存器
        SPI_RWReg(0x20+0x07,0x70);//状态寄存器
        SPI_WriteBuf(0x20+0x0A,RX_ADDRESS1,5);//通道0接收地址
        SPI_WriteBuf(0x20+0x10,TX_ADDRESS1,5);//发送地址
        SPI_RWReg(0x20+0x11,32);//接收数据通道0有效数据宽度 1-32 字节
    }
    //接收
    void RX_MODE()
    {
        //配置RNF
        Pin_CSN(1);
        Pin_CE(0);
        //0x02 发射, 0x03 接收- crc不使能 crc模式:8位效验
        //0x0e 发射, 0x0f 接收- crc使能 crc模式:16位效验
        SPI_RWReg(0x20+0x00,0x03);//0x02 发射, 0x03 接收
        SPI_RWReg(0x20+0x01,0x00);//自动应答, 若通道0应答:0x01 禁止自动应答:0x00
        SPI_RWReg(0x20+0x02,0x01);//接收地址允许 通道0允许
        SPI_RWReg(0x20+0x03,0x03);//设置地址宽度 5个地址宽度
        SPI_RWReg(0x20+0x04,0x00);//建立自动重发 禁止自动重发
        SPI_RWReg(0x20+0x05,40);//射频通道
        SPI_RWReg(0x20+0x06,0x07);//射频寄存器
        SPI_RWReg(0x20+0x07,0x70);//状态寄存器
        SPI_WriteBuf(0x20+0x0A,RX_ADDRESS1,5);//通道0接收地址
        SPI_WriteBuf(0x20+0x10,TX_ADDRESS1,5);//发送地址
        SPI_RWReg(0x20+0x11,32);//接收数据通道0有效数据宽度 1-32 字节
        Pin_CE(1);
        delay_us(120);
    }
    
    //发送数据
    void send_data(u8 *buff,u8 len)
    {
        TX_MODE();
        SPI_RWReg(0xE1,0xFF);//清除发送寄存器
        SPI_WriteBuf(0xA0,buff,len);//写入发送寄存器
        Pin_CE(1);
        delay_us(20);
        Pin_CE(0);
    }
    //接收数据
    void receive_data()
    {
        RX_MODE();
        SPI_RWReg(0xE2,0xFF);//清除接收寄存器
        Pin_CE(1);
        delay_us(120);
    }
    //获取数据
    void Get_Data(u8 *buf,u8 len)
    {
        SPI_ReadBuf(0x61,buf,len);
    }
    //清除中断
    void ClearStatus()
    {
        Pin_CE(0);
        SPI_RWReg(0x20+0x07,0x70);
        Pin_CE(1);
        delay_us(20);
    }
    void Pin_CE(u8 u)
    {
        if(u==0)
        {
            NRF_PORT->BRR = NRF_CE;
        }
        else
        {
            NRF_PORT->BSRR = NRF_CE;
        }
    }
    u8 Get_IRQ(void)
    {
        return GPIO_ReadInputDataBit(NRF_PORT, NRF_IRQ);
    }
    
    //用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数
    u8 SPI_WriteBuf(u8 reg, u8 *pBuf, u8 len) 
    {
        u8 s,ctr;
        Pin_CSN(0);
        delay_us(100);
        s=SPI_SendByte(reg);
        
        for(ctr=0; ctr<len; ctr++)
            SPI_SendByte(*pBuf++);
        Pin_CSN(1);
        delay_us(100);
        return s;
    }
    //功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数
    u8 SPI_ReadBuf(u8 reg, u8 *pBuf, u8 len) 
    {
        u8 s,ctr;
        Pin_CSN(0);
        delay_us(100);
        s=SPI_SendByte(reg);
        
        for(ctr=0; ctr<len; ctr++)
            pBuf[ctr]=SPI_SendByte(NOP);
        Pin_CSN(1);
        delay_us(100);
        return s;
    }
    //功能:NRF24L01 读写寄存器函数
    u8 SPI_RWReg(u8 reg, u8 value) 
    {
        u8 status = 0x00;
        Pin_CSN(0);
        delay_us(100);
        status = SPI_SendByte(reg); //发送寄存器地址,
        SPI_SendByte(value);//发送寄存器值
        delay_us(100);
        Pin_CSN(1);
        return (status);
    }
    //功能:NRF24L01 读写寄存器函数
    u8 Get_Status() 
    {
        return SPI_RWReg(0x07,0xFF);
    }
    //检测是否存在
    u8 nrf24l0_check(void)
    {
        u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
        u8 i;
        SPI_WriteBuf(0x20+0x10,buf,5);
        SPI_ReadBuf(0x10,buf,5);
        for(i=0; i<5; i++)if(buf[i]!=0xA5)break;
        if(i!=5)return 1;
        return 0;
    }
    bsp_nrf0241.c

    3.stm32f0xx_it.c 中断内的函数

    #include "delay.h"
    #include "stm32f0xx.h"
    #include "bsp_nrf0241.h"
    //按键中断
    void EXTI0_1_IRQHandler(void)
    {
        if(EXTI_GetITStatus(EXTI_Line0)!= RESET)
        {
            delay_ms(20);
            if(Get_KEY0()!= RESET)//消除按键抖动
            {
                u8 tx_buf[32]={0x11};//用户测试的数据
                send_data(tx_buf,32);//发送
            }
            EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志
        }
    }
    //nrf2401收发中断
    void EXTI2_3_IRQHandler(void)
    {
        if(EXTI_GetITStatus(EXTI_Line3)!= RESET)
        {
            u8 gstatus = Get_Status();//获取状态
            //发送
            if((gstatus & 0x20) != 0)
            {
                //发送成功 LED灯闪烁一次
                Pin_LED0(0);
                delay_ms(1000);
                Pin_LED0(1);
            }
            //发送达到最大次数
            if((gstatus & 0x10) != 0)
            {
                //发送最大次数
                Pin_LED0(0);
                delay_ms(1000);
                Pin_LED0(1);
            }
            //接收
            if((gstatus & 0x40) != 0)
            {
                //接收到数据
                u8 tx_bufr[32];
                Get_Data(tx_bufr,32);
                if(tx_bufr[0] == 0x11)//和发送数据进行对比
                {
                    Pin_LED0(0);
                    delay_ms(1000);
                    Pin_LED0(1);
                }
            }
            //清除中断标志
            EXTI_ClearITPendingBit(EXTI_Line3);
        }
        ClearStatus();//清除中断
        receive_data();//继续接收
    }
    stm32f0xx_it.c

    4.delay.h 延时函数(摘自网络)

    #include "stm32f0xx.h"
    #include "delay.h"
    
    static u8  fac_us=0;//us延时倍乘数
    static u16 fac_ms=0;//ms延时倍乘数
    //初始化延迟函数
    //SYSTICK的时钟固定为HCLK时钟的1/8
    //SYSCLK:系统时钟
    void delay_init(u8 SYSCLK)
    {
        SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
        fac_us=SYSCLK/8;            
        fac_ms=(u16)fac_us*1000;
    }                                    
    //延时nms
    //注意nms的范围
    //SysTick->LOAD为24位寄存器,所以,最大延时为:
    //nms<=0xffffff*8*1000/SYSCLK
    //SYSCLK单位为Hz,nms单位为ms
    //对72M条件下,nms<=1864 
    void delay_ms(u16 nms)
    {                     
        u32 temp;           
        SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
        SysTick->VAL =0x00;           //清空计数器
        SysTick->CTRL=0x01 ;          //开始倒数  
        do
        {
            temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器              
    }   
    //延时nus
    //nus为要延时的us数.                                               
    void delay_us(u32 nus)
    {        
        u32 temp;             
        SysTick->LOAD=nus*fac_us;     
        SysTick->VAL=0x00;
        SysTick->CTRL=0x01 ;
        do
        {
            temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));
        SysTick->CTRL=0x00;
        SysTick->VAL =0X00; 
    }
    delay.h

    5.main.c 入口测试函数

    #include "stm32f0xx.h"
    #include "delay.h"
    #include "bsp_spi.h"
    #include "bsp_nrf0241.h"
    
    void daly(uint32_t a)
    {
        for(;a>0;a--);
    }
    
    int main(void)
    {
        //初始化延时函数 stm32f030为48
        delay_init(48);
        /*
        *KEY0_LED0_Config();配置一个按键和一个LED灯
        * PA0 按键
        * PA4 LED灯(系统自带的用户LED灯 低电平点亮)
        *
        *SPI_Config();配置SPI
        * PA1 NSS 片选
        * PA5 SCK 时钟
        * PA6 MISO 主机输入从机输出
        * PA7 MOSI 主机输出从机输入
        *
        *NRF_Config();配置NRF24L01
        * PA2 CE 控制收发
        * PA3 IRQ 收发中断
        */
        KEY0_LED0_Config();
        SPI_Config();
        NRF_Config();
        delay_us(20);
        if(nrf24l0_check()==0)
        {
            //存在nrf2401模块
            Pin_LED0(0);
            delay_ms(1000);
            Pin_LED0(1);
            
            receive_data();//接收
        }
        while(1){ }
    }
    main.c

    准备两块用于收发的stm32f030单片机和NRF无线模块 用杜邦线连接起来(注意 MISO 和 MOSI 要对应连接, 不要交叉连接), 有必要还要引出用于测试的key0按钮, LED是板子默认的PA4, 连接好后分别给两块板子插上烧录器烧录编译好的代码, 就可以按KEY0进行测试了, 如果另外一个单片机的LED灯亮说明成功了.

    如果有不足的地方和经验欢迎在评论区交流.

  • 相关阅读:
    关于websocket
    Convert word or html to wiki syntax
    How to center an image?
    Multiline strings in JavaScript
    JavaScript tips and tricks 4
    Use IE userdata behavior as a clientside data storage
    Confused with JavaScript prototype
    Javascript中的作用域(scope)
    JavaScript tips and tricks 2
    AOP in JavaScript
  • 原文地址:https://www.cnblogs.com/weloglog888/p/15169631.html
Copyright © 2020-2023  润新知