nrf24L01 check不通过问题分析

下面这段代码是有问题的,使nrf24L01 check不通过。

#include "stm32f10x.h" // Device header
#include "spi.h"
#include "OLED.h"
/****** SPI2引脚连接 ******/
#define PA4_SPI1_NSS GPIO_Pin_4
#define PA5_SPI1_SCK GPIO_Pin_5
#define PA6_SPI1_MISO GPIO_Pin_6
#define PA7_SPI1_MOSI GPIO_Pin_7
// SPI1初始化
//---------------------------------------------------------------------------------------------------------------
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // GPIOA时钟使能
RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1时钟使能
GPIO_InitStructure.GPIO_Pin = PA6_SPI1_MISO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOB
GPIO_InitStructure.GPIO_Pin = PA5_SPI1_SCK | PA7_SPI1_MOSI;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // PA7/6/5复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA
GPIO_SetBits(GPIOA, PA5_SPI1_SCK | PA6_SPI1_MISO | PA7_SPI1_MOSI); // PA5/6/7上拉
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // SPI主机
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 数据捕获于第1个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // NSS信号由软件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 定义波特率预分频的值:波特率预分频值为16
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE); // 使能SPI外设
SPI1_ReadWriteByte(0xFF); // 启动传输
}
//---------------------------------------------------------------------------------------------------------------
// 设置SPI速度
//---------------------------------------------------
// SPI_DivideFrequency_2 2分频: 18MHz
// SPI_DivideFrequency_4 4分频: 9MHz
// SPI_DivideFrequency_8 8分频: 4.5MHz
// SPI_DivideFrequency_16 16分频:2.25MHz
void SPI1_SetSpeed(uint8_t SPI_DivideFrequency)
{
SPI1->CR1 &= 0XFFC7;
SPI1->CR1 |= SPI_DivideFrequency; // 设置SPI1速度
// SPI_Cmd(SPI1,ENABLE);
}
//---------------------------------------------------
// SPI读写一个字节
// TxData:要写入的字节
// 返回值:读取到的字节
//-----------------------------------------------------------------------
uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{
uint8_t TxWait = 0;
uint8_t RxWait = 0;
count++;
OLED_ShowString(4, 1, "TxWt:");
// 等待发送缓存为空
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
{
TxWait++;
OLED_ShowNum(4, 6, TxWait, 3);
if (TxWait > 250) // 等待时间过长则放弃本次读写
return 0;
}
OLED_ShowString(4, 9, "RxWt:");
SPI_I2S_SendData(SPI1, TxData); // SPI1写一个字节
// 等待接收缓存为空
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
{
RxWait++;
OLED_ShowNum(4, 14, RxWait, 3);
if (RxWait > 250) // 等待时间过长则放弃本次读写
return 0;
}
return SPI_I2S_ReceiveData(SPI1); // 将读到的字节返回
}

nrf24L01_check不通过

原因就出在这行代码上:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);              // GPIOA时钟使能

nrf24l01用到了中断有IRQ引脚处理必须用到AFIO,换成这样就好了。在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

下面是网络文章摘录

端口重映射初始化过程的步骤

接下来看一下端口重映射初始化过程的步骤,拿串口1为例,除了之前使能复用功能的2个时钟之外,还需要使能AFIO功能时钟,然后调用重映射函数:

  1. GPIO端口时钟使能。要使用到端口复用,首先是要使能端口的时钟了;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  1. 复用的外设时钟使能。比如要将PB6、PB7引脚复用成串口,必须也要使能串口时钟;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  1. 使能AFIO时钟。重映射必须使能AFIO时钟;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

STM32F103:什么时候需要复用IO(AFIO)?

https://news.eeworld.com.cn/mcu/article_2018061539739.html

刚接触STM32F103,在尝试编写“按键中断”和“PWM呼吸灯”程序的时候,发现例程都用到了管脚复用AFIO:

//打开管脚复用AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

写到“232USART串口通信”程序时,当我非常自信的写下上面这句代码后,发现例程里面却没有这句话,很让人摸不着头脑……查了很多资料,加上自己的理解,发现AFIO的使用还是有点内容值得总结一下的。

AFIO介绍:

MCU有对外管脚,包括CPU的管脚和内置外设(PWM,TIM,ADC……)的管脚;
他们都需要对外接口IO,但是管脚总数是有限的,有的管脚既作为普通IO,也作为外设IO,有时候甚至好几个内置外设共用一个IO,这就是管脚复用现象。

比如随便一个管脚的原理图上:
PA2/USART2_TX/ADC123_IN2/TIM5_CH3/TIM2_CH3
表明这个管脚除了作为普通PA2之外,还作为复用IO,有USART2,ADC,TIM5,TIM2等……

总结:

  1. 普通管脚就是GPIO,复用管脚(非普通管脚)就是AFIO;
  2. 只要用到内置外设的管脚,都需要打开复用IO(AFIO),比如对外输出PWM波形,使用AD转换等。

STM32之AFIO

https://blog.sina.com.cn/s/blog_5d9349d10100u9ni.html

1、不是说使用了IO的复用功能就一定要启动RCC_APB2Periph_AFIO的Clock的,参考下图

http://hi.csdn.net/attachment/201107/5/0_1309846137454X.gif

2、只有使用了AFIO的事件控制寄存器AFIO的重映射功能以及外部中断(EXTI)控制寄存器才需要开启AFIO的时钟,STM32参考手册从来没说过使用IO的复用功能就一定要开启AFIO时钟,这是个误区。

作者:yangsail

出处:https://www.cnblogs.com/yangsail/p/18229810

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   仰望星空_22  阅读(132)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题