STM32F103芯片SPI控制NRF24L012.4G无线模块交互通信实验
1.NRF24L01模块的资料百度搜索一下就有很多。这里我就不做介绍本文主要侧重于应用层面实验介绍与分享。
2.先看下原理图。
根据原理图:写出NRF24L01 C语言驱动文件如下:
1 #include "nrf1024spi.h" 2 #include "usart.h" 3 4 u8 RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0xc3,0x10,0x10,0x25}; //地址 5 6 u8 TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0xc3,0x10,0x10,0x25}; //地址 7 8 u8 NRFMatched = 0; 9 static uint8_t sta; 10 11 uint8_t NRF24L01_RXDATA[RX_PLOAD_WIDTH];//nrf24l01 最大发送队列 12 uint8_t NRF24L01_TXDATA[RX_PLOAD_WIDTH];//nrf24l01 最大发送队列 13 //写寄存器 14 uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value) 15 { 16 uint8_t status; 17 SPI_CSN_L(); 18 status = SPI_RW(reg); 19 SPI_RW(value); 20 SPI_CSN_H(); 21 return status; 22 } 23 24 25 //读寄存器 26 uint8_t NRF_Read_Reg(uint8_t reg) 27 { 28 uint8_t reg_val; 29 SPI_CSN_L(); 30 SPI_RW(reg); 31 reg_val = SPI_RW(0); 32 SPI_CSN_H(); 33 34 return reg_val; 35 } 36 //接收模式 37 void SetRX_Mode(void) 38 { 39 SPI_CE_L(); 40 NRF_Write_Reg(FLUSH_RX,0xff); 41 NRF_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);// 42 NRF_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); 43 NRF_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); 44 NRF_Write_Reg(NRF_WRITE_REG+RF_CH,40); 45 NRF_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH); 46 NRF_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);// 47 NRF_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);// 48 SPI_CE_H(); 49 50 } 51 52 //发送模式 53 void SetTX_Mode(void) 54 { 55 SPI_CE_L(); 56 NRF_Write_Reg(FLUSH_TX,0xff); 57 NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH); 58 NRF_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); 59 NRF_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); 60 NRF_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); 61 NRF_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a); 62 NRF_Write_Reg(NRF_WRITE_REG+RF_CH,40); 63 NRF_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); 64 NRF_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); 65 SPI_CE_H(); 66 67 68 } 69 //SPI连接检测 70 char NRF_check(void) 71 { 72 73 u8 buf[5]={0xC1,0xC2,0xC3,0xC4,0xC5}; 74 u8 buf1[5]={0}; 75 u8 i=0; 76 77 NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5); 78 NRF_Read_Buf(TX_ADDR,buf1,5); 79 80 for (i=0;i<5;i++) 81 { 82 if (buf1[i]!=0xC1+i) 83 break; 84 } 85 86 if (i==5) 87 { 88 89 printf("NRF24L01 found...\r\n"); 90 return 1 ; 91 92 } 93 else 94 { 95 printf("NRF24L01 check failed...\r\n"); 96 return 0 ; 97 } 98 99 100 } 101 102 //写缓存 103 uint8_t NRF_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars) 104 { 105 uint8_t i; 106 uint8_t status; 107 // SPI_CE_L(); 108 SPI_CSN_L(); 109 status = SPI_RW(reg); 110 for(i=0; i<uchars; i++) 111 { 112 SPI_RW(pBuf[i]); 113 } 114 115 SPI_CSN_H(); 116 return status; 117 } 118 //读缓存 119 uint8_t NRF_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars) 120 { 121 uint8_t i; 122 uint8_t status; 123 //SPI_CE_L(); 124 SPI_CSN_L(); 125 status = SPI_RW(reg); 126 for(i=0; i<uchars; i++) 127 { 128 pBuf[i] = SPI_RW(1); 129 } 130 SPI_CSN_H(); 131 return status; 132 } 133 134 u8 SPI_RW(u8 dat) 135 { 136 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); 137 SPI_I2S_SendData(SPI1, dat); 138 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); 139 return SPI_I2S_ReceiveData(SPI1); 140 } 141 142 143 144 145 //NRF24L01 引脚初始化 146 void nfr1024initspi(void) 147 { 148 149 SPI_InitTypeDef SPI_InitStructure; 150 GPIO_InitTypeDef GPIO_InitStructure; 151 152 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 153 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 154 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); 155 156 157 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; //SCK MISO MOSI 158 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 159 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 160 GPIO_Init(GPIOA, &GPIO_InitStructure); 161 162 //ce pa12 163 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; 164 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 165 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 166 GPIO_Init(GPIOA, &GPIO_InitStructure); 167 168 //NRF_CSN--PA4 169 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 170 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 171 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 172 GPIO_Init(GPIOA, &GPIO_InitStructure); 173 174 //nrf irq 175 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; 176 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 177 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 178 GPIO_Init(GPIOA, &GPIO_InitStructure); 179 180 GPIO_SetBits(GPIOA, GPIO_Pin_4); //SPI_CSN_H(); 181 182 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 183 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 184 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 185 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 186 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 187 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 188 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // 189 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 190 SPI_InitStructure.SPI_CRCPolynomial = 7; 191 SPI_Init(SPI1, &SPI_InitStructure); 192 /* Enable SPI1 */ 193 SPI_Cmd(SPI1, ENABLE); 194 195 } 196 //读包 197 u8 NRF24L01_RxPacket_2s(void) 198 { 199 uint8_t sta = NRF_Read_Reg(NRF_READ_REG + NRFRegSTATUS); 200 if(sta & (1<<RX_DR)) 201 { 202 NRF_Read_Buf(RD_RX_PLOAD,NRF24L01_RXDATA,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer 203 //ReceiveDataFormNRF(); 204 NRF_Write_Reg(0x27, sta); 205 printf("get ===>: %s \r\n",NRF24L01_RXDATA); 206 sta = 0; 207 return 1; 208 209 }else 210 { 211 return 0; 212 } 213 214 } 215 //读包 216 u8 NRF24L01_RxPacket(u8 *rxbuf) 217 { 218 u8 sta; 219 //SPI2_SetSpeed(SPI_SPEED_4); 220 sta=NRF_Read_Reg(NRFRegSTATUS); 221 NRF_Write_Reg(NRF_WRITE_REG+NRFRegSTATUS,sta); 222 if(sta&RX_OK) 223 { 224 NRF_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH); 225 NRF_Write_Reg(FLUSH_RX,0xff); 226 return 0; 227 } 228 return 1; 229 } 230 //发包 231 u8 NRF24L01_TxPacket(u8 *txbuf) 232 { 233 234 u8 sta; 235 //SPI1_SetSpeed(SPI_SPEED_8);// 236 SPI_CE_L();//NRF24L01_CE=0; 237 NRF_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);// 238 SPI_CE_H();//NRF24L01_CE=1;// 239 while(NRF24L01_IRQ!=0);// 240 sta=NRF_Read_Reg(NRFRegSTATUS); // 241 NRF_Write_Reg(NRF_WRITE_REG+NRFRegSTATUS,sta); // 242 if(sta&MAX_TX)// 243 { 244 NRF_Write_Reg(FLUSH_TX,0xff);// 245 printf("NRF24L01 send max \r\n"); 246 return MAX_TX; 247 } 248 if(sta&TX_OK)// 249 { 250 printf("NRF24L01 send ok \r\n"); 251 return TX_OK; 252 } 253 printf("NRF24L01 send fail \r\n"); 254 return 0xff;// 255 } 256 //匹配 257 void NRFmatching(void) 258 { 259 static uint32_t nTs,nT; 260 static uint32_t writeOvertime = 2 * 1000000;// unit :us 261 262 do 263 { 264 NRFMatched = 0; 265 printf("RX_ADDRESS[4] is %d \r\n",RX_ADDRESS[4]); 266 SetRX_Mode(); // reset RX mode write RX panel address 267 delay_ms(200); // delay is needed after reset NRF 268 sta = NRF_Read_Reg(NRF_READ_REG + NRFRegSTATUS); 269 printf("NRFmatching read reg staus %d \r\n",sta); 270 if((sta & 0x0E )== 0x00) 271 { 272 printf("match 1 \r\n"); 273 NRFMatched = 1; 274 275 }else 276 { 277 printf("match 0 \r\n"); 278 RX_ADDRESS[4] ++; //search the next RX_ADDRESS 279 if(RX_ADDRESS[4] == 0xff ) 280 { 281 RX_ADDRESS[4] = 0x00; 282 } 283 } 284 285 }while((sta & 0x0E )== 0x0E); 286 287 SetRX_Mode(); // reset RX mode 288 289 }
1 #ifndef __nrf1024spi 2 #define __nrf1024spi 3 #include "stm32f10x_it.h" 4 #include "stm32f10x.h" 5 6 7 //*********************************************NRF24L01************************************* 8 #define TX_ADR_WIDTH 5 // 5 uints TX address width 9 #define RX_ADR_WIDTH 5 // 5 uints RX address width 10 11 #define RX_PLOAD_WIDTH 32 // 32 uints TX payload 12 #define TX_PLOAD_WIDTH 32 // 32 uints TX payload 13 //***************************************NRF24L01?????******************************************************* 14 #define NRF_READ_REG 0x00 15 #define NRF_WRITE_REG 0x20 16 #define RD_RX_PLOAD 0x61 17 #define WR_TX_PLOAD 0xA0 18 #define FLUSH_TX 0xE1 19 #define FLUSH_RX 0xE2 20 #define REUSE_TX_PL 0xE3 21 #define NOP 0xFF 22 //*************************************SPI(nRF24L01)?????**************************************************** 23 #define CONFIG 0x00 // 24 #define EN_AA 0x01 // 25 #define EN_RXADDR 0x02 // 26 #define SETUP_AW 0x03 // 27 #define SETUP_RETR 0x04 // 28 #define RF_CH 0x05 // 29 #define RF_SETUP 0x06 // 30 #define NRFRegSTATUS 0x07 // 31 #define OBSERVE_TX 0x08 // 32 #define CD 0x09 // 33 #define RX_ADDR_P0 0x0A // 34 #define RX_ADDR_P1 0x0B // 35 #define RX_ADDR_P2 0x0C // 36 #define RX_ADDR_P3 0x0D // 37 #define RX_ADDR_P4 0x0E // 38 #define RX_ADDR_P5 0x0F // 39 #define TX_ADDR 0x10 // 40 #define RX_PW_P0 0x11 // 41 #define RX_PW_P1 0x12 // 42 #define RX_PW_P2 0x13 // 43 #define RX_PW_P3 0x14 // 44 #define RX_PW_P4 0x15 // 45 #define RX_PW_P5 0x16 // 46 #define FIFO_STATUS 0x17 // 47 //************************************************************************************** 48 #define RX_DR 6 // 49 #define TX_DS 5 // 50 #define MAX_RT 4 51 52 #define MAX_TX 0x10 53 #define TX_OK 0x20 54 #define RX_OK 0x40 55 56 #define SPI_CE_H() GPIO_SetBits(GPIOA, GPIO_Pin_12) 57 #define SPI_CE_L() GPIO_ResetBits(GPIOA, GPIO_Pin_12) 58 59 #define SPI_CSN_H() GPIO_SetBits(GPIOA, GPIO_Pin_4) 60 #define SPI_CSN_L() GPIO_ResetBits(GPIOA, GPIO_Pin_4) 61 62 #define NRF24L01_IRQ PAin(15) //IRQ 63 void nfr1024initspi(void); 64 65 uint8_t NRF_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars); 66 67 uint8_t NRF_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars); 68 69 u8 SPI_RW(u8 dat); 70 71 void NRFmatching(void); 72 u8 Nrf_Irq(void); 73 void SetRX_Mode(void); 74 75 uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value); 76 77 uint8_t NRF_Read_Reg(uint8_t reg); 78 79 #endif
接收机Main 入口
1 int main(void) 2 { 3 4 u8 redata[32]; 5 Stm32_Clock_Init(9); 6 delay_init(72); 7 uart_init(72,115200); 8 nfr1024initspi(); 9 NRF_check(); 10 SetRX_Mode(); 11 12 while(1) 13 { 14 printf("V2019-9-6 \r\n"); 15 delay_ms(1000); 16 if(!NRF24L01_RxPacket(redata)) 17 { 18 printf("%s \r\n",redata); 19 } 20 21 } 22 return 1; 23 }
发送机Main入口
1 int main(void) 2 { 3 static char ledsta; 4 u8 a,b; 5 u8 redata[32]; 6 SystemClock_HSI(9); //系统时钟初始化,时钟源内部HSI 7 SysTick_Config(SystemCoreClock / 1000); //SysTick开启系统tick定时器并初始化其中断,1ms 8 UART1_init(SysClock,uart1baudSet); //串口1初始化 9 10 delay_ms(6000); 11 NRF24L01_INIT(); //NRF24L01初始化 12 SetTX_Mode(); //设无线模块为发送模式 13 14 15 16 while (1) 17 { 18 printf("V2019-9-6 \r\n"); 19 delay_ms(2000); 20 for(a =0;a<31;a++) 21 { 22 redata[a] = 0x31 +a; 23 } 24 redata[31]= '\0'; 25 NRF24L01_TxPacket(redata); 26 printf("sent string %s \r\n",redata); 27 } 28 return 1; 29 30 }
看下 串口打印调试的效果