STM32F030C8配置NRF24L01
前言:
工作使用到STM32F030,項(xiàng)目暫告一段落,空閑時(shí)間,調(diào)試一下基本的無(wú)線模塊。其實(shí)還是碰到了一些阻礙。雖然STM32F103會(huì)用了NRF24L10,可是到了STM32F030還是有些配置上的區(qū)別,為了加快各位研發(fā)人員的開(kāi)發(fā)進(jìn)度,避免浪費(fèi)大量的時(shí)間在硬件平臺(tái)上,寫出個(gè)人代碼調(diào)試的經(jīng)驗(yàn)。個(gè)人水平有限,如有錯(cuò)誤,還請(qǐng)指正。
提示:
使用內(nèi)部RC時(shí)鐘,最大速度48MHz。
第一步:初始化端口/******************************************************************************* *@brief 初始化端口 因?yàn)?/font>CSN用的PB12 CE 用的PA11所以兩個(gè)時(shí)鐘都要開(kāi) *@param None *@retval None ****************************************************************Author:Liming**/ void NRF24L01_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB,ENABLE);//使能端口A/B時(shí)鐘
GPIO_InitStructure.GPIO_Pin= SPI2_CE_PIN; GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; GPIO_Init(SPI2_CE_PORT,&GPIO_InitStructure); //CE控制腳
GPIO_InitStructure.GPIO_Pin= SPI2_CSN_PIN; GPIO_Init(SPI2_CSN_PORT,&GPIO_InitStructure); //CSN控制腳 GPIO_ResetBits(SPI2_CE_PORT,SPI2_CE_PIN); GPIO_SetBits(SPI2_CSN_PORT,SPI2_CSN_PIN);
GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN; GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed= GPIO_Speed_Level_2; GPIO_Init(SPI2_SCK_GPIO_PORT,&GPIO_InitStructure); //SPI 引腳
GPIO_InitStructure.GPIO_Pin = SPI2_MISO_PIN; GPIO_Init(SPI2_MISO_GPIO_PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN; GPIO_Init(SPI2_MOSI_GPIO_PORT,&GPIO_InitStructure);
GPIO_PinAFConfig(SPI2_SCK_GPIO_PORT, SPI2_SCK_SOURCE,SPI2_SCK_AF); GPIO_PinAFConfig(SPI2_MISO_GPIO_PORT,SPI2_MISO_SOURCE, SPI2_MISO_AF); GPIO_PinAFConfig(SPI2_MOSI_GPIO_PORT,SPI2_MOSI_SOURCE, SPI2_MOSI_AF); }
第二步:初始化SPI/******************************************************************************* *@brief 初始化SPI 因?yàn)?/font>NRF24L01SPI最大支持10M,所以分頻到6MHz *@param None *@retval None ****************************************************************Author:Liming**/ void SPIx_Init(void) { SPI_InitTypeDefSPI_InitStruture; RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//使能SPI2時(shí)鐘
SPI_InitStruture.SPI_Direction= SPI_Direction_2Lines_FullDuplex;//SPI 設(shè)置為雙線雙向全雙工 SPI_InitStruture.SPI_Mode= SPI_Mode_Master;//設(shè)置為主SPI SPI_InitStruture.SPI_DataSize = SPI_DataSize_8b;//SPI 發(fā)送接收8 位幀結(jié)構(gòu) SPI_InitStruture.SPI_CPOL =SPI_CPOL_Low;//時(shí)鐘懸空低 SPI_InitStruture.SPI_CPHA =SPI_CPHA_1Edge;//數(shù)據(jù)捕獲于第一個(gè)時(shí)鐘沿 SPI_InitStruture.SPI_BaudRatePrescaler= SPI_BaudRatePrescaler_8;//波特率預(yù)分頻值為8 48/8=6MHz SPI_InitStruture.SPI_NSS= SPI_NSS_Soft;//內(nèi)部 NSS 信號(hào)有SSI 位控制 SPI_InitStruture.SPI_FirstBit= SPI_FirstBit_MSB; //數(shù)據(jù)傳輸從 MSB 位開(kāi)始 SPI_InitStruture.SPI_CRCPolynomial= 7; //CRC校驗(yàn)計(jì)算式 SPI_Init(SPI2,&SPI_InitStruture); //應(yīng)用到SPI1 SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);// 很重要的一句代碼 SPI_Cmd(SPI2,ENABLE); }
第三步:基礎(chǔ)支持程序代碼/******************************************************************************* *@brief SPIx 讀寫一個(gè)字節(jié) 這一步我使用F103的都不行 *@param TxData:要寫入的字節(jié) *@retval tmp:讀取到的字節(jié) ****************************************************************Author:Liming**/ uint8_t SPIx_ReadWriteByte(uint8_t TxData) { uint8_t tmp = 0x00;
/*Wait until the transmit buffer is empty */ while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) != SET) { } /*Send the byte */ SPI_SendData8(SPI2, TxData);
/*Wait to receive a byte */ while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != SET) { } /*Return the byte read from the SPI bus */ tmp= SPI_ReceiveData8(SPI2);
/*Wait until the BSY flag is set */ while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET) { }
/*Return read Data */ return tmp; }
/******************************************************************************* *@brief 寫寄存器 *@param None *@retval None ****************************************************************Author:Liming**/ u8 NRF24L01_Write_Reg(u8 reg,u8 value) { u8status; SPI_CSN_LOW; //使能SPI傳輸 status =SPIx_ReadWriteByte(reg);//發(fā)送寄存器號(hào) SPIx_ReadWriteByte(value); //寫入寄存器的值 SPI_CSN_HIGH; //禁止SPI傳輸 return(status); //返回狀態(tài)值 }
/******************************************************************************* *@brief 讀寄存器 *@param None *@retval None ****************************************************************Author:Liming**/ u8 NRF24L01_Read_Reg(u8 reg) { u8reg_val; SPI_CSN_LOW; //使能SPI傳輸 SPIx_ReadWriteByte(reg); //發(fā)送寄存器號(hào) reg_val=SPIx_ReadWriteByte(0XFF);//讀取寄存器內(nèi)容 SPI_CSN_HIGH; //禁止SPI傳輸 return(reg_val); //返回狀態(tài)值 }
/******************************************************************************* *@brief 讀多字節(jié)數(shù)據(jù) *@param None *@retval None ****************************************************************Author:Liming**/ unsigned char NRF24L01_Read_Buf(unsigned charreg,unsigned char *pBuf,unsigned char len) { unsignedchar status,u8_ctr; SPI_CSN_LOW; //使能SPI傳輸 status=SPIx_ReadWriteByte(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值 for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_ReadWriteByte(0XFF);//讀出數(shù)據(jù) SPI_CSN_HIGH; //關(guān)閉SPI傳輸 return status; //返回讀到的狀態(tài)值 } /******************************************************************************* *@brief 寫多字節(jié)數(shù)據(jù) *@param None *@retval None ****************************************************************Author:Liming**/ unsigned char NRF24L01_Write_Buf(unsignedchar reg, unsigned char *pBuf, unsigned char len) { unsignedchar status,u8_ctr; SPI_CSN_LOW; //使能SPI傳輸 status = SPIx_ReadWriteByte(reg);//發(fā)送寄存器值(位置),并讀取狀態(tài)值 for(u8_ctr=0; u8_ctr<len;u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //寫入數(shù)據(jù) SPI_CSN_HIGH; //關(guān)閉SPI傳輸 return status; //返回讀到的狀態(tài)值 }
/******************************************************************************* *@brief 發(fā)送一包數(shù)據(jù) *@param None *@retval None ****************************************************************Author:Liming**/ void NRF24L01_TxPacket(unsigned char*txbuf) { unsignedchar sta; SPI_CE_LOW; NRF24L01_Write_Reg(FLUSH_TX,0X00); // 清理發(fā)送寄存器 NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數(shù)據(jù)到TXBUF 32個(gè)字節(jié) NRF24L01_Write_Reg(SPI_WRITE_REG + CONFIG, 0x0E); // 清理發(fā)送寄存器 NRF_STATUS = NRF_STATUS_TX; SPI_CE_HIGH; //啟動(dòng)發(fā)送 }
/******************************************************************************* *@brief 接收一包數(shù)據(jù) *@param None *@retval None ****************************************************************Author:Liming**/ unsigned char NRF24L01_RxPacket(u8 *rxbuf) { unsignedchar sta;
sta=NRF24L01_Read_Reg(STATUS); //讀取狀態(tài)寄存器的值 NRF24L01_Write_Reg(SPI_WRITE_REG+STATUS,sta);//清除TX_DS或MAX_RT中斷標(biāo)志 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寄存器 return1; } return0;//沒(méi)收到任何數(shù)據(jù) }
/******************************************************************************* *@brief 檢測(cè)NRF24L01是否存在 進(jìn)入調(diào)試模式查看是否值正確 *@param None *@retval 1失敗 0成功 ****************************************************************Author:Liming**/ uint8_t NRF24L01_Check(void) { uint8_tbuf[5]={0XA5,0XA5,0XA5,0XA5,0XA5}; uint8_tbuf1[5]={0,0,0,0,0}; uint8_ti,Temp; NRF24L01_Write_Buf(SPI_WRITE_REG+TX_ADDR,buf,5);//寫入5個(gè)字節(jié)的地址. NRF24L01_Read_Buf(TX_ADDR,buf1,5); //讀出寫入的地址 for(i=0;i<5;i++) //調(diào)試斷點(diǎn)打到這一行,查看buf1是否都是0XA5 { if( buf1 != 0XA5 )break; } if(i! = 5 )return 1;//檢測(cè)24L01錯(cuò)誤 return0; //檢測(cè)到24L01 }
/******************************************************************************* *@brief 切換NRF24L01到接收模式 需要設(shè)置發(fā)送地址, * 有些人自己調(diào)程序,老是說(shuō)會(huì)斷,或者模式切換出問(wèn)題,或許參考一下紅色部分的思路。 *@param None *@retval None ****************************************************************Author:Liming**/
void RX_Mode(void) { unsigned char status; SPI_CE_LOW; //CE拉低,進(jìn)入配置模式 status = NRF24L01_Read_Reg(STATUS); NRF24L01_Write_Reg(SPI_WRITE_REG+STATUS,status);//清除中斷 NRF24L01_Write_Reg(SPI_WRITE_REG+SETUP_AW,0x01);//3字節(jié)地址 NRF24L01_Write_Reg(FLUSH_RX,0x00);//清除RX FIFO寄存器
/* 設(shè)置通道0接收地址*/ NRF24L01_Write_Buf(SPI_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDR_PIPE0,RX_ADR_WIDTH); /* 設(shè)置通道1接收地址*/ NRF24L01_Write_Buf(SPI_WRITE_REG+RX_ADDR_P1,(u8*)RX_ADDR_PIPE1,RX_ADR_WIDTH); NRF24L01_Write_Reg(SPI_WRITE_REG+RX_ADDR_P2, RX_ADDR_PIPE2);// 設(shè)置通道2接收地址 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_ADDR_P3, RX_ADDR_PIPE3);// 設(shè)置通道3接收地址 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_ADDR_P4, RX_ADDR_PIPE4);// 設(shè)置通道4接收地址 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_ADDR_P5, RX_ADDR_PIPE5);// 設(shè)置通道5接收地址
NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數(shù)據(jù)寬度 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P1,RX_PLOAD_WIDTH);//選擇通道1的有效數(shù)據(jù)寬度 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P2,RX_PLOAD_WIDTH);//選擇通道2的有效數(shù)據(jù)寬度 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P3,RX_PLOAD_WIDTH);//選擇通道3的有效數(shù)據(jù)寬度 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P4,RX_PLOAD_WIDTH);//選擇通道4的有效數(shù)據(jù)寬度 NRF24L01_Write_Reg(SPI_WRITE_REG+RX_PW_P5,RX_PLOAD_WIDTH);//選擇通道5的有效數(shù)據(jù)寬度
NRF24L01_Write_Reg(SPI_WRITE_REG+EN_AA,0x3F); //使能所有通道的自動(dòng)應(yīng)答 NRF24L01_Write_Reg(SPI_WRITE_REG+EN_RXADDR,0x3F);//使能所有通道的接收地址 NRF24L01_Write_Reg(SPI_WRITE_REG+RF_CH,0X00); //設(shè)置RF通信頻率 /*設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開(kāi)啟 */ NRF24L01_Write_Reg(SPI_WRITE_REG+RF_SETUP,0x0F); /*配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式*/ NRF24L01_Write_Reg(SPI_WRITE_REG+CONFIG,0x3F); NRF_STATUS = NRF_STATUS_RX; SPI_CE_HIGH; //CE拉高,進(jìn)入接收模式 }
/******************************************************************************* *@brief 切換NRF24L01到發(fā)送模式 需要設(shè)置發(fā)送地址, * 如果使能了自動(dòng)應(yīng)答還需要寫通道0的接收地址和發(fā)送地址相同。 * 有些人自己調(diào)程序,老是說(shuō)會(huì)斷,或者模式切換出問(wèn)題,或許參考一下紅色部分的思路。 *@param None *@retval None ****************************************************************Author:Liming**/ void TX_Mode(void) { unsigned char status; SPI_CE_LOW; status = NRF24L01_Read_Reg(STATUS); NRF24L01_Write_Reg(SPI_WRITE_REG+STATUS,status);//清除RX FIFO寄存器 NRF24L01_Write_Reg(SPI_WRITE_REG+SETUP_AW,0x01);//3字節(jié)地址 NRF24L01_Write_Reg(FLUSH_TX,0x00);//清除TX FIFO寄存器
/*寫TX節(jié)點(diǎn)地址*/ NRF24L01_Write_Buf(SPI_WRITE_REG+TX_ADDR,(u8*)TX_ADDR_PIPE0,TX_ADR_WIDTH); /*設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK*/ NRF24L01_Write_Buf(SPI_WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDR_PIPE0,TX_ADR_WIDTH); NRF24L01_Write_Reg(SPI_WRITE_REG+EN_AA,0x01); //使能通道0的自動(dòng)應(yīng)答 NRF24L01_Write_Reg(SPI_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址 /*設(shè)置自動(dòng)重發(fā)間隔時(shí)間:500us+ 86us;最大自動(dòng)重發(fā)次數(shù):5次*/ NRF24L01_Write_Reg(SPI_WRITE_REG+SETUP_RETR,0x15); NRF24L01_Write_Reg(SPI_WRITE_REG+RF_CH,0X00); //設(shè)置RF通道為40 /*設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開(kāi)啟 */ NRF24L01_Write_Reg(SPI_WRITE_REG+RF_SETUP,0x0F); /*配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式,開(kāi)啟所有中斷*/ NRF24L01_Write_Reg(SPI_WRITE_REG+CONFIG,0x0E); NRF_STATUS = NRF_STATUS_TX; SPI_CE_HIGH;//CE為高,10us后啟動(dòng)發(fā)送 }
到這里基本已經(jīng)可以讀寫寄存器了,也就是NRF24L01已經(jīng)調(diào)通了基本的發(fā)送和接受。遇到的問(wèn)題或許還有中斷引腳的配置,畢竟STM32F0還是和STM32F1不一樣。另外一篇詳細(xì)講外部中斷的配置。
全部資料51hei下載地址:
STM32F030C8配置NRF24L01.pdf
(508.95 KB, 下載次數(shù): 51)
2018-3-19 16:54 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|