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);
}
void sent_data(u8* fp,u16 flong)
{
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 用来接收此次传输的数据长度 用来截取有效串长,第二次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_H GPIOC->BSRR=GPIO_Pin_4
#define CE_L GPIOC->BRR=GPIO_Pin_4
#define CSN_H GPIOB->BSRR=GPIO_Pin_2
#define CSN_L GPIOB->BRR=GPIO_Pin_2
#define IRQ (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0))
#define IRQ_H GPIOB->BSRR=GPIO_Pin_0
#define LED1 GPIOB->BSRR=GPIO_Pin_12
#define LED0 GPIOB->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(&NVIC_InitStructure);
}
上一篇:STM32 代码中类型修饰符 volatile 的作用
下一篇:STM32驱动MAX6675读取温度
推荐阅读最新更新时间:2024-03-16 15:13
设计资源 培训 开发板 精华推荐
- 课随你变 票选你选型觉得最困难的元器件,干货越多礼品越大!
- 下载有礼:泰克全新 5 系列 MSO 混合信号示波器
- 下载有礼|精华课件汇编:泰克半导体器件的表征及可靠性研究交流会暨吉时利测试测量年度研讨会
- EEWORLD新年有奖竞猜,邀你来出题啦!
- 【投票跟帖有礼】原厂的翻新仪器怼市场上的二手仪器,你顶谁?
- 美信基础模拟IC APP下载 助力您创新模拟设计!评论、抢楼全有礼!
- 联想栗子工业智能开发板抢先首发!免费申请进行时~另有12 月 22 日深圳技术沙龙邀您莅临!
- 听技术大咖侃谈Type-C 测量那些事儿—— 即刻获取能量,轻松闯关赢礼品!
- 看视频瓜分红包:面向高效高密度开关电源的先进功率 MOSFET 技术及应用