忙活了好几天终于将STM32F746模拟SPI驱动NRF24L01进行数据交流的驱动写好了 ,不过有待调整,,先奉上以供大家参考!!!!!!
- /*****SPI驱动函数*******************/
- #include "stm32f7xx_hal_conf.h"
- SPI_HandleTypeDef hspi2;
- uint8_t status;
- //uint8_t txbuf[4]={0,1,2,3}; //发送缓冲
- uint8_t rxbuf[4]; //接收缓冲
- int i=0;
- uint8_t RX_BUF[RX_PLOAD_WIDTH]; //接收数据缓存
- uint8_t TX_BUF[TX_PLOAD_WIDTH]; //发射数据缓存
- uint8_t TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址
- uint8_t RX_ADDRESS[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};
- uint8_t aTxBuffer[] = "****SPI - Two Boards communication based on Polling **** SPI Message ******** SPI Message ******** SPI Message ****";
- uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
- {
- while (BufferLength--)
- {
- if((*pBuffer1) != *pBuffer2)
- {
- return BufferLength;
- }
- pBuffer1++;
- pBuffer2++;
- }
- return 0;
- }
- /* Buffer used for reception */
- uint8_t aRxBuffer[BUFFERSIZE];
- void Error_Handler(void);
- void spi_config(void)
- {
-
-
- GPIO_InitTypeDef GPIO_InitStruct;
-
- /*##-1- Enable peripherals and GPIO Clocks #################################*/
- /* Enable GPIO TX/RX clock */
- __GPIOI_CLK_ENABLE();
- __GPIOB_CLK_ENABLE();
- __GPIOH_CLK_ENABLE();
- __GPIOA_CLK_ENABLE();
- /* Enable SPI clock */
- SPIx_CLK_ENABLE();
- /*Configure GPIO pin : PF10 */
- GPIO_InitStruct.Pin = GPIO_PIN_8;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /*Configure GPIO pins : PF9 PF8 */
- GPIO_InitStruct.Pin = GPIO_PIN_3;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
- HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
-
- GPIO_InitStruct.Pin = GPIO_PIN_6;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
- HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
-
-
- /**SPI2 GPIO Configuration
- PI1 ------> SPI2_SCK
- PB14 ------> SPI2_MISO
- PB15 ------> SPI2_MOSI
- */
- GPIO_InitStruct.Pin = GPIO_PIN_1;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
- HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
- GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- hspi2.Instance = SPI2;
- hspi2.Init.Mode = SPI_MODE_MASTER;
- hspi2.Init.Direction = SPI_DIRECTION_2LINES;
- hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
- hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
- hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
- hspi2.Init.NSS = SPI_NSS_SOFT;
- hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
- hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
- hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
- hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
- hspi2.Init.CRCPolynomial = 7;
- hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
- hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
- HAL_SPI_Init(&hspi2);
-
- }
- uint8_t SPI_ExchangeByte(uint8_t input)
- {
- uint8_t output;
- while(HAL_SPI_TransmitReceive(&hspi2,&input,&output,1,1000)!=HAL_OK);
- return output;
- }
- void cmd(uint8_t *cmd,uint8_t *cmdsize)
- {
- while( cmdsize -- )
- {
- SPI_ExchangeByte( *cmd++ );
- }
- }
- uint8_t SPI_NRF_WriteBuf(uint8_t reg ,uint8_t *pBuf,uint8_t bytes)
- {
- uint8_t status;
- NRF_CE_LOW();
- /*置低CSN,使能SPI传输*/
- NRF_CSN_LOW();
- /*发送寄存器号*/
- status = SPI_ExchangeByte( reg );
-
- /*向缓冲区写入数据*/
- while( bytes -- )
- {
- SPI_ExchangeByte( *pBuf++ );
- }
-
- /*CSN拉高,完成*/
- NRF_CSN_HIGH();
-
- return (status); //返回NRF24L01的状态
- }
- uint8_t SPI_NRF_ReadBuf(uint8_t reg, uint8_t *buffer, uint8_t size )
- {
- uint8_t status;
- NRF_CE_LOW();
- /*置低CSN,使能SPI传输*/
- NRF_CSN_LOW();
- status =SPI_ExchangeByte( reg );
- while( size -- )
- {
- *buffer++ = SPI_ExchangeByte( 0xFF );
- }
-
- NRF_CSN_HIGH();
- return (status); //返回NRF24L01的状态
- }
- uint8_t check2401(void)
- {
- uint8_t buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
- uint8_t buf1[5];
- uint8_t i;
- /*写入5个字节的地址. */
- SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,buf,5);
- /*读出写入的地址 */
- SPI_NRF_ReadBuf(TX_ADDR,buf1,5);
- /*比较*/
- for(i=0;i<5;i++)
- {
- if(buf1[i]!=0xC2)
- break;
- }
-
- if(i==5)
- {
- printf("初始化NRF24L01成功...\r\n");
-
- return SUCCESS ;
- }
- //MCU与NRF成功连接
- else
- {
-
- printf("初始化NRF24L01失败...\r\n");
- return ERROR ;
- }
- //MCU与NRF不正常连接
- }
- /**
- * [url=home.php?mod=space&uid=159083]@brief[/url] 用于向NRF特定的寄存器写入数据
- * @param
- * @arg reg:NRF的命令+寄存器地址
- * @arg dat:将要向寄存器写入的数据
- * @retval NRF的status寄存器的状态
- */
- uint8_t SPI_NRF_WriteReg(uint8_t reg,uint8_t dat)
- {
- uint8_t status;
- NRF_CE_LOW();
- /*置低CSN,使能SPI传输*/
- NRF_CSN_LOW();
-
- /*发送命令及寄存器号 */
- status = SPI_ExchangeByte( reg );
-
- /*向寄存器写入数据*/
- SPI_ExchangeByte(dat);
-
- /*CSN拉高,完成*/
- NRF_CSN_HIGH();
-
- /*返回状态寄存器的值*/
- return(status);
- }
- /**
- * @brief 用于从NRF特定的寄存器读出数据
- * @param
- * @arg reg:NRF的命令+寄存器地址
- * @retval 寄存器中的数据
- */
- uint8_t SPI_NRF_ReadReg(uint8_t reg)
- {
- uint8_t reg_val;
- NRF_CE_LOW();
- /*置低CSN,使能SPI传输*/
- NRF_CSN_LOW();
-
- /*发送寄存器号*/
- SPI_ExchangeByte(reg);
- /*读取寄存器的值 */
- reg_val = SPI_ExchangeByte(NOP);
-
- /*CSN拉高,完成*/
- NRF_CSN_HIGH();
-
- return reg_val;
- }
- void NRF_RX_Mode(void)
- {
- NRF_CE_LOW();
- SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
- SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
- SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
- SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //设置RF通信频率
- SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
- SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
- SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
- /*CE拉高,进入接收模式*/
- NRF_CE_HIGH();
- }
- /**
- * @brief 配置发送模式
- * @param 无
- * @retval 无
- */
- void NRF_TX_Mode(void)
- {
- NRF_CE_LOW();
- SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址
- SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
- SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
- SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
- SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
- SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //设置RF通道为CHANAL
- SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
-
- SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断
- /*CE拉高,进入发送模式*/
- NRF_CE_HIGH();
- HAL_Delay(5);//CE要拉高一段时间才进入发送模式
-
- }
- /**
- * @brief 用于向NRF的发送缓冲区中写入数据
- * @param
- * @arg txBuf:存储了将要发送的数据的数组,外部定义
- * @retval 发送结果,成功返回TXDS,失败返回MAXRT或ERROR
- */
- uint8_t NRF_Tx_Dat(uint8_t *txbuf)
- {
- uint8_t state;
- /*ce为低,进入待机模式1*/
- NRF_CE_LOW();
- /*写数据到TX BUF 最大 32个字节*/
- SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
- /*CE为高,txbuf非空,发送数据包 */
- NRF_CE_HIGH();
-
- /*等待发送完成中断 */
- while(NRF_Read_IRQ()!=0);
-
- /*读取状态寄存器的值 */
- state = SPI_NRF_ReadReg(STATUS);
- /*清除TX_DS或MAX_RT中断标志*/
- SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);
- SPI_NRF_WriteReg(FLUSH_TX,NOP); //清除TX FIFO寄存器
- /*判断中断类型*/
- if(state&MAX_RT) //达到最大重发次数
- return MAX_RT;
- else if(state&TX_DS) //发送完成
- return TX_DS;
- else
- return ERROR; //其他原因发送失败
- }
- /**
- * @brief 用于从NRF的接收缓冲区中读出数据
- * @param
- * @arg rxBuf :用于接收该数据的数组,外部定义
- * @retval
- * @arg 接收结果
- */
- uint8_t NRF_Rx_Dat(uint8_t *rxbuf)
- {
- uint8_t state;
- NRF_CE_HIGH(); //进入接收状态
- /*等待接收中断*/
- while(NRF_Read_IRQ()!=0);
-
- NRF_CE_LOW(); //进入待机状态
- /*读取status寄存器的值 */
- state=SPI_NRF_ReadReg(STATUS);
-
- /* 清除中断标志*/
- SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);
- /*判断是否接收到数据*/
- if(state&RX_DR) //接收到数据
- {
- SPI_NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
- SPI_NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO寄存器
- return RX_DR;
- }
- else
- return ERROR; //没收到任何数据
- }
- void nrf_check(void)
- {
- status = check2401();
- if(status == SUCCESS)
- printf("\r\n NRF与MCU连接成功!\r\n");
- else
- printf("\r\n NRF与MCU连接失败,请重新检查接线。\r\n");
- }
- void nrf_send(uint8_t *txbuf)
- {
- printf("\r\n 主机端 进入自应答发送模式\r\n");
- HAL_Delay(10);//CE要拉高一段时间才进入发送模式
- NRF_TX_Mode();
-
- /*开始发送数据*/
- status = NRF_Tx_Dat(txbuf);
- printf("\r\n 电子协会\r\n");
- /*判断发送状态*/
- switch(status)
- {
- case MAX_RT:
- printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
- break;
-
- case ERROR:
- printf("\r\n 未知原因导致发送失败。 \r\n");
- break;
-
- case TX_DS:
- printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! \r\n");
- break;
- }
-
- // printf("\r\n 主机端 进入接收模式。 \r\n");
- // NRF_RX_Mode();
- //
- // /*等待接收数据*/
- // status = NRF_Rx_Dat(rxbuf);
- //
- // /*判断接收状态*/
- // switch(status)
- // {
- // case RX_DR:
- // for(i=0;i<4;i++)
- // {
- // printf("\r\n 主机端 接收到 从机端 发送的数据为:%d \r\n",rxbuf[i]);
- // txbuf[i] =rxbuf[i];
- // }
- // break;
- //
- // case ERROR:
- // printf("\r\n 主机端 接收出错。 \r\n");
- // break;
- // }
- }
- /*************************/