【STM32】无线通信实验代码详解
生活随笔
收集整理的這篇文章主要介紹了
【STM32】无线通信实验代码详解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- main.c
- 24l01.c
- 24l01.h
main.c
#include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "lcd.h" #include "key.h" #include "spi.h" #include "24l01.h" int main(void){ u8 key,mode;u16 t=0; u8 tmp_buf[33]; delay_init(); //延時函數(shù)初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置中斷優(yōu)先級分組2uart_init(9600); //串口初始化為9600LED_Init(); //初始化與LED連接的硬件接口LCD_Init(); //初始化LCD KEY_Init(); //按鍵初始化NRF24L01_Init(); //初始化NRF24L01 POINT_COLOR=RED; //設置字體為紅色 LCD_ShowString(60,50,200,16,16,"Mini STM32"); LCD_ShowString(60,70,200,16,16,"NRF24L01 TEST"); LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(60,110,200,16,16,"2014/3/12"); while(NRF24L01_Check()) //檢查NRF24L01是否在位. {LCD_ShowString(60,130,200,16,16,"NRF24L01 Error");delay_ms(200);LCD_Fill(60,130,239,130+16,WHITE);delay_ms(200);} LCD_ShowString(60,130,200,16,16,"NRF24L01 OK");while(1) //在該部分確定進入哪個模式!{key=KEY_Scan(0);if(key==KEY0_PRES){mode=0; break;}else if(key==KEY1_PRES){mode=1;break;}t++;if(t==100)LCD_ShowString(10,150,230,16,16,"KEY0:RX_Mode KEY1:TX_Mode"); //閃爍顯示提示信息if(t==200){ LCD_Fill(10,150,230,150+16,WHITE);t=0; }delay_ms(5); } LCD_Fill(10,150,240,166,WHITE); //清空上面的顯示 POINT_COLOR=BLUE;//設置字體為藍色 if(mode==0)//RX模式{LCD_ShowString(60,150,200,16,16,"NRF24L01 RX_Mode"); LCD_ShowString(60,170,200,16,16,"Received DATA:"); NRF24L01_RX_Mode(); while(1){ if(NRF24L01_RxPacket(tmp_buf)==0) //一旦接收到信息,則顯示出來.{tmp_buf[32]=0;//加入字符串結束符LCD_ShowString(0,190,239,32,16,tmp_buf); }else delay_us(100); t++;if(t==10000)//大約1s鐘改變一次狀態(tài){t=0;LED0=!LED0;} }; }else//TX模式{ LCD_ShowString(60,150,200,16,16,"NRF24L01 TX_Mode"); NRF24L01_TX_Mode();mode=' ';//從空格鍵開始 while(1){ if(NRF24L01_TxPacket(tmp_buf)==TX_OK){LCD_ShowString(60,170,239,32,16,"Sended DATA:"); LCD_ShowString(0,190,239,32,16,tmp_buf); key=mode;for(t=0;t<32;t++){key++;if(key>('~'))key=' ';tmp_buf[t]=key; }mode++; if(mode>'~')mode=' '; tmp_buf[32]=0;//加入結束符 }else{ LCD_ShowString(60,170,239,32,16,"Send Failed "); LCD_Fill(0,188,240,218,WHITE);//清空上面的顯示 };LED0=!LED0;delay_ms(1500); };} }24l01.c
#include "24l01.h" #include "delay.h" #include "spi.h"const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發(fā)送地址 const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發(fā)送地址//初始化24L01的IO口void NRF24L01_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC,GPIO_Pin_4);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉輸入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);SPI1_Init(); //初始化SPISPI_Cmd(SPI1, DISABLE); // SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //設置SPI單向或者雙向的數(shù)據(jù)模式:SPI設置為雙線雙向全雙工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //設置SPI工作模式:設置為主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //設置SPI的數(shù)據(jù)大小:SPI發(fā)送接收8位幀結構SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //選擇了串行時鐘的穩(wěn)態(tài):時鐘懸空低電平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //數(shù)據(jù)捕獲于第一個時鐘沿SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信號由硬件(NSS管腳)還是軟件(使用SSI位)管理:內(nèi)部NSS信號有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定義波特率預分頻的值:波特率預分頻值為256SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定數(shù)據(jù)傳輸從MSB位還是LSB位開始:數(shù)據(jù)傳輸從MSB位開始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值計算的多項式SPI_Init(SPI1, &SPI_InitStructure); //根據(jù)SPI_InitStruct中指定的參數(shù)初始化外設SPIx寄存器NRF24L01_CE=0; //使能24L01NRF24L01_CSN=1; //SPI片選取消 } //檢測24L01是否存在 //返回值:0,成功;1,失敗 u8 NRF24L01_Check(void) {u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};u8 i;SPI1_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//寫入5個字節(jié)的地址. 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=0; //使能SPI傳輸status =SPI1_ReadWriteByte(reg);//發(fā)送寄存器號 SPI1_ReadWriteByte(value); //寫入寄存器的值NRF24L01_CSN=1; //禁止SPI傳輸 return(status); //返回狀態(tài)值 } //讀取SPI寄存器值 //reg:要讀的寄存器 u8 NRF24L01_Read_Reg(u8 reg) {u8 reg_val; NRF24L01_CSN = 0; //使能SPI傳輸 SPI1_ReadWriteByte(reg); //發(fā)送寄存器號reg_val=SPI1_ReadWriteByte(0XFF);//讀取寄存器內(nèi)容NRF24L01_CSN = 1; //禁止SPI傳輸 return(reg_val); //返回狀態(tài)值 } //在指定位置讀出指定長度的數(shù)據(jù) //reg:寄存器(位置) //*pBuf:數(shù)據(jù)指針 //len:數(shù)據(jù)長度 //返回值,此次讀到的狀態(tài)寄存器值 u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len) {u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI傳輸status=SPI1_ReadWriteByte(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值 for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI1_ReadWriteByte(0XFF);//讀出數(shù)據(jù)NRF24L01_CSN=1; //關閉SPI傳輸return status; //返回讀到的狀態(tài)值 } //在指定位置寫指定長度的數(shù)據(jù) //reg:寄存器(位置) //*pBuf:數(shù)據(jù)指針 //len:數(shù)據(jù)長度 //返回值,此次讀到的狀態(tài)寄存器值 u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len) {u8 status,u8_ctr; NRF24L01_CSN = 0; //使能SPI傳輸status = SPI1_ReadWriteByte(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI1_ReadWriteByte(*pBuf++); //寫入數(shù)據(jù) NRF24L01_CSN = 1; //關閉SPI傳輸return status; //返回讀到的狀態(tài)值 } //啟動NRF24L01發(fā)送一次數(shù)據(jù) //txbuf:待發(fā)送數(shù)據(jù)首地址 //返回值:發(fā)送完成狀況 u8 NRF24L01_TxPacket(u8 *txbuf) {u8 sta;SPI1_SetSpeed(SPI_BaudRatePrescaler_8);//spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) NRF24L01_CE=0;NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數(shù)據(jù)到TX BUF 32個字節(jié)NRF24L01_CE=1;//啟動發(fā)送 while(NRF24L01_IRQ!=0);//等待發(fā)送完成sta=NRF24L01_Read_Reg(STATUS); //讀取狀態(tài)寄存器的值 NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&MAX_TX)//達到最大重發(fā)次數(shù){NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_TX; }if(sta&TX_OK)//發(fā)送完成{return TX_OK;}return 0xff;//其他原因發(fā)送失敗 } //啟動NRF24L01發(fā)送一次數(shù)據(jù) //txbuf:待發(fā)送數(shù)據(jù)首地址 //返回值:0,接收完成;其他,錯誤代碼 u8 NRF24L01_RxPacket(u8 *rxbuf) {u8 sta; SPI1_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) sta=NRF24L01_Read_Reg(STATUS); //讀取狀態(tài)寄存器的值 NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&RX_OK)//接收到數(shù)據(jù){NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數(shù)據(jù)NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器 return 0; } return 1;//沒收到任何數(shù)據(jù) } //該函數(shù)初始化NRF24L01到RX模式 //設置RX地址,寫RX數(shù)據(jù)寬度,選擇RF頻道,波特率和LNA HCURR //當CE變高后,即進入RX模式,并可以接收數(shù)據(jù)了 void NRF24L01_RX_Mode(void) {NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//寫RX節(jié)點地址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的有效數(shù)據(jù)寬度 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //設置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開啟 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f); //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式 NRF24L01_CE = 1; //CE為高,進入接收模式 } //該函數(shù)初始化NRF24L01到TX模式 //設置TX地址,寫TX數(shù)據(jù)寬度,設置RX自動應答的地址,填充TX發(fā)送數(shù)據(jù),選擇RF頻道,波特率和LNA HCURR //PWR_UP,CRC使能 //當CE變高后,即進入RX模式,并可以接收數(shù)據(jù)了 //CE為高大于10us,則啟動發(fā)送. void NRF24L01_TX_Mode(void) { NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節(jié)點地址 NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節(jié)點地址,主要為了使能ACK 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+SETUP_RETR,0x1a);//設置自動重發(fā)間隔時間:500us + 86us;最大自動重發(fā)次數(shù):10次NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //設置RF通道為40NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //設置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開啟 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷NRF24L01_CE=1;//CE為高,10us后啟動發(fā)送 }24l01.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有效數(shù)據(jù),1~32字節(jié) #define WR_TX_PLOAD 0xA0 //寫TX有效數(shù)據(jù),1~32字節(jié) #define FLUSH_TX 0xE1 //清除TX FIFO寄存器.發(fā)射模式下用 #define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用 #define REUSE_TX_PL 0xE3 //重新使用上一包數(shù)據(jù),CE為高,數(shù)據(jù)包被不斷發(fā)送. #define NOP 0xFF //空操作,可以用來讀狀態(tài)寄存器 //SPI(NRF24L01)寄存器地址 #define CONFIG 0x00 //配置寄存器地址;bit0:1接收模式,0發(fā)射模式;bit1:電選擇;bit2:CRC模式;bit3:CRC使能;//bit4:中斷MAX_RT(達到最大重發(fā)次數(shù)中斷)使能;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 //設置地址寬度(所有數(shù)據(jù)通道):bit1,0:00,3字節(jié);01,4字節(jié);02,5字節(jié); #define SETUP_RETR 0x04 //建立自動重發(fā);bit3:0,自動重發(fā)計數(shù)器;bit7:4,自動重發(fā)延時 250*x+86us #define RF_CH 0x05 //RF通道,bit6:0,工作通道頻率; #define RF_SETUP 0x06 //RF寄存器;bit3:傳輸速率(0:1Mbps,1:2Mbps);bit2:1,發(fā)射功率;bit0:低噪聲放大器增益 #define STATUS 0x07 //狀態(tài)寄存器;bit0:TX FIFO滿標志;bit3:1,接收數(shù)據(jù)通道號(最大:6);bit4,達到最多次重發(fā)//bit5:數(shù)據(jù)發(fā)送完成中斷;bit6:接收數(shù)據(jù)中斷; #define MAX_TX 0x10 //達到最大發(fā)送次數(shù)中斷 #define TX_OK 0x20 //TX發(fā)送完成中斷 #define RX_OK 0x40 //接收到數(shù)據(jù)中斷#define OBSERVE_TX 0x08 //發(fā)送檢測寄存器,bit7:4,數(shù)據(jù)包丟失計數(shù)器;bit3:0,重發(fā)計數(shù)器 #define CD 0x09 //載波檢測寄存器,bit0,載波檢測; #define RX_ADDR_P0 0x0A //數(shù)據(jù)通道0接收地址,最大長度5個字節(jié),低字節(jié)在前 #define RX_ADDR_P1 0x0B //數(shù)據(jù)通道1接收地址,最大長度5個字節(jié),低字節(jié)在前 #define RX_ADDR_P2 0x0C //數(shù)據(jù)通道2接收地址,最低字節(jié)可設置,高字節(jié),必須同RX_ADDR_P1[39:8]相等; #define RX_ADDR_P3 0x0D //數(shù)據(jù)通道3接收地址,最低字節(jié)可設置,高字節(jié),必須同RX_ADDR_P1[39:8]相等; #define RX_ADDR_P4 0x0E //數(shù)據(jù)通道4接收地址,最低字節(jié)可設置,高字節(jié),必須同RX_ADDR_P1[39:8]相等; #define RX_ADDR_P5 0x0F //數(shù)據(jù)通道5接收地址,最低字節(jié)可設置,高字節(jié),必須同RX_ADDR_P1[39:8]相等; #define TX_ADDR 0x10 //發(fā)送地址(低字節(jié)在前),ShockBurstTM模式下,RX_ADDR_P0與此地址相等 #define RX_PW_P0 0x11 //接收數(shù)據(jù)通道0有效數(shù)據(jù)寬度(1~32字節(jié)),設置為0則非法 #define RX_PW_P1 0x12 //接收數(shù)據(jù)通道1有效數(shù)據(jù)寬度(1~32字節(jié)),設置為0則非法 #define RX_PW_P2 0x13 //接收數(shù)據(jù)通道2有效數(shù)據(jù)寬度(1~32字節(jié)),設置為0則非法 #define RX_PW_P3 0x14 //接收數(shù)據(jù)通道3有效數(shù)據(jù)寬度(1~32字節(jié)),設置為0則非法 #define RX_PW_P4 0x15 //接收數(shù)據(jù)通道4有效數(shù)據(jù)寬度(1~32字節(jié)),設置為0則非法 #define RX_PW_P5 0x16 //接收數(shù)據(jù)通道5有效數(shù)據(jù)寬度(1~32字節(jié)),設置為0則非法 #define NRF_FIFO_STATUS 0x17 //FIFO狀態(tài)寄存器;bit0,RX FIFO寄存器空標志;bit1,RX FIFO滿標志;bit2,3,保留//bit4,TX FIFO空標志;bit5,TX FIFO滿標志;bit6,1,循環(huán)發(fā)送上一數(shù)據(jù)包.0,不循環(huán); // //24L01操作線 #define NRF24L01_CE PAout(4) //24L01片選信號 #define NRF24L01_CSN PCout(4) //SPI片選信號 #define NRF24L01_IRQ PAin(1) //IRQ主機數(shù)據(jù)輸入 //24L01發(fā)送接收數(shù)據(jù)寬度定義 #define TX_ADR_WIDTH 5 //5字節(jié)的地址寬度 #define RX_ADR_WIDTH 5 //5字節(jié)的地址寬度 #define TX_PLOAD_WIDTH 32 //32字節(jié)的用戶數(shù)據(jù)寬度 #define RX_PLOAD_WIDTH 32 //32字節(jié)的用戶數(shù)據(jù)寬度void NRF24L01_Init(void);//初始化 void NRF24L01_RX_Mode(void);//配置為接收模式 void NRF24L01_TX_Mode(void);//配置為發(fā)送模式 u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//寫數(shù)據(jù)區(qū) u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//讀數(shù)據(jù)區(qū) u8 NRF24L01_Read_Reg(u8 reg); //讀寄存器 u8 NRF24L01_Write_Reg(u8 reg, u8 value);//寫寄存器 u8 NRF24L01_Check(void);//檢查24L01是否存在 u8 NRF24L01_TxPacket(u8 *txbuf);//發(fā)送一個包的數(shù)據(jù) u8 NRF24L01_RxPacket(u8 *rxbuf);//接收一個包的數(shù)據(jù) #endif總結
以上是生活随笔為你收集整理的【STM32】无线通信实验代码详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【STM32】SPI 实验代码详解
- 下一篇: 【STM32】FreeRTOS 移植到