2401 一个简略的SPI 接口的 2.4G 射频模块 淘宝价20¥,DIY 的17¥ ,算是廉价。
u8 sta; //界说一个可位寻址的变量sta
uc8 TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};
char RX_BUF[256];
uchar TX_BUF[256];
void RF_SPI_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
/* PB15-MOSI2,PB13-SCK2*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_0);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 装备中止线0为下降触发*/
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_2);//预置为高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_4);//预置为高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);//预置为高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
SPI_Cmd(SPI2, DISABLE); //必须先禁能,才干改动MODE
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//两线全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//CPOL=0 时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//CPHA=0 数据捕获第1个
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//软件NSS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64 ;//64分频
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC7
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
但牢记不行疏忽SPI的硬件接纳,由于读SPI_DR才干铲除RXEN
***************************************************************/
u8 SPI_RW(u8 byte)
{
/*等候发送寄存器空*/
while((SPI2->SR & SPI_I2S_FLAG_TXE)==RESET);
/*发送一个字节*/
SPI2->DR = byte;
/* 等候接纳寄存器有用*/
while((SPI2->SR & SPI_I2S_FLAG_RXNE)==RESET);
return(SPI2->DR);
}
/**************************************************
函数:SPI_RW_Reg()
描绘:写数据value到reg寄存器
*************************************************/
u8 SPI_RW_Reg(u8 reg, u8 value)
{
u8 status;
CSN_L; // CSN置低,开端传输数据
status = SPI_RW(reg); // 挑选寄存器,一起回来状况字
SPI_RW(value); // 然后写数据到该寄存器
CSN_H; // CSN拉高,完毕数据传输
return(status); // 回来状况寄存器
}
/**************************************************
函数: init_io()
描绘:初始化IO
*************************************************/
void RX_Mode(void);
void init_io(void)
{
CE_L; // 待机
CSN_H; // SPI制止
LED1;// 封闭指示灯
RX_Mode();//接纳
}
函数:SPI_Read()
描绘:从reg寄存器读一字节
*************************************************/
u8 SPI_Read(u8 reg)
{
u8 reg_val;
CSN_L; // CSN置低,开端传输数据
SPI_RW(reg); // 挑选寄存器
reg_val = SPI_RW(0); // 然后从该寄存器读数据
CSN_H; // CSN拉高,完毕数据传输
return(reg_val); // 回来寄存器数据
}
函数:SPI_Read_Buf()
描绘:从reg寄存器读出bytes个字节,一般用来读取接纳通道
数据或接纳/发送地址
*************************************************/
uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes)
{
uchar status, i;
CSN_L; // CSN置低,开端传输数据
status = SPI_RW(reg); // 挑选寄存器,一起回来状况字
for(i=0; i
CSN_H; // CSN拉高,完毕数据传输
return(status); // 回来状况寄存器
}
函数:SPI_Write_Buf()
描绘:把pBuf缓存中的数据写入到nRF24L01,一般用来写入发
射通道数据或接纳/发送地址
*************************************************/
uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
{
uchar status, i;
CSN_L; // CSN置低,开端传输数据
status = SPI_RW(reg); // 挑选寄存器,一起回来状况字
for(i=0; i
CSN_H; // CSN拉高,完毕数据传输
return(status); // 回来状况寄存器
}
函数:RX_Mode()
描绘:这个函数设置nRF24L01为接纳形式,等候接纳发送设备的数据包
*************************************************/
void RX_Mode(void)
{
CE_L;
SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 接纳设备接纳通道0运用和发送设备相同的发送地址
SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // 使能接纳通道0主动应对
SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // 使能接纳通道0
SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // 挑选射频通道0x40
SPI_RW_Reg(RF_WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接纳通道0挑选和发送通道相同有用数据宽度
SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接纳形式
CE_H; // 拉高CE发动接纳设备
}
函数:TX_Mode()
描绘:
这个函数设置nRF24L01为发送形式,(CE=1继续至少10us),
130us后发动发射,数据发送完毕后,发送模块主动转入接纳
形式等候应对信号。
*************************************************/
void TX_Mode(uchar * BUF)
{
CE_L;
SPI_Write_Buf(RF_WRITE_REG + TX_ADDR, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址
SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 为了应对接纳设备,接纳通道0地址和发送地址相同
SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 写数据包到TX FIFO
SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // 使能接纳通道0主动应对
SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // 使能接纳通道0
SPI_RW_Reg(RF_WRITE_REG + SETUP_RETR, 0x0a); // 主动重发延时等候250us+86us,主动重发10次
SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // 挑选射频通道0x40
SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电
CE_H;CE_H;delay_ms(1);
}
函数:Check_ACK()
描绘:
查看接纳设备有无接纳到数据包,设定没有收到应对信
号是否重发
***************************************************/
uchar Check_ACK(u8 clear)
{
while(IRQ);
sta = SPI_RW(NOP); // 回来状况寄存器
if(MAX_RT)
if(clear) // 是否铲除TX FIFO,若没有铲除在铲除MAX_RT中止标志后重发
SPI_RW(FLUSH_TX);
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 铲除TX_DS或MAX_RT中止标志
IRQ_H;
if(TX_DS)
return(0x00);
else
return(0xff);
}
{
u16 i=65535;
TX_Mode((u8*)&flong); //传送长度
while(!tran&&i>1)i–; //等候完结
tran=0;
flong=flong/33+1;
for(i=0;i<20000;i++);//130uS*2延时
while(flong)
{
if(MAX_RT) return;//无应对回来
TX_Mode(fp); //传送数据
while(!tran&&i>1)i–; //等候完结
tran=0;
for(i=0;i<20000;i++);//130uS*2延时
fp+=32;flong–;
}
void test (void)
{
if (Uart2_Get_Flag!=0&&Timer2==0)
{
sent_data(TX_BUF,(u16)Uart2_Get_Flag);
Uart2_Get_Flag=0;
}
if(Timer2==0&&RX_NU==2)
{
RX_NU=1;
USART2_Puts(“传输过错 “);
USART2_Puts(“\r\n”);
}
}
* Function Name : EXTI0_IRQHandler
* Description : This function handles External interrupt Line 0 request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
extern u8 sta;
extern char RX_BUF[256];
extern uchar TX_BUF[256];
extern u8 SPI_RW_Reg(u8 reg, u8 value);
extern void RX_Mode(void);
extern uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes);
u8 RX_NU=1;//1接纳长度 2接纳数据
u16 rectnu,onerc; //接纳串长,接纳次数
char* PRX_BUF=RX_BUF;
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0);
tran=1;
CSN_L;
sta=SPI_RW(NOP); // 回来状况寄存器
CSN_H;
if(MAX_RT)
{
USART2_Puts(“对方无应对 “);
CSN_L;
SPI_RW(FLUSH_TX); // 铲除TX FIFO,若没有铲除在铲除MAX_RT中止标志后重发
CSN_H;
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta);
}
if(TX_DS)
{
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 铲除TX_DS或MAX_RT中止标志
}
{
if(RX_NU==1)
{
CE_L;
SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // 从RX FIFO读出数据
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 铲除RX_DS中止标志
rectnu=RX_BUF[0];rectnu|=RX_BUF[1]<<8; //接纳串长
onerc=rectnu/33+1; //核算接纳次数
RX_NU=2;RX_Mode();Timer2=500;/*超时时刻*/
return;
}
{
CE_L;
SPI_Read_Buf(RD_RX_PLOAD, PRX_BUF, TX_PLOAD_WIDTH); // 从RX FIFO读出数据
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 铲除RX_DS中止标志
onerc–;PRX_BUF+=32; //接纳计数 接纳指针移动
{
RX_BUF[rectnu]=\0; //截取有用串长
USART2_Puts(RX_BUF); //串口发送接纳到的字符
USART2_Puts(“\r\n”);
PRX_BUF=RX_BUF; //康复指针
RX_NU=1;
}
return;
}
}
LED;
RX_Mode();
/*******************************************************************************
* Function Name : USART2_IRQHandler
* Description : This function handles USART2 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
extern u16 Uart2_Get_Flag;
extern u8 Uart2_Get_Data;
extern u8 TX_BUF[256];
void USART2_IRQHandler(void)
{
//接纳中止
if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)
{
Timer2=500;//500MS后nfr2401发送
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
TX_BUF[Uart2_Get_Flag]=USART_ReceiveData(USART2);
Uart2_Get_Flag++;
//USART2_Puts(TX_BUF);
}
//溢出-假如产生溢出需求先读SR,再读DR寄存器 则可铲除不断入中止的问题
if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET)
{
USART_ClearFlag(USART2,USART_FLAG_ORE);//读SR
USART_ReceiveData(USART2);//读DR
}
}
在 外部中止中 能够一次传输最少要两次 第一次RX_NU==1 用来接纳此次传输的数据长度 用来截取有用串长,第2次RX_NU==2 就收数据放到数组里 若是数据善于32个字节就分屡次传输。其间引进 超时机制 若是200/500 MS 后传输还没完结(RX_NU再次 等于1)就抛弃接纳数据 直接接纳再次新的串长度。这个机制很重要但还有待完善。
串口中也相同500MS 还没新的数据进来就阐明串口接纳完结 之后就发送数据。Uart2_Get_Flag 当然便是串长了。
NRF24L01 能够参阅其数据手册 都是中文好说好说~~这儿就不提了。
#ifndef _API_DEF_
#define _API_DEF_
// Define interface to nRF24L01
//* Define SPI pins
/*sbit CE = P1^0; // Chip Enable pin signal (output)
sbit CSN = P1^1; // Slave Select pin, (output to CSN, nRF24L01)
sbit IRQ = P1^3; // Interrupt signal, from nRF24L01 (input)
sbit MISO = P1^4; // Master In, Slave Out pin (input)
sbit MOSI = P1^5; // Serial Clock pin, (output)
sbit SCK = P1^7; // Master Out, Slave In pin (output)
*/
// SPI(nRF24L01) commands
#define RF_READ_REG 0x00 // Define read command to register
#define RF_WRITE_REG 0x20 // Define write command to register
#define RD_RX_PLOAD 0x61 // Define RX payload register address
#define WR_TX_PLOAD 0xA0 // Define TX payload register address
#define FLUSH_TX 0xE1 // Define flush TX register command
#define FLUSH_RX 0xE2 // Define flush RX register command
#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command
#define NOP 0xFF // Define No Operation, might be used to read status register
// SPI(nRF24L01) registers(addresses)
#define CONFIG 0x00 // Config register address
#define EN_AA 0x01 // Enable Auto Acknowledgment register address
#define EN_RXADDR 0x02 // Enabled RX addresses register address
#define SETUP_AW 0x03 // Setup address width register address
#define SETUP_RETR 0x04 // Setup Auto. Retrans register address
#define RF_CH 0x05 // RF channel register address
#define RF_SETUP 0x06 // RF setup register address
#define STATUS 0x07 // Status register address
#define OBSERVE_TX 0x08 // Observe TX register address
#define CD 0x09 // Carrier Detect register address
#define RX_ADDR_P0 0x0A // RX address pipe0 register address
#define RX_ADDR_P1 0x0B // RX address pipe1 register address
#define RX_ADDR_P2 0x0C // RX address pipe2 register address
#define RX_ADDR_P3 0x0D // RX address pipe3 register address
#define RX_ADDR_P4 0x0E // RX address pipe4 register address
#define RX_ADDR_P5 0x0F // RX address pipe5 register address
#define TX_ADDR 0x10 // TX address register address
#define RX_PW_P0 0x11 // RX payload width, pipe0 register address
#define RX_PW_P1 0x12 // RX payload width, pipe1 register address
#define RX_PW_P2 0x13 // RX payload width, pipe2 register address
#define RX_PW_P3 0x14 // RX payload width, pipe3 register address
#define RX_PW_P4 0x15 // RX payload width, pipe4 register address
#define RX_PW_P5 0x16 // RX payload width, pipe5 register address
#define FIFO_STATUS 0x17 // FIFO Status Register register address
#endif /* _API_DEF_ */
#ifndef HAL_H
#define HAL_H
//硬件初始化
extern void ChipHalInit(void);
extern void ChipOutHalInit(void);
extern void delay_ms(u16 dly_ms);
extern void USART_Configuration(void);
extern void RF_SPI_Config(void);
extern volatile u16 Timer1,Timer2;
//RF_2401
extern void init_io(void);
extern void test (void);
extern u8 tran;//中止进入标志
extern u8 SPI_Read(u8 reg);
extern u8 SPI_RW(u8 byte);
#define TX_ADR_WIDTH 5 // 5字节宽度的发送/接纳地址
#define TX_PLOAD_WIDTH 32 // 接纳字节数32个字
#define uchar u8
/*操控引脚*/
#define CE_HGPIOC->BSRR=GPIO_Pin_4
#define CE_LGPIOC->BRR=GPIO_Pin_4
#define CSN_HGPIOB->BSRR=GPIO_Pin_2
#define CSN_LGPIOB->BRR=GPIO_Pin_2
#define IRQ(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0))
#define IRQ_HGPIOB->BSRR=GPIO_Pin_0
#define LED1GPIOB->BSRR=GPIO_Pin_12
#define LED0GPIOB->BRR=GPIO_Pin_12
#define LED GPIOB->ODR=((GPIOD->ODR)^GPIO_Pin_12)
#define RX_DR ((sta>>6)&0X01)
#define TX_DS ((sta>>5)&0X01)
#define MAX_RT ((sta>>4)&0X01)
//USART
extern void USART2_Putc(unsigned char c);
extern void USART2_Puts(char * str);
extern u16 Uart2_Get_Flag;//串口2接纳到数据长度
extern u8 Uart2_Get_Data;//串口2接纳的数据
#endif
中止用前留意优先级的设置
#include “STM32Lib\\stm32f10x.h”
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 装备中止运用组合1*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* EXTI0*/
NVIC_InitStructure.NVIC_IRQChannel =EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*UART2*/
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NV%&&&&&%_InitStructure);
}