所言极是,能把51的资源用尽也是一代高手
我准备后期在遥控器上扩展一个LCD
到时候字库、图案库啥的一上 不知道够不够啊
肤浅理解啊
NRF24L01发送实验
相对比较顺利
接收实验倒腾了一晚上
发现连NRF24L01都检测不到
怀疑是管脚配置有问题
详情:http://forum.eepw.com.cn/thread/249476/1
欢迎各路大神来喷
NRF24L01的控制字不少
其实这个实验用到的并不多
/*******************************************************/ #define TX_ADDR_WITDH 5//发送地址宽度设置为5个字节 #define RX_ADDR_WITDH 5//接收地址宽度设置为5个字节 #define TX_DATA_WITDH 4//发送数据宽度1个字节 #define RX_DATA_WITDH 4//接收数据宽度1个字节 /*******************命令寄存器***************************/ #define R_REGISTER 0x00//读取配置寄存器 #define W_REGISTER 0x20//写配置寄存器 #define R_RX_PAYLOAD 0x61//读取RX有效数据 #define W_TX_PAYLOAD 0xa0//写TX有效数据 #define FLUSH_TX 0xe1//清除TXFIFO寄存器 #define FLUSH_RX 0xe2//清除RXFIFO寄存器 #define REUSE_TX_PL 0xe3//重新使用上一包有效数据 #define NOP 0xff//空操作 /******************寄存器地址****************************/ #define CONFIG 0x00//配置寄存器 #define EN_AA 0x01//使能自动应答 #define EN_RXADDR 0x02//接收通道使能0-5个通道 #define SETUP_AW 0x03//设置数据通道地址宽度3-5 #define SETUP_RETR 0x04//建立自动重发 #define RF_CH 0x05//射频通道设置 #define RF_SETUP 0x06//射频寄存器 #define STATUS 0x07//状态寄存器 #define OBSERVE_TX 0x08//发送检测寄存器 #define CD 0x09//载波 #define RX_ADDR_P0 0x0a//数据通道0接收地址 #define RX_ADDR_P1 0x0b//数据通道1接收地址 #define RX_ADDR_P2 0x0c//数据通道2接收地址 #define RX_ADDR_P3 0x0d//数据通道3接收地址 #define RX_ADDR_P4 0x0e//数据通道4接收地址 #define RX_ADDR_P5 0x0f//数据通道5接收地址 #define TX_ADDR 0x10//发送地址 #define RX_PW_P0 0x11//P0通道数据宽度设置 #define RX_PW_P1 0x12//P1通道数据宽度设置 #define RX_PW_P2 0x13//P2通道数据宽度设置 #define RX_PW_P3 0x14//P3通道数据宽度设置 #define RX_PW_P4 0x15//P4通道数据宽度设置 #define RX_PW_P5 0x16//P5通道数据宽度设置 #define FIFO_STATUS 0x17//FIFO状态寄存器
SPI1的配置
比较常规,可以参考数据手册和函数说明
void SPI1_Config(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //使能SPI1时钟 /* 配置SPI1的复用GPIO */ // PA5--CLK PA7--MOSI 复用推挽输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //PA6--MISO 输入浮空 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /*PB2--CE PA1--NSS (GPIOA1驱动CSN) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_Init(GPIOA, &GPIO_InitStructure); /*PA3--IRQ */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); SPI1_CE_LOW(); SPI1_NRF_CSN_HIGH();//拉高CSN 失能片选 /* 配置SPI1模块 初始化*/ //声明用来初始化的结构体 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; //空闲电平低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第一个上升沿采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS管理为软件件模式 SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8; //波特率预分频8 9MHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输低位在前 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC校验方式 SPI_Init(SPI1, &SPI_InitStructure); //初始化 // SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); SPI_Cmd(SPI1, ENABLE); //使能SPI1 }//SPI1_Config()
然后是NRF24L01的一系列子函数
这块片子其实比较傻瓜
通信过程全部硬件实现了
仅仅需要进行控制和读写
/************************************************************* **函数名: SPI_RW_Byte(SPI_TypeDef* SPIx,unsigned char Byte); **描述 : SPI写Byte **参数 : **返回值: u8 STATUS寄存器的内容 **注意 : ************************************************************/ u8 SPI_RW_Byte(SPI_TypeDef* SPIx,unsigned char Byte) { while( SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); //查发送缓冲器是否为空,空即可以发送 SPI_I2S_SendData(SPIx, Byte); //库函数:发送一个字节 //当SPI接收缓冲器为空时等待 while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPIx); }//SPI_RW_Byte() /************************************************************* **函数名: SPI_NRF_Write(char CMD,char* WBuff,char ByteNUM); **描述 : SPI1写NRF **参数 : **返回值: u8 STATUS **注意 : ************************************************************/ u8 SPI_NRF_Write(SPI_TypeDef* SPIx,char CMD,unsigned char* WBuff,unsigned char ByteNUM) { unsigned char i,status; SPI1_CE_LOW(); SPI1_NRF_CSN_LOW();//使能片选 status=SPI_RW_Byte( SPIx , CMD); for(i=0;i<ByteNUM;i++) { SPI_RW_Byte( SPIx,*WBuff++); // printf("写入第%d个数据\r\n",ByteNUM); } SPI1_NRF_CSN_HIGH();// return status; }//SPI_NRF_Write() /************************************************************* **函数名: SPI_NRF_Read(SPI_TypeDef* SPIx,char CMD,char* RBuff,char ByteNUM); **描述 : SPI1写NRF **参数 : **返回值: u8 status **注意 : ************************************************************/ u8 SPI_NRF_Read(SPI_TypeDef* SPIx,char CMD,unsigned char* RBuff,unsigned char ByteNUM) { unsigned char i,status; SPI1_CE_LOW(); SPI1_NRF_CSN_LOW(); status=SPI_RW_Byte( SPIx , CMD); for(i=0;i< ByteNUM ;i++) { RBuff[i]=SPI_RW_Byte(SPIx,NOP); // 取接收缓冲器,一个字节 //printf("读出第%d个数据\r\n",ByteNUM); } SPI1_NRF_CSN_HIGH(); return status; }//SPI_NRF_Read() /************************************************************* **函数名: SPI_NRF_MOD_TX() **描述 : 配置NRF进入 发送模式 **参数 : **返回值: **注意 : 仅用于测试 无参无返 可改成带配置参数的模块函数 Tx通道0 地址TX_ADDR=0x05B6B5B4B3 ************************************************************/ void SPI_NRF_MOD_TX(void) { u8 TX_Array[5]; u8 _TX_RX_ADDR_[5]={0xB3,0xB4,0xB5,0xB6,0x05}; SPI1_CE_LOW();//CE=0 待机模式 TX_Array[0]=0x03;//设置地址宽度 11--5字节 10--4字节 01-3字节 00--不合法 SPI_NRF_Write(SPI1,W_REGISTER+SETUP_AW,TX_Array,1); TX_Array[0]=0xf3;//建立自动重发 间隔‘1111‘--等待4000+86us 15次 SPI_NRF_Write(SPI1,W_REGISTER+SETUP_RETR,TX_Array,1); TX_Array[0]=0x02;//射频通道 X000 0010 SPI_NRF_Write(SPI1,W_REGISTER+RF_CH,TX_Array,1); TX_Array[0]=0x0f;//射频参数寄存器 0000 1111 2Mbps 发射功率 00-18dBm 01-12dBm 10-6dBm 11-0dBm 1--低噪声放大器增益 SPI_NRF_Write(SPI1,W_REGISTER+RF_SETUP,TX_Array,1); TX_Array[0]=0x3f;//xx11 1111 0-5接收通道允许 SPI_NRF_Write(SPI1,W_REGISTER+EN_RXADDR,TX_Array,1); TX_Array[0]=0x3f;//xx11 1111 0-5通道允许自动应答 SPI_NRF_Write(SPI1,W_REGISTER+EN_AA,TX_Array,1); SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证 SPI_NRF_Write(SPI1,W_REGISTER+RX_ADDR_P0,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证 TX_Array[0]=0x0e;//中断全开 发送模式 PRIM_RX=0 PWR_UP=1 SPI_NRF_Write(SPI1,W_REGISTER+CONFIG,TX_Array,1); TX_Array[0]=0xfe;//1111 xxxx STATUS寄存器 写‘1’清除所有标志 SPI_NRF_Write(SPI1,W_REGISTER+STATUS,TX_Array,1); SPI1_CE_HIGH();//CE=1 使能发射模式 delay_us(100);//CE拉高需要一定的延时才能进行发送 延时之后 即可通过SPI接口发送TX_PLD } /************************************************************* **函数名: SPI_NRF_MOD_RX() **描述 : 配置NRF进入 接收模式 **参数 : **返回值: **注意 : 仅用于测试 无参无返 可改成带配置参数的模块函数 RX通道0 地址TX_ADDR=0xB3B4B5B605 ************************************************************/ void SPI_NRF_MOD_RX(void) { u8 TX_Array[5]; u8 _TX_RX_ADDR_[5]={0xB3,0xB4,0xB5,0xB6,0x05}; SPI1_CE_LOW();//CE=0 待机模式 TX_Array[0]=0x03;//允许接收通道0000 0011 SPI_NRF_Write(SPI1,W_REGISTER+EN_RXADDR,TX_Array,1); TX_Array[0]=0x03;//设置地址宽度 11--5字节 10--4字节 01-3字节 00--不合法 SPI_NRF_Write(SPI1,W_REGISTER+SETUP_AW,TX_Array,1); TX_Array[0]=0x20;//射频通道 X000 0010 SPI_NRF_Write(SPI1,W_REGISTER+RF_CH,TX_Array,1); TX_Array[0]=0x0f;//射频参数寄存器 0000 1111 2Mbps 发射功率 00-18dBm 01-12dBm 10-6dBm 11-0dBm 1--低噪声放大器增益 SPI_NRF_Write(SPI1,W_REGISTER+RF_SETUP,TX_Array,1); TX_Array[0]=0x3f;//xx11 1111 0-5通道允许自动应答 SPI_NRF_Write(SPI1,W_REGISTER+EN_AA,TX_Array,1); TX_Array[0]=0x04;//xx11 1111 数据通道0 有效数据宽度 (1-32)字节 SPI_NRF_Write(SPI1,W_REGISTER+RX_PW_P0,TX_Array,1); TX_Array[0]=0xfe;//1111 xxxx STATUS寄存器 写‘1’清除所有标志 SPI_NRF_Write(SPI1,W_REGISTER+STATUS,TX_Array,1); SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证 SPI_NRF_Write(SPI1,W_REGISTER+RX_ADDR_P0,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证 TX_Array[0]=0x0f;//接收模式 PRIM_RX=1 PWR_UP=1 允许接收终端 SPI_NRF_Write(SPI1,W_REGISTER+CONFIG,TX_Array,1); SPI1_CE_HIGH();//CE=1 使能发射模式 delay_us(100);//CE拉高需要一定的延时才能进行发送 延时之后 即可通过SPI接口发送TX_PLD //轮询中断24L01中断的到来 NRF_Read_IRQ() } /************************************************************* **函数名: SPI_NRF_TX_DATAS() **描述 : 配置NRF发送 数据 **参数 : TBuff[ByteNUM] ByteNUM **返回值: ErrorStatus **注意 : ************************************************************/ ErrorStatus SPI_NRF_TX_DATAS(u8* TBuff,u8 ByteNUM) { u8 Status[1]; do{ SPI1_CE_LOW();//拉低待机 SPI_NRF_Write(SPI1,W_TX_PAYLOAD,TBuff,ByteNUM);//发送TBuff数组 SPI1_CE_HIGH();//拉低待机 } while(NRF_Read_IRQ()!=0);//中断产生时,IRQ引脚低电平 SPI_NRF_Write(SPI1, FLUSH_TX,TBuff,0); SPI1_CE_LOW();//拉低待机 delay_us(100); SPI_NRF_Read(SPI1,R_REGISTER+STATUS,Status,1);//读取Status if(Status[0]&0x10) { Status[0]&=0x10; SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);// printf("Tx Error!\r\n");//重发超时 发送失败 return ERROR; } else { Status[0]&=0x20; SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);// printf("Tx Success\r\n");//发送成功 return SUCCESS; } } /************************************************************* **函数名: SPI_NRF_RX_DATAS() **描述 : 配置NRF发送 数据 **参数 : RBuff[ByteNUM] ByteNUM **返回值: ErrorStatus **注意 : ************************************************************/ ErrorStatus SPI_NRF_RX_DATAS(u8* RBuff) { ErrorStatus RX_Status=SUCCESS; u8 Status[1]; while(NRF_Read_IRQ()!=0);//中断产生时,IRQ引脚低电平 SPI1_CE_LOW();//拉低待机,才能操作寄存器 delay_us(100); SPI_NRF_Read(SPI1,R_REGISTER+STATUS,Status,1);//读取Status switch(Status[0]&0x0e) { case 0x0e: RX_Status=ERROR; break; //RX_FIFO 空 default : printf("Rx Success!\r\n");//RX_FIFO非空 break; /* case 0x00: break; //通道0 case 0x02: break; //通道1 case 0x04: break; //通道2 case 0x06: break; //通道3 case 0x08: break; //通道4 case 0x0A: break; //通道5*/ } SPI_NRF_Read(SPI1,R_RX_PAYLOAD,RBuff,4);//读RX_FIFO SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);//处理状态寄存器标志 return RX_Status; } /************************************************************* **函数名: NRF_Check **描述 : 检测器件 **参数 : **返回值: 0:正常,1:有误 **注意 : ************************************************************/ u8 NRF_Check(void) { u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5}; u8 i; SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,buf,5); SPI_NRF_Read(SPI1,TX_ADDR,buf,5); for(i=0;i<5;i++) if(buf[i]!=0XA5) break; if(i!=5) return 1;//检测有误 return 0; //检测无误 }
还是把USART1初始化了一下
方便调试
/************************************************************* **函数名: usart_Configuration() **描述 : 配置USART1 **参数 : **返回值: **注意 : ************************************************************/ void usart_Configuration() { USART_InitTypeDef USART_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* PA10 USART1_Rx */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* USARTx configured as follow: - BaudRate = 115200 baud - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled */ USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; USART_ClockInit(USART1, &USART_ClockInitStructure); USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); /* Configure four bit for preemption priority */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); /* Enable the USART1 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
看看主函数的内容
其实就是USAT1、SPI1初始化
检测NRF24L01的在线情况
然后进入一个数据发送的无条件循环
usart_Configuration(); printf("USART1测试成功!!!!!\r\n"); SPI1_Config(); printf("SPI初始化成功!!!!!!\r\n"); while(NRF_Check()); printf("NRF2401正常在线!!!!\r\n"); SPI_NRF_MOD_TX(); printf("NRF2401发送模式!!!!\r\n"); while(1) { Errcode = SPI_NRF_TX_DATAS(Tx_buf,5); SPI_RW_Byte(SPI1,FLUSH_TX);//清空FIFO LED_On; if(Errcode == 1) {printf("Yeah,All Data TXed\r\n");} else {printf("Shit,All Data can not TX\r\n");} LED_Off; delay_ms(2500); }
看看视频:
视频地址:http://player.youku.com/player.php/sid/XNjkzNzMxMDIw/v.swf
有奖活动 | |
---|---|
【有奖活动——B站互动赢积分】活动开启啦! | |
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |