求助:SPIx->DR=Data 之后寄存器都是乱码

2019-10-15 07:49发布

小弟刚学STM32f103,用到 无线模块NRF24l01 和 SPI,搞了很久单片机都没检测到 nrf24l01
问题1:SPIx->DR=Data之后,我再用串口传SPIx->DR,发现和Data不一致,而且是乱码

问题2:SPI2的MOSI管脚(PB15)用示波器看不到波形,一直是低电平。CLK是2Mhz的矩形波

描述:管脚连接方面我检查了很多遍了,没有接错;         代码用的原子例程里的无线通信部分,用不了,做了一点点修改还是不行,
         不知道我初始化有木有问题呢;
         目前一直停留在查找是否存在NRF24l01的步骤。


void SPI2_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  *SPI_InitStructure;

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


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13  | GPIO_Pin_15;       // PB13:CLK        PB15:MOSI
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
                                         
       
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8;                                //PB7:CE   PB8:CSN
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               
GPIO_Init(GPIOB, &GPIO_InitStructure);                                         
GPIO_SetBits(GPIOB,GPIO_Pin_8);                                               
       
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_9;                                    //PB9: IRQ
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PG9 êäèë  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_9);               


        SPI_Cmd(SPI2, DISABLE);
       
        SPI_InitStructure->SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
        SPI_InitStructure->SPI_Mode = SPI_Mode_Master;               
        SPI_InitStructure->SPI_DataSize = SPI_DataSize_8b;               
        SPI_InitStructure->SPI_CPOL = SPI_CPOL_High;               
        SPI_InitStructure->SPI_CPHA = SPI_CPHA_2Edge;       
        SPI_InitStructure->SPI_NSS = SPI_NSS_Soft;               
        SPI_InitStructure->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;       
        SPI_InitStructure->SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure->SPI_CRCPolynomial = 7;       
        SPI_Init(SPI2, SPI_InitStructure);  
       
        SPI_Cmd(SPI2, ENABLE);
       
        SPI2_ReadWriteByte(0xff);         


}   


u8 SPI2_ReadWriteByte(u8 TxData)
{                  
  int retry=0;                                                
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
                {
                retry++;
                if(retry>200){
               
      return 0;}
                }                          
        SPI2->DR=TxData; =============================================这里出问题了
        retry=0;
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
                {
                retry++;
                if(retry>200){
                return 0;}}                                                                              
          return SPI2->DR;                             
}








友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
xfcjava3
1楼-- · 2019-10-15 08:39
请参考我的NRF2401L程序部分,已经使用过的了,请参考。
/*************************管脚定义************************/
#define NRF24L01_CSNON  GPIOB->BSRR = GPIO_Pin_12
#define NRF24L01_CSNOFF GPIOB->BRR = GPIO_Pin_12

#define NRF24L01_CEON  GPIOB->BSRR = GPIO_Pin_11
#define NRF24L01_CEOFF GPIOB->BRR = GPIO_Pin_11




/***********************************************************************
         外设时钟使能
************************************************************************/
void RCC_Configuration(void)
{       
          /*  使能外设时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 |
                     RCC_APB2Periph_GPIOA  | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
                     RCC_APB2Periph_GPIOD  | RCC_APB2Periph_GPIOE
              , ENABLE);
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能复用IO时钟
       
        //注意: 开启TIM2时钟时,不能同时开启USART2时钟
        //原因:TIM2,USART2功能使用相同的引脚A1,PA2,PA3,PA4
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_SPI2, ENABLE);/* TIM2 clock enable */       
       
}



void NRF24L01_GPIO_SPI_Configration(void)
{   
         GPIO_InitTypeDef GPIO_InitStructure;
         SPI_InitTypeDef  SPI_InitStructure;
          
         NRF24L01_CSNON;
         NRF24L01_CEON;
       
         /* SPI2 NSS SCK MISO MOSI PB12-15 */   
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;//SPI2的I/O使能
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //NSS 推挽输出         
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //口线翻转速度为50MHz                              
        GPIO_Init(GPIOB, &GPIO_InitStructure);        //初始化函数

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15|GPIO_Pin_14;//SPI2的I/O使能
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //SCK MOSI  MISO复用推挽输出         
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //口线翻转速度为50MHz                              
        GPIO_Init(GPIOB, &GPIO_InitStructure);        //初始化函数
       
          //RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); //SPI2 时钟                     
         SPI_I2S_DeInit(SPI2);
       
          SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工模式(或是半双工)
          SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主机模式(Slave从机模式)
          SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//八位数据(16b十六位)
          SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//Low低电平有效(High高)
          SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//第几个跳变沿传输数据
          SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//NSS管脚Soft软件控制  Hard是硬件控制
          SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;//(8种时钟分频2 4 8 16 32 64 128 256)
          SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//MSB数据高位在前 LSB低位在前
          SPI_InitStructure.SPI_CRCPolynomial = 7;//校验位
          SPI_Init(SPI2, &SPI_InitStructure);         
          SPI_Cmd(SPI2, ENABLE);//使能
}

u8 SPI2_SendData(u8 SPIData)//发送数据函数 数据长度自定
{
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}
    SPI_I2S_SendData(SPI2,SPIData);

    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){}
    return (SPI_I2S_ReceiveData(SPI2));
}




u8 SPI2_ReceiveData(void)//接收数据函数 数据长度自定
{   
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
    {}
    return (SPI_I2S_ReceiveData(SPI2));
}




/****************************************************************************************************/
//功能:NRF24L01读写寄存器函数
/****************************************************************************************************/
u8 SPI_RW_Reg(u8 reg, u8 value)
{
    u8 status;

    NRF24L01_CSNOFF;                   // CSN low, init SPI transaction
    status = SPI2_SendData(reg);      // select register
    SPI2_SendData(value);             // ..and write value to it..
    NRF24L01_CSNON;                   // CSN high again

    return(status);            // return nRF24L01 status uchar
}




/****************************************************************************************************/
//功能:NRF24L01读寄存器函数
/****************************************************************************************************/
u8 SPI_Read_Reg(u8 reg)
{
    u8 reg_val;   
    NRF24L01_CSNOFF;                        //使能SPI传输
    SPI2_SendData(reg);         //发送寄存器号
    reg_val = SPI2_SendData(0XFF);//读取寄存器内容
    NRF24L01_CSNON;                        //禁止SPI传输   
    return(reg_val);                //返回状态值
}




/****************************************************************************************************/
//函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
//功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数
/****************************************************************************************************/
u8 SPI_Read_Buf(u8 reg, u8 *pBuf, u8 uchars)
{
    u8 status,uchar_ctr;

    NRF24L01_CSNOFF;                       // Set CSN low, init SPI tranaction
    status = SPI2_SendData(reg);          // Select register to write to and read status uchar

    for(uchar_ctr = 0;uchar_ctr < uchars;uchar_ctr++)
    {
       pBuf[uchar_ctr] = SPI2_SendData(0XFF);    //
    }
    NRF24L01_CSNON;                           

    return(status);                    // return nRF24L01 status uchar
}




/*********************************************************************************************************/
//函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
//功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数
/*********************************************************************************************************/
u8 SPI_Write_Buf(u8 reg, u8 *pBuf, u8 uchars)
{
    u8 status,uchar_ctr;

    NRF24L01_CSNOFF;            //SPI使能      
    status = SPI2_SendData(reg);   
    for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++)
    {
       SPI2_SendData(*pBuf++);
    }
    NRF24L01_CSNON;           //关闭SPI

    return(status);    //
}



u8 nRF24L01_TxPacket(u8 *tx_buf)
{
    u8 sta;
    NRF24L01_CEOFF;    //StandBy I模式
    SPI_Write_Buf(WRITE_REGS + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
    SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);     // 装载数据

    NRF24L01_CEON;   //置高CE,激发数据发送
    OSTimeDly(20);

    sta = SPI_Read_Reg(STATUS);  //读取状态寄存器的值   
    SPI_RW_Reg(WRITE_REGS + STATUS,sta); //清除TX_DS或MAX_RT中断标志
       
    if(sta & MAX_TX)//达到最大重发次数
    {
        SPI_RW_Reg(FLUSH_TX,0xFF);//清除TX FIFO寄存器
        return MAX_TX;
    }
    if(sta & TX_OK)//发送完成
    {
        return TX_OK;
    }
               
    return 0xff;//其他原因发送失败

}



u8 nRF24L01_RxPacket(u8 *rxbuf)
{
    u8 sta;         
    sta = SPI_Read_Reg(STATUS);  //读取状态寄存器的值      
    SPI_RW_Reg(WRITE_REGS + STATUS,sta); //清除TX_DS或MAX_RT中断标志

    if(sta & RX_OK)//接收到数据
    {
        SPI_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
        SPI_RW_Reg(FLUSH_RX,0XFF);//清除RX FIFO寄存器
        return 0;
    }   
    return 1;//没收到任何数据  
}   



/****************************************************************************************/
//NRF24L01初始化
/***************************************************************************************/
void TX_NRF24L01(void)
{
    NRF24L01_CEOFF;    // chip enable
    SPI_Write_Buf(WRITE_REGS + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址
    SPI_Write_Buf(WRITE_REGS + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址

    SPI_RW_Reg(WRITE_REGS + EN_AA, 0x01);      // 频道0自动 ACK应答允许
    SPI_RW_Reg(WRITE_REGS + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21
    SPI_RW_Reg(WRITE_REGS + SETUP_RETR, 0x1a); // 设置自动重发时间和次数:500us + 86us, 10 retrans...
    SPI_RW_Reg(WRITE_REGS + RF_CH,40);        //   设置信道工作为2.4GHZ,收发必须一致
    SPI_RW_Reg(WRITE_REGS + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
    SPI_RW_Reg(WRITE_REGS + RF_SETUP, 0x0F);      //设置发射速率为1MHZ,发射功率为最大值0dB
    SPI_RW_Reg(WRITE_REGS + CONFIG, 0x0E);      // IRQ收发完成中断响应,16位CRC ,主接收
    NRF24L01_CEON;    // chip enable
}


void RX_NRF24L01(void)
{
    NRF24L01_CEOFF;  
    SPI_Write_Buf(WRITE_REGS+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址

    SPI_RW_Reg(WRITE_REGS+EN_AA,0x01);             //使能通道0的自动应答   
    SPI_RW_Reg(WRITE_REGS+EN_RXADDR,0x01);         //使能通道0的接收地址
    SPI_RW_Reg(WRITE_REGS+RF_CH,40);              //设置RF通信频率  
    SPI_RW_Reg(WRITE_REGS+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度   
    SPI_RW_Reg(WRITE_REGS+RF_SETUP,0x0F);          //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
    SPI_RW_Reg(WRITE_REGS+CONFIG, 0x0F);           //配置基本工作模式的参数WR_UP,EN_CRC,16BIT_CRC,接收模式
    NRF24L01_CEON;    //CE为高,进入接收模式
}  







xfcjava3
2楼-- · 2019-10-15 11:07
NRF24L01.H 头文件的内容如下:

#ifndef _NRF24L01_H_
#define _NRF24L01_H_

#include "stm32f10x.h"

/*****************************************管脚定义*************************************/
#define NRF24L01_CSNON  GPIOB->BSRR = GPIO_Pin_12
#define NRF24L01_CSNOFF GPIOB->BRR = GPIO_Pin_12

#define NRF24L01_CEON  GPIOB->BSRR = GPIO_Pin_11
#define NRF24L01_CEOFF GPIOB->BRR = GPIO_Pin_11

/*****************************************地址、数据长度*************************************/
#define TX_ADR_WIDTH    5   // 5 uints TX address width
#define RX_ADR_WIDTH    5   // 5 uints RX address width
#define TX_PLOAD_WIDTH 32 // 20 uints TX payload
#define RX_PLOAD_WIDTH 32 // 20 uints TX payload
#define MAX_TX   0x10  //达到最大发送次数中断
#define TX_OK   0x20  //TX发送完成中断
#define RX_OK   0x40  //接收到数据中断
#define STATUS          0x07  //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发
/***************************************NRF24L01寄存器指令*******************************************************/
#define READ_REGS        0x00 // 读寄存器指令
#define WRITE_REGS       0x20 // 写寄存器指令
#define RD_RX_PLOAD     0x61 // 读取接收数据指令
#define WR_TX_PLOAD     0xA0 // 写待发数据指令
#define FLUSH_TX        0xE1 // 冲洗发送 FIFO指令
#define FLUSH_RX        0xE2 // 冲洗接收 FIFO指令
#define REUSE_TX_PL     0xE3 // 定义重复装载数据指令
#define NOP             0xFF // 保留
/*************************************SPI(nRF24L01)寄存器地址****************************************************/
#define CONFIG          0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式
#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 // 频道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接收数据长度
#define RX_PW_P1        0x12 // 接收频道0接收数据长度
#define RX_PW_P2        0x13 // 接收频道0接收数据长度
#define RX_PW_P3        0x14 // 接收频道0接收数据长度
#define RX_PW_P4        0x15 // 接收频道0接收数据长度
#define RX_PW_P5        0x16 // 接收频道0接收数据长度
#define FIFO_STATUS     0x17 // FIFO栈入栈出状态寄存器设置

/***********************函数声明**********************/

extern void NRF24L01_GPIO_SPI_Configration(void);

extern u8 nRF24L01_TxPacket(u8 *tx_buf);
extern u8 nRF24L01_RxPacket(u8 *rxbuf);

extern void RX_NRF24L01(void);
extern void TX_NRF24L01(void);

extern u8 SPI_Write_Buf(u8 reg, u8 *pBuf, u8 uchars);
extern u8 SPI_Read_Buf(u8 reg, u8 *pBuf, u8 uchars);

extern u8 SPI_RW_Reg(u8 reg, u8 value);

#endif



yggswhu
3楼-- · 2019-10-15 15:37
xfcjava3 发表于 2016-7-2 21:29
NRF24L01.H 头文件的内容如下:

#ifndef _NRF24L01_H_

CE CSN 是哪些管脚可以自定义,我跟你的库函数不一样,看这个没啥意义
yggswhu
4楼-- · 2019-10-15 17:21
xfcjava3 发表于 2016-7-2 21:29
NRF24L01.H 头文件的内容如下:

#ifndef _NRF24L01_H_

不好意思。。。我没看到前面的
yggswhu
5楼-- · 2019-10-15 22:35
 精彩回答 2  元偷偷看……
xfcjava3
6楼-- · 2019-10-16 03:50
看看你的端口初始化配置:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

一周热门 更多>