打印

[已解决]STM32F0 无法使NRF2401工作,求达人指点迷津!

[复制链接]
8576|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wgsxsm|  楼主 | 2012-8-18 19:16 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 wgsxsm 于 2012-8-20 11:38 编辑

首先,说一下情况:
参考STM32F0开发板的例程中的推挽输出(参照GPIO),上拉输入(参照EXTI),复用输出(参照UART),然后照着正点原子的ALIENTEK MINISTM32 实验 无线通信实验完成了连线以及配置,但是,无法使这两个板子通讯,经过检测,发现F0的板子的NRF24L01_Check()一直无法过去,while在那里,现在传上代码,请达人们给予指点,谢谢了

程序很简单,就是初始化24L01及检测它的存在

主函数部分
int main(void)
{

   
    NRF24L01_Init();    //初始化NRF24L01
    while(NRF24L01_Check());//检测24L01,一直死在这里,很不解

  while (1)
  {

  }
}

24L01函数部分

const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
                                 
//初始化24L01的IO口
void NRF24L01_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOC, ENABLE);   

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ;   //推挽输出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ;   //推挽输出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC,GPIO_Pin_4);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN  ;   //上拉输入
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    SPIx_Init();    //初始化SPI
   
    Clr_NRF24L01_CE;     //使能24L01  NRF24L01_CE
    Set_NRF24L01_CSN;    //SPI片选取消 NRF24L01_CSN               
}

void SPIx_Init(void)
{

        GPIO_InitTypeDef GPIO_InitStructure;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE );        
        
        GPIO_DeInit(GPIOA);

  /* Connect pin to Periph */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);   
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_0);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_0);
  
  /* Configure pins as AF pushpull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                //选择了串行时钟的稳态:时钟悬空低电平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        //数据捕获于第一个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;                //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

        SPI_Cmd(SPI1, ENABLE); //使能SPI外设
        
        SPIx_ReadWriteByte(0xff);//启动传输        
}   

//检测24L01是否存在
//返回值:0,成功;1,失败        
u8 NRF24L01_Check(void)
        {
        u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
        u8 i;
        SPIx_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)            
        NRF24L01_Write_Buf(NRF24L01_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.        
        NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
        for(i=0;i<5;i++)if(buf!=0XA5)break;                                                                    
        if(i!=5)return 1;//检测24L01错误        
        return 0;                 //检测到24L01
        }
沙发
wgsxsm|  楼主 | 2012-8-18 19:18 | 只看该作者
//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPIx_ReadWriteByte(u8 TxData)
{        
    u8 retry=0;                 
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
        {
        retry++;
        if(retry>200)return 0;
        }              
    SPI_I2S_SendData16(SPI1, TxData); //通过外设SPIx发送一个数据
    retry=0;
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位
        {
        retry++;
        if(retry>200)return 0;
        }                                 
    return SPI_I2S_ReceiveData16(SPI1); //返回通过SPIx最近接收的数据                        
}


红色部分和原子的不一样,因为F0的SPI部分有
void SPI_SendData8(SPI_TypeDef* SPIx, uint8_t Data)
uint8_t SPI_ReceiveData8(SPI_TypeDef* SPIx)

使用特权

评论回复
板凳
znsword| | 2012-8-18 23:03 | 只看该作者
到NRF24L01_Check里面看看运行到哪里死掉了?

使用特权

评论回复
地板
wgsxsm|  楼主 | 2012-8-19 15:48 | 只看该作者
到NRF24L01_Check里面看看运行到哪里死掉了?
znsword 发表于 2012-8-18 23:03


//检测24L01是否存在
//返回值:0,成功;1,失败        
u8 NRF24L01_Check(void)
        {
        u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
        u8 i;
        SPIx_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)            
        NRF24L01_Write_Buf(NRF24L01_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.        
        NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
        for(i=0;i<5;i++)if(buf!=0XA5)break;                                                                    
        if(i!=5)return 1;//检测24L01错误        
        return 0;                 //检测到24L01
        }



发送的是 A5 A5 A5 A5 A5
接收到的不是,所以就一直在那里打转

使用特权

评论回复
5
wgsxsm|  楼主 | 2012-8-19 16:29 | 只看该作者

使用特权

评论回复
6
wgsxsm|  楼主 | 2012-8-19 16:29 | 只看该作者
很奇怪为什么接收的第一个数据变化掉了

使用特权

评论回复
7
znsword| | 2012-8-19 18:02 | 只看该作者
呵呵!我用STM32F0+SPI+5110的时候也出现类似的情况,发送给5110的第一个数据总是不对,最后导致字模数据错位,最后一个显示不出来,后来我在发送完最后一个数据之后又发了一个0,就可以了。具体原因还没有弄明白,不过你可以试试这种方法。

使用特权

评论回复
8
wgsxsm|  楼主 | 2012-8-19 18:45 | 只看该作者
7# znsword
谢谢,我已经搞定了,原来配置SPI时候少加了一条语句,而,这条语句对应的M3里好像没有

使用特权

评论回复
9
znsword| | 2012-8-19 19:09 | 只看该作者
LZ能不能透漏下少加了那条语句?

使用特权

评论回复
10
wgsxsm|  楼主 | 2012-8-19 21:14 | 只看该作者
9# znsword

  SPI_RxFIFOThresholdConfig(SD_SPI, SPI_RxFIFOThreshold_QF);

参考了一个SD卡的程序,那个SD_SPI=SPI1

使用特权

评论回复
11
sinadz| | 2012-8-19 23:00 | 只看该作者
9# znsword

  SPI_RxFIFOThresholdConfig(SD_SPI, SPI_RxFIFOThreshold_QF);

参考了一个SD卡的程序,那个SD_SPI=SPI1
wgsxsm 发表于 2012-8-19 21:14

有时参考一些比较好的程序,可以帮助很快找到问题

使用特权

评论回复
12
火箭球迷| | 2012-8-19 23:12 | 只看该作者
找这些问题,除了需要经验还需要一些耐心的

使用特权

评论回复
13
xsgy123| | 2012-8-19 23:19 | 只看该作者
LZ这解决问题的速度还是挺快的

使用特权

评论回复
14
wgsxsm|  楼主 | 2012-8-19 23:20 | 只看该作者
11# sinadz

是的

使用特权

评论回复
15
wgsxsm|  楼主 | 2012-8-19 23:21 | 只看该作者
13# xsgy123
一条语句浪费了我两天的时间
都是M0惹的祸

使用特权

评论回复
16
bh7kve| | 2013-2-6 20:12 | 只看该作者
这个函数的作用是?

使用特权

评论回复
17
rhyem| | 2013-10-30 19:51 | 只看该作者
楼主,还是不能用哦!

使用特权

评论回复
18
jjkkty| | 2014-5-6 16:40 | 只看该作者
楼主 能不能说一下你是怎么发现这个语句的?我在f429上遇到了同样的问题,也是check不过去

使用特权

评论回复
19
jjkkty| | 2014-5-6 17:14 | 只看该作者
好吧,你是看了一个SD卡的程序,我也好好看看

使用特权

评论回复
20
cailantu| | 2014-11-30 11:15 | 只看该作者
jjkkty 发表于 2014-5-6 17:14
好吧,你是看了一个SD卡的程序,我也好好看看

您好,你问题解决了么?我这两天也遇到了同样的问题,加了那个语句,也是没办法通过。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

34

主题

652

帖子

4

粉丝