u8 sta; //define a bit-addressable variable sta
uc8 TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};
char RX_BUF[256];
uchar TX_BUF[256];
/****************************************************** */
void RF_SPI_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph _GPIOD,ENABLE)
;
/* PB15-MOSI2,PB13-SCK2*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure .GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_0);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure interrupt line 0 as falling trigger*/
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger
= EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_ LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_2);//Preset to high
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO _InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_4); //Preset to high
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GP IO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12); //Preset to high
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_ InitStructure);
SPI_Cmd(SPI2, DISABLE); //Must disable before changing MODE
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //Two-line full-duplex
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //Master
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8-bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //CPOL=0 clock floating low
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //CPHA=0 data capture first
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //Software NSS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //64-divide
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //High bit first
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC7
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
But remember not to ignore the hardware reception of SPI, because reading SPI_DR can clear RXEN
**************************************************************/
u8 SPI_RW(u8 byte)
{
/*Wait for the transmit register to be empty*/
while((SPI2->SR & SPI_I2S_FLAG_TXE)==RESET);
/*Send a byte*/
SPI2->DR = byte;
/*Wait for the receive register to be valid*/
while((SPI2->SR & SPI_I2S_FLAG_RXNE)==RESET);
return(SPI2->DR);
}
/******************************************************
Function: SPI_RW_Reg()
Description: Write data value to reg register
******************************************************/
u8 SPI_RW_Reg(u8 reg, u8 value)
{
u8 status;
CSN_L; // CSN is set low and data transmission starts
status = SPI_RW(reg); // Select register and return status word
SPI_RW(value); // Then write data to the register CSN_H
; // Pull CSN high to end data transmission
return(status); // Return to status register
}
/******************************************************
Function: init_io()
Description: Initialize IO
*****************************************************/
void RX_Mode(void);
void init_io(void)
{
CE_L; // Standby
CSN_H; // SPI disables
LED1; // Turn off indicator light
RX_Mode(); // Receive
}
Function: SPI_Read()
Description: Read one byte from register reg
************************************************/
u8 SPI_Read(u8 reg)
{
u8 reg_val;
CSN_L; // Set CSN low to start data transmission
SPI_RW(reg); // Select register
reg_val = SPI_RW(0); // Then read data from this register
CSN_H; // Pull CSN high to end data transmission
return(reg_val); // Return register data
}
Function: SPI_Read_Buf()
Description: Read bytes from register reg, usually used to read receive channel
data or receive/send address
************************************************/
uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes)
{
uchar status, i;
CSN_L; // Set CSN low to start data transmission
status = SPI_RW(reg); // Select register and return status word
for(i=0; i
; // Pull CSN high to end data transmission
return(status); // Return status register
}
Function: SPI_Write_Buf()
Description: Write the data in the pBuf buffer to the nRF24L01, usually used to write the
transmit channel data or receive/send address
************************************************/
uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
{
uchar status, i;
CSN_L; // Set CSN low to start transmitting data
status = SPI_RW(reg); // Select the register and return the status word
for(i=0; i
CSN_H; // Pull CSN high to end data transmission
return(status); // Return to status register
}
Function: RX_Mode()
Description: This function sets the nRF24L01 to receive mode and waits for the data packet received from the transmitting device
****************************************************/
void RX_Mode(void)
{
CE_L;
SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // The receiving device receives channel 0 using the same transmit address as the transmitting device
SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // Enable automatic response of receiving channel 0
SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // Enable receiving channel 0
SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // Select RF channel 0x40
SPI_RW_Reg(RF_WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Receive channel 0 selects the same effective data width as the transmit channel
SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // Data transmission rate 1Mbps, transmit power 0dBm, low noise amplifier gain
SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0f); // CRC enable, 16-bit CRC check, power on, receive mode
CE_H; // Pull CE high to start the receiving device
}
Function: TX_Mode()
Description:
This function sets nRF24L01 to transmit mode (CE=1 for at least 10us),
starts transmitting after 130us, and after data transmission is completed, the transmitting module automatically switches to receive
mode and waits for the response signal.
*************************************************/
void TX_Mode(uchar * BUF)
{
CE_L;
SPI_Write_Buf(RF_WRITE_REG + TX_ADDR, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // Write transmit address
SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // In order to respond to the receiving device, the receive channel 0 address is the same as the transmit address
SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // Write data packet to TX FIFO
SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // Enable receive channel 0 automatic response
SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // Enable receiving channel 0
SPI_RW_Reg(RF_WRITE_REG + SETUP_RETR, 0x0a); // Automatic retransmission delay wait 250us+86us, automatic retransmission 10 times
SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // Select RF channel 0x40
SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // Data transmission rate 1Mbps, transmission power 0dBm, low noise amplifier gain
SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0e); // CRC enable, 16-bit CRC check, power on
CE_H;CE_H;delay_ms(1);
}
Function: Check_ACK()
Description:
Check whether the receiving device has received the data packet, and set whether to resend if no response
signal
************************************************/
uchar Check_ACK(u8 clear)
{
while(IRQ);
sta = SPI_RW(NOP); // Return status registerif
(MAX_RT)
if(clear) // Whether to clear TX FIFO, if not clear, resend after clearing the MAX_RT interrupt
flagSPI_RW(FLUSH_TX);
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // Clear TX_DS or MAX_RT interrupt flag
IRQ_H;
if(TX_DS)
return(0x00);
else
return(0xff);
}
void sent_data(u8* fp,u16 flong)
{
u16 i=65535;
TX_Mode((u8*)&flong); //Transmission lengthwhile
(!tran&&i>1)i--; //Wait for completiontran
=0;
flong=flong/33+1;
for(i=0;i<20000;i++);//130uS*2 delaywhile
(flong)
{
if(MAX_RT) return;//No response
returnTX_Mode(fp); //Transmit datawhile
(!tran&&i>1)i--; //Wait for completiontran
=0;
for(i=0;i<20000;i++);//130uS*2 delayfp
+=32;flong--;
}
void test (void)
{
if (Uart2_Get_Flag!=0&&Timer2==0)
{
sent_data(TX_BUF,(u16)Uart2_Get_Flag);
Uart2_Get_Flag=0;
}
if(Timer2==0&&RX_NU==2)
{
RX_NU=1 ;
USART2_Puts("Transmission Error");
USART2_Puts("\r\n");
}
}
* Function Name : EXTI0_IRQHandler
* Description : This function handles External interrupt Line 0 request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
extern u8 sta;
extern char RX_BUF[256];
extern uchar TX_BUF[256];
extern u8 SPI_RW_Reg(u8 reg, u8 value);
extern void RX_Mode(void);
extern uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes);
u8 RX_NU=1;//1 receive length 2 receive data
u16 rectnu,onerc; //receive string length, receive times
char* PRX_BUF=RX_BUF;
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0);
tran=1;
CSN_L;
sta=SPI_RW(NOP); // Return to status register
CSN_H;
if(MAX_RT)
{
USART2_Puts("No response from the other party");
CSN_L;
SPI_RW(FLUSH_TX); // Clear TX FIFO. If not cleared, resend CSN_H after clearing the MAX_RT interrupt flag
;
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta);
}
if(TX_DS)
{
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // Clear TX_DS or MAX_RT interrupt flag
}
{
if(RX_NU==1)
{
CE_L;
SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // Read data from RX FIFOSPI_RW_Reg
(RF_WRITE_REG + STATUS, sta); // Clear RX_DS interrupt flagrectnu
=RX_BUF[0];rectnu|=RX_BUF[1]<<8; // Receive string lengthonerc
=rectnu/33+1; // Calculate the number of
receptionsRX_NU=2;RX_Mode();Timer2=500; /*Timeout*/
return;
}
{
CE_L;
SPI_Read_Buf(RD_RX_PLOAD, PRX_BUF, TX_PLOAD_WIDTH); // Read data from RX FIFO
SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // Clear RX_DS interrupt flag
onerc--;PRX_BUF+=32; // Receive count receive pointer moves
{
RX_BUF[rectnu]='\0'; //Intercept the effective string length
USART2_Puts(RX_BUF); //Serial port sends the received characters
USART2_Puts("\r\n");
PRX_BUF=RX_BUF; //Restore pointer
RX_NU=1;
}
return;
}
}
LED;
RX_Mode();
}
/****************************************************** ******************************
* Function Name: USART2_IRQHandler
* Description: This function handles USART2 global interrupt request.
* Input: None
* Output: None
* Return: None
****************************************** *************************************/
extern u16 Uart2_Get_Flag;
extern u8 Uart2_Get_Data;
extern u8 TX_BUF[ 256];
void USART2_IRQHandler(void)
{
//Receive interrupt
if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)
{
Timer2=500; //After 500MS nfr2401 sends
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
TX_BUF[Uart2_Get_Flag]=USART_ReceiveData( USART2);
Uart2_Get_Flag++;
//USART2_Puts(TX_BUF);
}
//Overflow - if overflow occurs, read SR first, then read DR register to clear the problem of continuous interruption
if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET)
{
USART_ClearFlag(USART2 ,USART_FLAG_ORE); //read SR
USART_ReceiveData(USART2); //read DR
}
}
In the external interrupt, at least two transmissions can be made at a time. The first time RX_NU==1 is used to receive the data length of this transmission to intercept the effective string length. The second time RX_NU==2 receives the data and puts it into the array. If the data is longer than 32 bytes, it will be transmitted in multiple times. A timeout mechanism is introduced. If the transmission is not completed after 200/500 MS (RX_NU is equal to 1 again), the receiving data is abandoned and the new string length is directly received. This mechanism is very important but needs to be improved.
The same is true for the serial port. If there is no new data in 500MS, it means that the serial port has completed receiving the data and then sends the data. Uart2_Get_Flag is of course the serial length.
For NRF24L01, you can refer to its data sheet, which is all in Chinese. It’s easy to explain~~I won’t mention it here.
#ifndef _API_DEF_
#define _API_DEF_
// Define interface to nRF24L01
//* Define SPI pins
/*sbit CE = P1^0; // Chip Enable pin signal (output)
sbit CSN = P1^1; // Slave Select pin, (output to CSN, nRF24L01)
sbit IRQ = P1^3 ; // Interrupt signal, from nRF24L01 (input)
sbit MISO = P1^4; // Master In, Slave Out pin (input)
sbit MOSI = P1^5; // Serial Clock pin, (output)
sbit SCK = P1^ 7; // Master Out, Slave In pin (output)
*/
// SPI(nRF24L01) commands
#define RF_READ_REG 0x00 // Define read command to register
#define RF_WRITE_REG 0x20 // Define write command to register
#define RD_RX_PLOAD 0x61 // Define RX payload register address
#define WR_TX_PLOAD 0xA0 // Define TX payload register address
#define FLUSH_TX 0xE1 // Define flush TX register command
#define FLUSH_RX 0xE2 // Define flush RX register command
#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command
#define NOP 0xFF // Define No Operation, might be used to read status register
// SPI(nRF24L01) registers(addresses)
#define CONFIG 0x00 // 'Config' register address
#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR 0x02 // 'Enabled RX addresses' register address
#define SETUP_AW 0x03 // 'Setup address width' register address
#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
#define RF_CH 0x05 // 'RF channel' register address
#define RF_SETUP 0x06 // 'RF setup' register address
#define STATUS 0x07 // 'Status' register address
#define OBSERVE_TX 0x08 // 'Observe TX' register address
#define CD 0x09 // 'Carrier Detect' register address
#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address
#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address
#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address
#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address
#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address
#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address
#define TX_ADDR 0x10 // 'TX address' register address
#define RX_PW_P0 0x11 // 'RX payload width, pipe0 ' register address
#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address
#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address
#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address
#endif /* _API_DEF_ */
extern u8 SPI_RW(u8 byte); #define
TX_ADR_WIDTH 5 // 5-byte width
transmit
/
receive
address
#define
TX_PLOAD_WIDTH
32
//
Receive
byte
number 32 words
#define uchar u8
/
*
control pin */
#define
CE_H GPIOC->BSRR=GPIO_Pin_4
#define CE_L GPIOC->BRR=GPIO_Pin_4
#define CSN_H GPIOB->BSRR=GPIO_Pin_2
#define CSN_L GPIOB->BRR=GPIO_Pin_2
#define IRQ (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0))
#define IRQ_H GPIOB->BSRR=GPIO_Pin_0
#define LED1 GPIOB->BSRR=GPIO_Pin_12
#define LED0 GPIOB->BRR=GPIO_Pin_12
#define LED GPIOB->ODR=((GPIOD->ODR)^GPIO_Pin_12)
#define RX_DR ((sta>>6)&0X01)
#define TX_DS ((sta>>5)&0X01)
#define MAX_RT ((sta>>4)&0X01)
//USART
extern void USART2_Putc(unsigned char c);
extern void USART2_Puts(char * str);
extern u16 Uart2_Get_Flag; //Data length received by serial port 2
extern u8 Uart2_Get_Data; //Data received by serial port 2
#endif
Pay attention to the priority setting before interruption
#include "STM32Lib\\stm32f10x.h"
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure interrupt usage combination 1*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* EXTI0*/
NVIC_InitStructure.NVIC_IRQChannel =EXTI0_IR Qn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*UART2*/
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority
= 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
Previous article:The role of the type modifier volatile in STM32 code
Next article:STM32 drives MAX6675 to read temperature
Recommended ReadingLatest update time:2024-11-16 13:04
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- How does TTL inverter work?
- Giant microbit (giga:bit)
- Renesas CPK-RA6M4 Development Board Review + Unboxing and Building Environment
- Has anyone used the ionizing radiation sensor module? Discuss some technical issues
- RS-485 communication interface encoder
- FPGA Implementation of Fully Parallel FFT
- RT-Thread has been ported to W600
- MakeCode now supports STM103
- Please help me with the trip zone configuration of TI's 28034!!!
- Is the threshold for electromagnetic wave and antenna major getting lower and lower? Is the reliance on simulation software getting higher and higher?