STM32F103ZET6驱动NRF24L01
STM32驱动NRF24L01 C语言程序

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
#define MAX_TX #define TX_OK #define RX_OK /********* #define #define #define #RX_ADR_WIDTH TX_PLOAD_WIDTH RX_PLOAD_WIDTH
Page 3
// // // // // //
/**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = SCK_Pin|MISO_Pin|MOSI_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF0_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE END 0 */ SPI_HandleTypeDef hspi1; /* SPI1 init function */ void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct; if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE();
基于STM32F103控制的NRF24L01多路无线通信设计研究

基于STM32F103控制的NRF24L01多路无线通信设计研究作者:朱重儒任哲昆来源:《中国新通信》 2018年第1期【摘要】本文基于STM32F103 控制的NRF24L01 多路无线通信系统,设计了组网、串口通信模块,因具有功耗少、有一定的抗干扰能力,但传输的距离少,适合范围较小的无线系统网络。
【关键词】 STM32F103 NRF24L01 多路无线通信设计随着智能技术、信息技术的发展,无线通信传输需求明显增强,如针对智能家具系统。
本次研究尝试设计基于STM32F103 控制的NRF24L01 多路无线通信系统。
一、基本设计1、NRF24L01 无线传输模块与组网。
无线传输模块通过计算机、数据系统主要设备,传输图像具有数据量大优势,目前比较流行的是2.4GHz 无线收发芯片,NRF24L01 芯片,该频段是全球开放的频段,能够避免低频信号、各类家电干扰,提高系统的便捷性。
在增加天线的情况下传输200m,可以通过SPI 接口进行配置,功耗比较低,放射模式发射功率约为-6dBm 时消耗电流9mA,接收模式消耗12.3mA[1]。
NRF24L01 模式下在ShockBurst 模式下,可以接收6 路通道的数据,每个数据都可以采用不同的地址,但采用前文提到的全球开放的频段,实现多路无线通信。
收到数据后,通过NRF24L01 的中断引角IRQ,将核心模块处理程序引入中断,将数据从无线模块RXFIFO 寄存器读取中来。
2、STM32F103 单片机。
STM32F103 系列32 位闪存微控制器是一种基于嵌入式开发的突破性ARM Cortex-M3 内核,系列不仅大幅度提升中断响应速度,同时具有功效低等优势,最高工作频率72MHz,有256K 字节的闪存,64K 字节静态存储器,有太网接口、2 个CAN 总线接口等接口配备,80 个输入输出接口,2 个12 位ADC 模数转换器,多种定时器。
数据采集可以选择SD 存储卡、GPS 接收模块、各种类型的感受模块等。
关于使用STM32硬件SPI驱动NRF24L01

关于使用STM32硬件SPI驱动NRF24L01+ 今天是大年初一总算有时间做点想做很久的事了,说到NRF2401可能很多电子爱好者都有用过或是软件模拟驱动又或是用单片机自带的硬件SPI来驱动,但不管是用哪种方法来驱动我想都在调试方面耗费了不少的时间(可能那些所谓的电子工程师不会出现这种情况吧!)网上的资料确实很多,但大多数都并没有经过发贴人认真测试过,有的只是理论上可以行的通但上机测试只能说是拿回来给他修改。
本文作者也是经过无助的多少天才算是调试成功了(基于STM32硬件SPI,软件模拟的以前用51单片机已经调通了今天就不准备再拿来讲了,当然如果以后有朋友有需要也可以告诉我,我也可以重新写一篇关于51的驱动的只要有时间是没有问题的。
)因为我用的是STM32F103C8T6的系统而且是刚接触不知道别的系统和我用的这个系统有多大的差别所以我不会整个代码全贴上来就完事了,我将就着重思路配合代码写出来,这样对于刚接触单片机的朋友会有很好的作用,但是还有一点请大家要原谅,可能会存在一些说的不好的地方,毕竟我没有经过正规渠道系统地学习过电子知识,对于前辈来说存在这样那样的问题不可避免的,在此也希望大家指教!贴个图先:NRF2401+的资料大家上网查一下,我输字的速度有点不好说!下面我来说一下整个调试流程吧1.先把STM32串口一调通(因为我不知道STM32 I/O口不知可不可以像51那样并口输出数据,如果可以那就更方便啰)。
2.与NRF2401建立起通信(这个才是问题的关键);3.利用读NRF2401的一个状态寄存器(STATUS)的值并通过串口发送到PC后通过51下载软件的串口助手显示出来(如果你用液晶来调试那你太有才了,你液晶和NRF2401存在牵连可能就会给寻找不成功的原因造成困难,而且还有不少硬件工作要做)在这说一下本文只调试发送程序,致于接收只改一个程序参数就行了。
我们先来调试STM32F103C8T6的串口1吧(也就是USART1)!它是STM32F103C8T6的片上外设之一,使用它时相对来说简单了不少。
nRF24L01无线模块讲解解读

数据通道
nRF24L01 在接收模式下可以接收6 路不同通道的数据。
数据通道
• 每一个数据通道使用不同的地址,但是共用相同的频道。 也就是说6 个不同的nRF24L01 设置为发送模式后可以与 同一个设置为接收模式的nRF24L01 进行通讯,而设置为 接收模式的nRF24L01 可以对这6 个发射端进行识别。 • 数据通道是通过寄存器EN_RXADDR 来设置的,默认状 态下只有数据通道0 和数据通道1 是开启状态的。 • nRF24L01在确认收到数据后记录地址,并以此地址为目 标地址发送应答信号,在发送端,数据通道0被用作接收 应答信号,因此属通道0 的接收地址要与发送地址端地址 相等,以确保接收到正确的应答信号。
封装引脚及其引脚功能
nRF单端50Ω射频输出原理图
nRF24L10与单片机应用电路图
举例:NRF24L01模块口与STM32连接原理图中断
• nRF24L01 的中断引脚(IRQ)为低电平触发,当状态寄 存器中TX_DS(数据发送完成中断位)、RX_DR(接收 数据中断位) 或MAX_RT(达到最多次重发中断位)为 高时触发中断。 • 当MCU 给中断源写‘1’时,中断引脚被禁止。可屏蔽中 断可以被IRQ 中断屏蔽。通过设置可屏蔽中断位为高,则 中断响应被禁止。默认状态下所有的中断源是被禁止的。
nRF24l01的SPI通信时序
增强型ShockBurstTM 发送模式
• 1、 配置寄存器位PRIM_RX 为低 • 2、 当MCU 有数据要发送时,接收节点地址(TX_ADDR) 和有效数据(TX_PLD)通过SPI 接口写入nRF24L01。发送 数据的长度以字节计数从MCU 写入TX FIFO。当CSN 为 低时数据被不断的写入。发送端发送完数据后,将通道0 设置为接收模式来接收应答信号,其接收地址 (RX_ADDR_P0)与接收端地址(TX_ADDR)相同。 例:在上图 中数据通道5 的发送端(TX5)及接收端(RX)地 址设置如下: TX5:TX_ADDR=0xB3B4B5B605 TX5:RX_ADDR_P0=0xB3B4B5B605 RX:RX_ADDR_P5=0xB3B4B5B605
STM32F103ZET6驱动NRF24L01.pdf

#include "bsp.h"
u8 TX_ADDRESS[TX_ADR_WIDTH]={0x02,0x02,0x02,0x02,0x02}; //发送地址
u8 RX_ADDRESS[RX_ADR_WIDTH]={0x02,0x02,0x02,0x02,0x02}; //发送地址
GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOB,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
NRF2写入的地址
for(i=0;i<5;i++)
//检测读到的数据是否正确
{
//PG6 -- CE PG7 -- CS GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //PG6 7 推挽 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化指定 IO //IRQ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOG, &GPIO_InitStructure);
STM32驱动NRF24L01

STM32驱动NRF24L01
1. 简介
NRF24L01 是nordic 的无线通信芯片,它具有以下特点:
1)2.4G 全球开放的ISM 频段(2.400 - 2.4835GHz),免许可证使用;
2)最高工作速率2Mbps,高校的GFSK 调制,抗干扰能力强;
3)125 个可选的频道,满足多点通信和调频通信的需要;
4)内置CRC 检错和点对多点的通信地址控制;
5)低工作电压(1.9~3.6V),待机模式下状态为26uA;掉电模式下为
900nA;
6)可设置自动应答,确保数据可靠传输;
7)工作于EnhancedShockBurst 具有Automatic packet handling,Auto packet transaction handling ,可以实现点对点或是 1 对 6 的无线通信,速度可以达
到2M(bps),具有可选的内置包应答机制,极大的降低丢包率。
8)通过SPI 总线与单片机进行交互,最大通信速率为10Mbps;
1.1 结构框图
如图右侧为六个控制和数据信号,分别为CSN、SCK、MISO、MOSI、IRQ、CE。
信号线功能
CSN 芯片的片选线,CSN 为低电平芯片工作
SCK 芯片控制的时钟线(SPI 时钟)
MISO 芯片控制数据线(Master input slave output)
MOSI 芯片控制数据线(Master output slave input)
IRQ 中断信号。
无线通信过程中MCU 主要是通过IRQ 与NRF24L01 进。
SPI方式STM32F103与2.4G模块NRF24L01收发通讯

1.简介通过SPI方式与NRF24L01模块进行通讯,接收到的数据通过串口1打印出来,实时监测是否收到数据,发送的数据是“2.4G TEST”,当收不到数据时打印“no data”。
一块STM32F103ZET6开发板接收数据,另一块STM32F103RBT6开发板发送数据,两个淘宝买的2.4G NRF24L01模块。
还用到一块USB转TTL模块用来电平转换传送数据,串口调试助手接收串口发送数据。
2.代码部分---------nrf24l01.h-----------#ifndef __24L01_H#define __24L01_H#include "sys.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 //空操作,可以用来读状态寄存器//SPI(NRF24L01)寄存器地址#define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;//bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能#define EN_AA 0x01 //使能自动应答功能 bit0~5,对应通道0~5#define EN_RXADDR 0x02 //接收地址允许,bit0~5,对应通道0~5#define SETUP_AW 0x03 //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;#define SETUP_RETR 0x04 //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us#define RF_CH 0x05 //RF通道,bit6:0,工作通道频率;#define RF_SETUP 0x06 //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益#define STATUS 0x07 //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发//bit5:数据发送完成中断;bit6:接收数据中断;#define MAX_TX 0x10 //达到最大发送次数中断#define TX_OK 0x20 //TX发送完成中断#define RX_OK 0x40 //接收到数据中断#define OBSERVE_TX 0x08 //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器#define CD 0x09 //载波检测寄存器,bit0,载波检测;#define RX_ADDR_P0 0x0A //数据通道0接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P1 0x0B //数据通道1接收地址,最大长度5个字节,低字节在前#define RX_ADDR_P2 0x0C //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P3 0x0D //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P4 0x0E //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define RX_ADDR_P5 0x0F //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;#define TX_ADDR 0x10 //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等#define RX_PW_P0 0x11 //接收数据通道0有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P1 0x12 //接收数据通道1有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P2 0x13 //接收数据通道2有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P3 0x14 //接收数据通道3有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P4 0x15 //接收数据通道4有效数据宽度(1~32字节),设置为0则非法#define RX_PW_P5 0x16 //接收数据通道5有效数据宽度(1~32字节),设置为0则非法#define NRF_FIFO_STATUS 0x17 //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RXFIFO满标志;bit2,3,保留//bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;////////////////////////////////////////////////////////////////////////////////////////////////////////////24L01操作线#define NRF24L01_CE_High GPIO_SetBits(GPIOB,GPIO_Pin_4) //24l01片选#define NRF24L01_CE_Low GPIO_ResetBits(GPIOB,GPIO_Pin_4) //24L01片选信号#define NRF24L01_CSN_High GPIO_SetBits(GPIOB,GPIO_Pin_5) //SPI片选信号#define NRF24L01_CSN_Low GPIO_ResetBits(GPIOB,GPIO_Pin_5)#define NRF24L01_IRQ GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6) //IRQ主机数据输入//24L01发送接收数据宽度定义#define TX_ADR_WIDTH 5 //5字节的地址宽度#define RX_ADR_WIDTH 5 //5字节的地址宽度#define TX_PLOAD_WIDTH 32 //32字节的用户数据宽度#define RX_PLOAD_WIDTH 32 //32字节的用户数据宽度void NRF24L01_Init(void); //初始化void NRF24L01_RX_Mode(void); //配置为接收模式void NRF24L01_TX_Mode(void); //配置为发送模式u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s); //读数据区u8 NRF24L01_Read_Reg(u8 reg); //读寄存器u8 NRF24L01_Write_Reg(u8 reg, u8 value); //写寄存器u8 NRF24L01_Check(void); //检查24L01是否存在u8 NRF24L01_TxPacket(u8 *txbuf); //发送一个包的数据u8 NRF24L01_RxPacket(u8 *rxbuf); //接收一个包的数据#endif-----------nrf24l01.c----------------#include "24l01.h"#include "delay.h"#include "usart.h"///////////////////////////////////////////////////////////////////////////////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;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOBGPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI 单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPISPI_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_8;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器//使能SPI外设GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4|GPIO_Pin_5; //PB12上拉防止W25X的干扰GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PG6 输入GPIO_Init(GPIOB, &GPIO_InitStructure);//使能SPI外设SPI_Cmd(SPI2, ENABLE);NRF24L01_CE_Low; //使能24L01NRF24L01_CSN_High; //SPI片选取消}//SPIx 读写一个字节//TxData:要写入的字节//返回值:读取到的字节u8 SPI2_ReadWriteByte(u8 TxData){while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //检查指定的SPI标志位设置与否:发送缓存空标志位SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据delay_us(2);while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);//检查指定的SPI标志位设置与否:接受缓存非空标志位return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据delay_us(2);}//检测24L01是否存在//返回值:0,成功;1,失败u8 NRF24L01_Check(void){u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};u8 i;//SPI2_SetSpeed(SPI_BaudRatePrescaler_4); //spi速度为9Mhz(24L01的最大SPI 时钟为10Mhz)NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址for(i=0;i<5;i++)if(buf[i]!=0XA5)break;if(i!=5)return 1;//检测24L01错误return 0; //检测到24L01}//SPI写寄存器//reg:指定寄存器地址//value:写入的值u8 NRF24L01_Write_Reg(u8 reg,u8 value){u8 status;NRF24L01_CSN_Low; //使能SPI传输status =SPI2_ReadWriteByte(reg);//发送寄存器号SPI2_ReadWriteByte(value); //写入寄存器的值NRF24L01_CSN_High; //禁止SPI传输return(status); //返回状态值}//读取SPI寄存器值//reg:要读的寄存器u8 NRF24L01_Read_Reg(u8 reg){u8 reg_val;NRF24L01_CSN_Low; //使能SPI传输SPI2_ReadWriteByte(reg); //发送寄存器号reg_val=SPI2_ReadWriteByte(0XFF);//读取寄存器内容NRF24L01_CSN_High; //禁止SPI传输return(reg_val); //返回状态值}//在指定位置读出指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len){u8 status,u8_ctr;NRF24L01_CSN_Low; //使能SPI传输status=SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI2_ReadWriteByte(0XFF);//读出数据NRF24L01_CSN_High; //关闭SPI传输return status; //返回读到的状态值}//在指定位置写指定长度的数据//reg:寄存器(位置)//*pBuf:数据指针//len:数据长度//返回值,此次读到的状态寄存器值u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len){u8 status,u8_ctr;NRF24L01_CSN_Low; //使能SPI传输status = SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI2_ReadWriteByte(*pBuf++); //写入数据NRF24L01_CSN_High; //关闭SPI传输return status; //返回读到的状态值}//启动NRF24L01发送一次数据//txbuf:待发送数据首地址//返回值:发送完成状况u8 NRF24L01_TxPacket(u8 *txbuf){u8 sta;// SPI2_SetSpeed(SPI_BaudRatePrescaler_8);//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)NRF24L01_CE_Low;NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节NRF24L01_CE_High;//启动发送//while(NRF24L01_IRQ!=0);//等待发送完成sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志if(sta&MAX_TX)//达到最大重发次数{NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器return MAX_TX;}if(sta&TX_OK)//发送完成{return TX_OK;}return 0xff;//其他原因发送失败}//启动NRF24L01发送一次数据//txbuf:待发送数据首地址//返回值:0,接收完成;其他,错误代码u8 NRF24L01_RxPacket(u8 *rxbuf){u8 sta;//SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI 时钟为10Mhz)sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志if(sta&RX_OK)//接收到数据{NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器return 0;}return 1;//没收到任何数据}//该函数初始化NRF24L01到RX模式//设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR//当CE变高后,即进入RX模式,并可以接收数据了void NRF24L01_RX_Mode(void){NRF24L01_CE_Low;NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);/ /写RX节点地址NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通信频率NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式NRF24L01_CE_High; //CE为高,进入接收模式}//该函数初始化NRF24L01到TX模式//设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR//PWR_UP,CRC使能//当CE变高后,即进入RX模式,并可以接收数据了//CE为高大于10us,则启动发送.void NRF24L01_TX_Mode(void){NRF24L01_CE_Low;NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACKNRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断NRF24L01_CE_High;//CE为高,10us后启动发送}-------usart.h----------#ifndef __USART_H#define __USART_H#include "stdio.h"#include "sys.h"/////////////////////////////////////////////////////////////////////////////// void uart_init(u32 bound);void usart1_send_string(u8 *BuffToSend);#endif---------usart.c---------------#include "sys.h"#include "usart.h"/////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);//使能USART1,GPIOA时钟//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器//USART 初始化设置USART_ART_BaudRate = bound;//串口波特率USART_ART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_ART_StopBits = USART_StopBits_1;//一个停止位USART_ART_Parity = USART_Parity_No;//无奇偶校验位USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE); //使能串口1}//打印字符串void usart1_send_string(u8 *BuffToSend){u8 i=0;while(BuffToSend[i]!='\0'){USART_SendData(USART1, BuffToSend[i]);while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);i++;}}收发主函数是分开写的,因为用的不同的芯片。
STM32学习笔记-STM32F103ZET6

STM32F103 系列芯片的系统架构:系统结构:在每一次复位以后,所有除SRAM 和FLITF 以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR 来打开该外设的时钟。
GPIO 输入输出,外部中断,定时器,串口。
理解了这四个外设,基本就入门了一款MCU。
时钟控制RCC:-4~16M 的外部高速晶振-内部8MHz 的高速RC 振荡器-内部40KHz低速RC 振荡器,看门狗时钟-内部锁相环(PLL,倍频),一般系统时钟都是外部或者内部高速时钟经过PLL 倍频后得到- 外部低速32.768K 的晶振,主要做RTC 时钟源ARM存储器映像:数据字节以小端格式存放在存储器中。
一个字里的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。
存储器映像与寄存器映射:ARM 存储器映像4GB0X0000 00000X1FFF FFFF0X2000 00000X3FFF FFFF0X4000 00000X5FFF FFFF寄存器名称相对外设基地址的偏移值编号位表读写权限寄存器位功能说明使用C语言封装寄存器:1、总线和外设基地址封装利用地址偏移(1)定义外设基地址(Block2 首地址)(2)定义APB2总线基地址(相对外设基地址偏移固定)(3)定义GPIOX外设基地址(相对APB2总线基地址偏移固定)(4)定义GPIOX寄存器地址(相对GPIOX外设基地址偏移固定)(5)使用 C 语言指针操作寄存器进行读/写//定义外设基地址#define PERIPH_BASE ((unsigned int)0x40000000) 1)//定义APB2 总线基地址#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) 2)//定义GPIOC 外设基地址#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) 3)//定义寄存器基地址这里以GPIOC 为例#define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) 4)#define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04)#define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08)#define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C)#define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10)#define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14)#define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18)//控制GPIOC 第0 管脚输出一个低电平5)GPIOC_BSRR = (0x01<<(16+0));//控制GPIOC 第0 管脚输出一个高电平GPIOC_BSRR = (0x01<<0);2、寄存器封装利用结构体、外设基地址和寄存器地址偏移typedef unsigned int uint32_t; /*无符号32 位变量*/typedef unsigned short int uint16_t; /*无符号16 位变量*//* GPIO 寄存器列表*/typedef struct{uint32_t CRL; /*GPIO 端口配置低寄存器地址偏移: 0x00 */uint32_t CRH; /*GPIO 端口配置高寄存器地址偏移: 0x04 */uint32_t IDR; /*GPIO 数据输入寄存器地址偏移: 0x08 */uint32_t ODR; /*GPIO 数据输出寄存器地址偏移: 0x0C */uint32_t BSRR; /*GPIO 位设置/清除寄存器地址偏移: 0x10 */uint32_t BRR; /*GPIO 端口位清除寄存器地址偏移: 0x14 */uint16_t LCKR; /*GPIO 端口配置锁定寄存器地址偏移: 0x18 */}GPIO_TypeDef;只要给结构体设置好首地址,就能把结构体内成员的地址确定下来,然后就能以结构体的形式访问寄存器。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/**************************************************** 函数名:SPI 初始化 形参: 返回值: 函数功能:写使能 ****************************************************/ void SPI2_Config(void) {
描述:这个函数设置 nRF24L01 为接收模式,等待接收发送设备的数据包
u8 status; CS_LOW(); // CSN 置低,开始传输数据 SPI2_ReadWriteByte(reg); // 选择寄存器 status=SPI2_ReadWriteByte(0); // 然后从该寄存器读数 CS_HIGH(); // CSN 拉高,结束数据传输
return (status); // 返回寄存器数据 } /****************************************************************************** **
timeout=0;
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET);
{
timeout++;
if(timeout>500)return 0;
}
return SPI_I2S_ReceiveData(SPI2);
}
/************************************************** 函数:SPI_RW_REG()
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //MOSI -- PB15 SCK -- PB13
//PB13 -- SPI2_CK PB14 -- SPI2_MOSI PB15 -- SPI2_MISO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; 分频值为 4
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; MSB 位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); SPI_Cmd(SPI2,ENABLE);
u8 status,i; CS_LOW(); // CSN 置低,开始传输数据 status = SPI2_ReadWriteByte(reg); // 选择寄存器,同时返回状态字 for(i=0; i<bytes; i++) {
pBuf[i]=SPI2_ReadWriteByte(0); // 逐个字节从 nRF24L01 读出 }
u8 SPI2_ReadWriteByte(u8 data)
{
u32 timeout=0;
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE) == RESET);
{
timeout++;
if(timeout>500)return 0;
}
SPI_I2S_SendData(SPI2,data);
STM32 驱动无线模块,已调好可用
#include "bsp.h"
u8 TX_ADDRESS[TX_ADR_WIDTH]={0x02,0x02,0x02,0x02,[RX_ADR_WIDTH]={0x02,0x02,0x02,0x02,0x02}; //发送地址
//PG6 -- CE PG7 -- CS GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //PG6 7 推挽 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化指定 IO //IRQ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOG, &GPIO_InitStructure);
SPI2_ReadWriteByte(*pBuf++); // 逐个字节写入 nRF24L01
} CS_HIGH(); // CSN 拉高,结束数据传输 return(status); // 返回状态寄存器
} /****************************************************************************** *
//SPI 主机模
//数据 8 位 //CPOL -
//CPHA - 0 //NSS 信号软
// 波 特 率 预
// 数 据 传 输 从
//CRC 值
CE_LOW();//待机 CS_HIGH(); } /**************************************************** 函数名:NRF24L01 初始化 形参: 返回值: 函数功能:写使能 ****************************************************/
CS_HIGH(); // CSN 拉高,结束数据传输 return(status); // 返回状态寄存器 } /****************************************************************************** **
函数:RX_Mode()
函数:NRF24L01_Read_Reg(BYTE reg)
描述:从 reg 寄存器读一字节
******************************************************************************* */
u8 NRF24L01_Read_Reg(u8 reg) {
函数:SPI_Read_Buf()
描述:从 reg 寄存器读出 bytes 个字节,通常用来读取接收通道数据或接收/发送地址
******************************************************************************* */
u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 bytes) {
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_Init(GPIOB, &GPIO_InitStructure);
//SPI 协议的初始化
/****************************************************
函数名:NRF24L01_Check
形参:无
返回值:0 -- 成功 1 -- 失败
函数功能:检测 24L01 是否存在
****************************************************/
描述: 根据 SPI 协议,写一字节数据到 nRF24L01,同时从 nRF24L01 读出一字节
**************************************************/ u8 NRF24L01_Write_Reg(u8 reg, u8 value) {
u8 status; CS_LOW(); // CSN 置低,开始传输数据 status = SPI2_ReadWriteByte(reg); // 选择寄存器,同时返回状态字 SPI2_ReadWriteByte(value); // 然后写数据到该寄存器
}
/****************************************************
函数名:SPI2_Send_Receive_Byte
形参: data -- 给 FLASH 发送的数据
返回值:flash 返回的数据
函数功能:给 FLASH 发送数据和读取数据
****************************************************/
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
//SPI2 设置为双线
全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; 0 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; 件控制
CS_HIGH(); // CSN 拉高,结束数据传输 return(status); // 返回 }