Experience and solution on nRF24L01 reading any internal register value as 08H[Copy link]
A certain design required the use of nRF24L01 to achieve bidirectional data communication. When the program that was originally successfully running on the 51 microcontroller was transplanted to the STM8 microcontroller, the problem of not being able to run occurred. When trying to read the internal registers of nRF24L01 to view the working status of the module, it was found that no matter which register the read value was 0x08. Now I will describe this experience and the final solution in detail. The original design platform was IAP15W4K58S4, the development environment was Keil uVision4, and the set working frequency was 22.1184MHz; the transplanted target platform was STM8S105K4T6, the development environment was IAR for STM8, HSE: 8MHz was used, and the CPU clock was not divided. The design also used serial communication with a baud rate of 115200bps and external interrupts. Due to design requirements, on the STM8S, the nRF24L01 module was connected to the PB0~PB5 ports of the STM8S in the form of software simulating SPI. The pin definitions are as follows: #define nRF24L01_MISO PB_IDR_IDR5 #define nRF24L01_MOSI PB_ODR_ODR4 #define nRF24L01_SCK PB_ODR_ODR3 #define nRF24L01_CSN PB_ODR_ODR2 #define nRF24L01_CE PB_ODR_ODR1 #define nRF24L01_IRQ PB_IDR_IDR0 Copy code Following the basic steps of debugging, I replaced the wireless module, the connection line, and the platform core board, but none of them could solve the problem. Considering the IIC interface of STM8S, it is a true open-drain output without an internal pull-up resistor. So I checked the chip manual:
From the manual, we can see that PE1 and PE2 of STM8S105K4T6 are real open-drain outputs, but these two pins are not available on the LQFP32 package I use. PB4 and PB5 are IIC mapping pins with pull-up resistors. So the problem is not with the pin selection. I checked the chip manual again and noticed that the output speed of the PB pins is all at the O1 level. The manual describes O1 as follows:
It can be seen that O1 is a non-configurable 2MHz slow pin. Because the operating frequency of the microcontroller I configured reached 8MHz, I suspected that the pin level changed too fast during the communication with nRF24L01, resulting in unstable IO level. So I configured CPUDIV to make the CPU operating frequency divided by 8 at 1MHz, but the fault still exists. So the pin output speed is not the cause of the problem. Re-checking the nRF24L01 chip manual, I thought that the read values of each register of the chip were all 08H, so the possibility of chip initialization failure should be ruled out. Because regardless of whether it is initialized or not, after following the correct configuration steps, the register reserved bits inside the chip should keep the reserved values unchanged. However, the current phenomenon is that, taking the CD carrier detection register as an example, there should only be two possible values 00H and 01H, but it reads 08H. Focusing on the underlying SPI simulation functions that communicate with the module, the SPI read and write functions I use on the 51 platform are as follows: unsigned char nRF24L01_SPI_RW(unsigned char dat)//Send a byte of data to SPI, and due to the characteristics of its shift register, return the received byte{ unsigned char i; for(i=0;i<8;i++)//Output 8 bits{ nRF24L01_MOSI=(dat&0x80);//High bit out first, pass bit by bitdat=(dat<<1);//Transfer bitnRF24L01_SCK=1;//Set the clock highnRF24L01_MISO=1; dat|=nRF24L01_MISO;//Get the bit sent from the slavenRF24L01_SCK=0; //Pull down the clock} return(dat);//Return the shifted data} Copy the code and rewrite the function according to the SPI protocol as follows: unsigned char nRF24L01_SPI_RW(unsigned char dat)//Send a byte of data to SPI, and according to the characteristics of its shift register, return the received byte{ unsigned char i; for(i=0;i<8;i++)//Output 8 bits{ if(dat&0x80) { nRF24L01_MOSI=1; } else { nRF24L01_MOSI=0; } dat=(dat<<1);//Transfer bit nRF24L01_SCK=1;//Set high clockif(nRF24L01_MISO) { dat|=1; } else { dat|=0; } nRF24L01_SCK=0; //Pull down the clock} return(dat);//Return the shifted data} Copy the code and unexpectedly it returned to normal. After gradual simplification and debugging, such an expression can also run normally in the IAR environment: unsigned char nRF24L01_SPI_RW(unsigned char dat)//Send a byte of data to SPI, and according to the characteristics of its shift register, return the received byte{ unsigned char i; for(i=0;i<8;i++)//Output 8 bits{ nRF24L01_MOSI=(_Bool)(dat&0x80);//High bit out first, pass bit by bit, forced to convert to Boolean type dat=(dat<<1);//Transfer bit nRF24L01_SCK=1;//Set clock high dat|=nRF24L01_MISO//Get the bit sent from the slave nRF24L01_SCK=0; //Pull down the clock} return(dat);//Return the data obtained by shifting} Copy the code Therefore, we can conclude that under IAR, a bit can only be assigned logical 0 or 1. If a non-Boolean data is assigned, confusion will occur.