【Let'sdo第1期-功率检测与控制系统DIY】使用nucle-F411RE SPITFTLCD液晶屏显示INA219模块检测电流
参加EEPW论坛2025 Let'sdo第1期-功率检测与控制系统DIY,大概任务就是使用nucle-F411RE开发板和INA219模块来检测开发板和用电器模块运行时的电压和电流,不过我这边对实验用器件做出了一些个人意向的修改,首先是我不太喜欢使用OLED屏进行显示,因为OLED屏能显示的信息太少,并且使用不当容易烧坏,因此我使用自己提供的SPITFTLCD液晶屏来显示,除此之外像INA219模块驱动代码都是完全一致的。这个课程需要占用PB8 PB9用作模拟I2C接口,占用PA5 PA6 PA7用作SPI1接口,以及一些GPIO作为液晶屏信号控制,然后再占用一组SPI2与NRF24L01模块进行通信,由于液晶屏和NRF24L01模块的SPI参数有差异,因此不使用同一组SPI接口:
void FAKE_I2C_INA_Delay() { uint8_t x; for(x=1;x>0;x--) { __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); } } void FAKE_I2C_INA_PB8_PB9_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; FAKE_I2C_INA_SCL_PB8_CLK_ENABLE; FAKE_I2C_INA_SDA_PB9_CLK_ENABLE; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pin = FAKE_I2C_INA_SCL_PB8_PIN; HAL_GPIO_Init(FAKE_I2C_INA_SCL_PB8_PORT , &GPIO_InitStruct); GPIO_InitStruct.Pin = FAKE_I2C_INA_SDA_PB9_PIN; HAL_GPIO_Init(FAKE_I2C_INA_SDA_PB9_PORT , &GPIO_InitStruct); FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_SDA_PB9_HIGH; } void FAKE_I2C_INA_PB8_PB9_SDA_OUT(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pin = FAKE_I2C_INA_SDA_PB9_PIN; HAL_GPIO_Init(FAKE_I2C_INA_SDA_PB9_PORT , &GPIO_InitStruct); } void FAKE_I2C_INA_PB8_PB9_SDA_IN(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Pin = FAKE_I2C_INA_SDA_PB9_PIN; HAL_GPIO_Init(FAKE_I2C_INA_SDA_PB9_PORT , &GPIO_InitStruct); } void FAKE_I2C_INA_PB8_PB9_Start(void) { FAKE_I2C_INA_SDA_PB9_HIGH; FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_Delay(); FAKE_I2C_INA_SDA_PB9_LOW; FAKE_I2C_INA_Delay(); FAKE_I2C_INA_SCL_PB8_LOW; } void FAKE_I2C_INA_PB8_PB9_Stop(void) { FAKE_I2C_INA_SDA_PB9_LOW; FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_Delay(); FAKE_I2C_INA_SDA_PB9_HIGH; FAKE_I2C_INA_Delay(); FAKE_I2C_INA_SCL_PB8_LOW; FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_SDA_PB9_HIGH; } bool FAKE_I2C_INA_PB8_PB9_ACK_Read(void) { bool ack; FAKE_I2C_INA_SDA_PB9_HIGH; FAKE_I2C_INA_PB8_PB9_SDA_IN(); FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_Delay(); if(FAKE_I2C_INA_SDA_PB9_READ == SET) ack = false; else ack=true; FAKE_I2C_INA_SCL_PB8_LOW; FAKE_I2C_INA_PB8_PB9_SDA_OUT(); return ack; } void FAKE_I2C_INA_PB8_PB9_ACK_Send(bool ack) { FAKE_I2C_INA_SCL_PB8_LOW; if(ack == true) { FAKE_I2C_INA_SDA_PB9_LOW; } else { FAKE_I2C_INA_SDA_PB9_HIGH; } FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_Delay(); FAKE_I2C_INA_SCL_PB8_LOW; } void FAKE_I2C_INA_PB8_PB9_Send_Byte(uint8_t byte) { uint8_t i; FAKE_I2C_INA_SCL_PB8_LOW; for(i=0;i<8;i++) { if(byte & 0x80) { FAKE_I2C_INA_SDA_PB9_HIGH; } else { FAKE_I2C_INA_SDA_PB9_LOW; } FAKE_I2C_INA_SCL_PB8_HIGH; FAKE_I2C_INA_Delay(); FAKE_I2C_INA_SCL_PB8_LOW; FAKE_I2C_INA_Delay(); byte <<= 1; } FAKE_I2C_INA_PB8_PB9_ACK_Read(); } uint8_t FAKE_I2C_INA_PB8_PB9_Read_Byte(void) { uint8_t i,byte=0; FAKE_I2C_INA_PB8_PB9_SDA_IN(); for(i=0;i<8;i++) { FAKE_I2C_INA_SCL_PB8_HIGH; byte<<=1; if(FAKE_I2C_INA_SDA_PB9_READ == SET) { byte |= 0x01; } else { byte &= 0xFE; } FAKE_I2C_INA_SCL_PB8_LOW; FAKE_I2C_INA_Delay(); } FAKE_I2C_INA_PB8_PB9_SDA_OUT(); return byte; } void FAKE_I2C_INA_PB8_PB9_Read_Bytes(unsigned char reg,unsigned char *data) { FAKE_I2C_INA_PB8_PB9_Start(); FAKE_I2C_INA_PB8_PB9_Send_Byte(INA219_ADDRESS); FAKE_I2C_INA_PB8_PB9_Send_Byte(reg); FAKE_I2C_INA_PB8_PB9_Start(); FAKE_I2C_INA_PB8_PB9_Send_Byte(INA219_ADDRESS + 0x01); *data = FAKE_I2C_INA_PB8_PB9_Read_Byte(); data++; FAKE_I2C_INA_PB8_PB9_ACK_Send(1); *data = FAKE_I2C_INA_PB8_PB9_Read_Byte(); FAKE_I2C_INA_PB8_PB9_ACK_Send(0); FAKE_I2C_INA_PB8_PB9_Stop(); } void FAKE_I2C_INA_PB8_PB9_REG_Write(unsigned char reg,unsigned int data) { unsigned char data_temp[2]; data_temp[0]=(unsigned char )(data>>8); data_temp[1]=(unsigned char )(data & 0xFF); FAKE_I2C_INA_PB8_PB9_Start(); FAKE_I2C_INA_PB8_PB9_Send_Byte(INA219_ADDRESS); FAKE_I2C_INA_PB8_PB9_Send_Byte(reg); FAKE_I2C_INA_PB8_PB9_Send_Byte(data_temp[0]); data++; FAKE_I2C_INA_PB8_PB9_Send_Byte(data_temp[1]); FAKE_I2C_INA_PB8_PB9_Stop(); } void INA_Init(void) { FAKE_I2C_INA_PB8_PB9_Init(); FAKE_I2C_INA_PB8_PB9_REG_Write(INA219_REG_CONFIG , INA219_CONFIG_value); FAKE_I2C_INA_PB8_PB9_REG_Write(INA219_REG_CALIBRATION , INA_CAL); } unsigned int INA_GET_Voltage_MV(void) { unsigned char data_temp[2]; FAKE_I2C_INA_PB8_PB9_Read_Bytes(0x02 , data_temp); return (int)((((data_temp[0]<<8) + data_temp[1]) >> 3)*4); } unsigned int INA_GET_Current_MA(void) { unsigned char data_temp[2]; FAKE_I2C_INA_PB8_PB9_REG_Write(INA219_REG_CONFIG , INA219_CONFIG_value); FAKE_I2C_INA_PB8_PB9_Read_Bytes(INA219_REG_CURRENT , data_temp); return (int)((((data_temp[0]<<8) + data_temp[1]))*IAN_I_LSB); } unsigned int INA_GET_Power_MW(void) { unsigned char data_temp[2]; FAKE_I2C_INA_PB8_PB9_Read_Bytes(INA219_REG_POWER , data_temp); return (int)(((data_temp[0]<<8) + data_temp[1]) * INA_Power_LSB); }
这里使用模拟I2C逻辑来驱动INA219模块,可以很方便移植到别的平台上,并且不受GPIO引脚限制。INA219模块的模拟I2C时序跟一般常用的I2C器件如BMP280 MPU9250 DS3231的时序有细微差别,两者的代码无法直接通用。
#define FAKE_I2C_INA_SCL_PB8_PORT GPIOB #define FAKE_I2C_INA_SCL_PB8_PIN GPIO_PIN_8 #define FAKE_I2C_INA_SCL_PB8_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE(); #define FAKE_I2C_INA_SCL_PB8_HIGH HAL_GPIO_WritePin(FAKE_I2C_INA_SCL_PB8_PORT , FAKE_I2C_INA_SCL_PB8_PIN , GPIO_PIN_SET); #define FAKE_I2C_INA_SCL_PB8_LOW HAL_GPIO_WritePin(FAKE_I2C_INA_SCL_PB8_PORT , FAKE_I2C_INA_SCL_PB8_PIN , GPIO_PIN_RESET); #define FAKE_I2C_INA_SDA_PB9_PORT GPIOB #define FAKE_I2C_INA_SDA_PB9_PIN GPIO_PIN_9 #define FAKE_I2C_INA_SDA_PB9_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE(); #define FAKE_I2C_INA_SDA_PB9_HIGH HAL_GPIO_WritePin(FAKE_I2C_INA_SDA_PB9_PORT , FAKE_I2C_INA_SDA_PB9_PIN , GPIO_PIN_SET); #define FAKE_I2C_INA_SDA_PB9_LOW HAL_GPIO_WritePin(FAKE_I2C_INA_SDA_PB9_PORT , FAKE_I2C_INA_SDA_PB9_PIN , GPIO_PIN_RESET); #define FAKE_I2C_INA_SDA_PB9_READ HAL_GPIO_ReadPin(FAKE_I2C_INA_SDA_PB9_PORT , FAKE_I2C_INA_SDA_PB9_PIN) #define INA219_ADDRESS (0x40 << 1)
INA2219的地址选位0x40,其实是可以通过拨码开关设置为0x45的,使用起来没有任何区别。
然后再使用SPI1(PA5 PA6 PA7)来点SPITFTLCD彩屏:
uint8_t SPI1_PA5_PA6_PA7_Read_Write_Byte(uint8_t TxData) { uint8_t Rxdata; HAL_SPI_TransmitReceive(&hspi1 , &TxData , &Rxdata , 1 , 1000); return Rxdata; } void SPI1_PA5_PA7_Write_Byte(uint8_t TxData) { HAL_SPI_Transmit(&hspi1 , &TxData , 1 , 1000); } void SPI1_PA5_PA6_PA7_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; HAL_GPIO_Init(GPIOA , &GPIO_InitStruct); hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; HAL_SPI_Init(&hspi1); hdma_spi1_rx.Instance = DMA2_Stream0; hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3; hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi1_rx.Init.Mode = DMA_NORMAL; hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW; hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_spi1_rx); __HAL_LINKDMA(&hspi1 , hdmarx , hdma_spi1_rx); hdma_spi1_tx.Instance = DMA2_Stream2; hdma_spi1_tx.Init.Channel = DMA_CHANNEL_2; hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi1_tx.Init.Mode = DMA_NORMAL; hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW; hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_spi1_tx); __HAL_LINKDMA(&hspi1 , hdmatx , hdma_spi1_tx); HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); }
还需要PA4 PA8 PB7三个GPIO来控制液晶屏的片选,复位,DC选择:
#define SPITFTLCD_ST7789_CS_GPIO_PORT GPIOA #define SPITFTLCD_ST7789_CS_GPIO_PIN GPIO_PIN_4 #define SPITFTLCD_ST7789_CS_GPIO_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE(); #define SPITFTLCD_ST7789_CS_HIGH HAL_GPIO_WritePin(SPITFTLCD_ST7789_CS_GPIO_PORT , SPITFTLCD_ST7789_CS_GPIO_PIN , GPIO_PIN_SET); #define SPITFTLCD_ST7789_CS_LOW HAL_GPIO_WritePin(SPITFTLCD_ST7789_CS_GPIO_PORT , SPITFTLCD_ST7789_CS_GPIO_PIN , GPIO_PIN_RESET); #define SPITFTLCD_ST7789_RESET_GPIO_PORT GPIOA #define SPITFTLCD_ST7789_RESET_GPIO_PIN GPIO_PIN_8 #define SPITFTLCD_ST7789_RESET_GPIO_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE(); #define SPITFTLCD_ST7789_RESET_HIGH HAL_GPIO_WritePin(SPITFTLCD_ST7789_RESET_GPIO_PORT , SPITFTLCD_ST7789_RESET_GPIO_PIN , GPIO_PIN_SET); #define SPITFTLCD_ST7789_RESET_LOW HAL_GPIO_WritePin(SPITFTLCD_ST7789_RESET_GPIO_PORT , SPITFTLCD_ST7789_RESET_GPIO_PIN , GPIO_PIN_RESET); #define SPITFTLCD_ST7789_DC_GPIO_PORT GPIOB #define SPITFTLCD_ST7789_DC_GPIO_PIN GPIO_PIN_7 #define SPITFTLCD_ST7789_DC_GPIO_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE(); #define SPITFTLCD_ST7789_DC_HIGH HAL_GPIO_WritePin(SPITFTLCD_ST7789_DC_GPIO_PORT , SPITFTLCD_ST7789_DC_GPIO_PIN , GPIO_PIN_SET); #define SPITFTLCD_ST7789_DC_LOW HAL_GPIO_WritePin(SPITFTLCD_ST7789_DC_GPIO_PORT , SPITFTLCD_ST7789_DC_GPIO_PIN , GPIO_PIN_RESET);
使用显示ASCII字符的函数显示必要信息:
void SPITFTLCD_ST7789_ShowChar1632(uint16_t x , uint16_t y , uint8_t num , uint16_t fc , uint16_t bc , uint8_t mode) { uint8_t temp,sizex,t,m=0; uint16_t i,TypefaceNum; uint16_t x0=x; sizex=16; TypefaceNum=(sizex/8+((sizex%8)?1:0))*32; num=num-' '; SPITFTLCD_ST7789_Address_Set(x,y,x+sizex-1,y+32-1); for(i=0;i<TypefaceNum;i++) { temp = ascii_3216[num][i]; for(t=0;t<8;t++) { if(!mode) { if(temp&(0x01<<t))SPITFTLCD_ST7789_WR_DATA(fc); else SPITFTLCD_ST7789_WR_DATA(bc); m++; if(m%sizex==0) { m=0; break; } } else { if(temp&(0x01<<t))SPITFTLCD_ST7789_DrawPoint(x , y , fc); x++; if((x-x0)==sizex) { x=x0; y++; break; } } } } } void SPITFTLCD_ST7789_ShowString1632(uint16_t x , uint16_t y , const uint8_t *p , uint16_t fc , uint16_t bc , uint8_t mode) { while(*p != '\0') { SPITFTLCD_ST7789_ShowChar1632(x,y,*p,fc,bc,mode); x += 16; p++; } }
定时器2和定时器3初始化:
TIM_HandleTypeDef TIM2_Handler; TIM_HandleTypeDef TIM3_Handler; void TIM2_Init(uint16_t arr,uint16_t psc) { __HAL_RCC_TIM2_CLK_ENABLE(); TIM2_Handler.Instance=TIM2; TIM2_Handler.Init.Prescaler=psc; TIM2_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; TIM2_Handler.Init.Period=arr; TIM2_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&TIM2_Handler); HAL_TIM_Base_Start(&TIM2_Handler); } void TIM3_Init(uint16_t arr,uint16_t psc) { __HAL_RCC_TIM3_CLK_ENABLE(); TIM3_Handler.Instance=TIM3; TIM3_Handler.Init.Prescaler=psc; TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; TIM3_Handler.Init.Period=arr; TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&TIM3_Handler); HAL_TIM_Base_Start(&TIM3_Handler); }
定时器2和定时器3设置参数,定时器2为100ms溢出,定时器3为500ms溢出:
TIM2_Init(1000 - 1 , 5000 - 1); TIM3_Init(5000 - 1 , 5000 - 1);
INA219模块的测量口正负极直接接在开发板的供电跳帽上,就可以获取开发板运行电流以及运行功率了:
SPI2初始化:
uint8_t SPI2_PB10_PC2_PC3_Read_Write_Byte(uint8_t TxData) { uint8_t Rxdata; HAL_SPI_TransmitReceive(&hspi2 , &TxData , &Rxdata , 1 , 1000); return Rxdata; } void SPI2_PB10_PC2_PC3_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_SPI2_CLK_ENABLE(); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; GPIO_InitStruct.Pin = GPIO_PIN_10; HAL_GPIO_Init(GPIOB , &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; HAL_GPIO_Init(GPIOC , &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_3; HAL_GPIO_Init(GPIOC , &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_128; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 10; HAL_SPI_Init(&hspi2); }
通过SPI2接口设置NRF24L01模块收发模式以及收发函数:
uint8_t NRF24L01_Check(void) { uint8_t buf[5]={0xa5 , 0xa5 , 0xa5 , 0xa5 , 0xa5}; uint8_t i; NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR , buf , 5); NRF24L01_Read_Buf(TX_ADDR , buf , 5); for(i=0;i<5;i++) if(buf[i]!=0XA5) break; if(i!=5) return 1; return 0; } uint8_t NRF24L01_RxPacket(uint8_t *rxbuf) { uint8_t sta; sta = NRF24L01_Read_Reg(STATUS); NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS , sta); if(sta & RX_OK) { printf("sta = 0x%x RX_OK.\n" , sta); NRF24L01_Read_Buf(RD_RX_PLOAD , rxbuf , RX_PLOAD_WIDTH); NRF24L01_Write_Reg(FLUSH_RX , 0xff); return 0; } return 1; } uint8_t NRF24L01_TxPacket(uint8_t *txbuf) { uint8_t sta; NRF24L01_CE_LOW; NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); NRF24L01_CE_HIGH; while(NRF24L01_IRQ_READ() != 0); sta = NRF24L01_Read_Reg(STATUS); NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); if(sta&MAX_TX) { NRF24L01_Write_Reg(FLUSH_TX,0xff); return MAX_TX; } if(sta&TX_OK) { return TX_OK; } return 0xff; } void NRF24L01_RX_Mode(void) { NRF24L01_CE_LOW; NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH); NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH); NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f); NRF24L01_CE_HIGH; } void NRF24L01_TX_Mode(void) { NRF24L01_CE_LOW; NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);//дTX½ÚµãµØÖ· NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH); NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a); NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); NRF24L01_CE_HIGH; }
演示视频:
https://www.bilibili.com/video/BV16DMJzbE4z/?vd_source=06455e7f94c397f493f40aba56679e79