STC15单片机 固定翼无人机/航模 飞控程序

2023-05-16

stc15单片机 固定翼无人机 飞控程序

硬件

  1. stcf2k60s2
  2. 2.4g无线通信模块nrf24l01
  3. mg90s数字舵机
  4. 摇杆
  5. 无刷电机
  6. 电调

用到的单片机资源

  1. pwm
  2. ad转换

程序结构

  1. 利用ADC转换读取摇杆值
  2. 将摇杆数值转换为16进制通过2.4G无线通信模块发送置接收端
  3. 通过接收到的数据控制pwm改变来控制舵机电机

硬件使用

  1. 舵机
    采用50Hz的PWM信号控制
    在这里插入图片描述

  2. 电调
    采用71.4hz的PWM信号控制,高电平宽度为1.0到2.0ms,电调上电需要自检,自检的方法就是给高电平宽度为1ms持续3s左右,当电机发出急促的哔哔哔声音就自己成功,可以开始控制

程序

遥控端
左边摇杆控制油门
右边摇杆控制转向及高度

#include "STC15F2K60S2.H"
#include "stdio.h"
#include "intrins.h"   
#include "nrf_24l01.h"

#define uint unsigned int
#define uchar unsigned char
#define ADC_POWER 0xE0 //ADC电源控制位
#define ADC_FLAG 0x10 //ADC完成标志
#define ADC_START 0x08 //ADC起始控制位
#define ADC_SPEEDLL 0x00 //540个时钟

uchar rx_buf[TX_PLOAD_WIDTH];
uchar tx_buf[TX_PLOAD_WIDTH];
unsigned char sta;
uchar dat0;
uchar dat1;
uchar dat2;
uint num;
uint num0;
uint num1;
uint num2;
uint k;
sbit S1=P2^3;
sbit S2=P2^4;

void Delay100ms(void);
void delayms(int ms);
void uartInit(void);
void UARTSend(char ucData);
void UART_PutString(unsigned char *s);
uchar GetADCResult(unsigned char ch);
void InitADC();


void main(void)
{
  unsigned int lock_key=0;
	
	P0M0=0X00;P0M1=0X00;
	P1M0=0X00;P1M1=0X00;
	P2M0=0X00;P2M1=0X00;
	P3M0=0X00;P3M1=0X00;
	P4M0=0X00;P4M1=0X00;
	
  uartInit();	 
	Delay100ms();
  init_nrf24l01_io();
	InitADC();
  UART_PutString("READY!\r\n");
  ifnnrf_rx_mode();//初始化  接收模式

  while(1)
  {  
		  if(S1==0)
		   {
				 delayms(1);
				 if(S1!=0)
				 {
					 k=1;
				 }
			 }
			 	 if(S2==0)
		   {
				 delayms(1);
				 if(S2!=0)
				 {
					 k=2;
				 }
			 }
      num=GetADCResult(0);//num数值0-255
      num0=num/51;
      num=GetADCResult(2);
		  if(num<190)
			{
				num1=num/85;
			}
      if(190<num&&num<210)num1=3;
			if(num>210)
			{
				num1=(num-210)/15+3;
			}
      num=GetADCResult(3);
      if(num<160)
			{
				num2=num/80;
			}
      if(160<num&&num<185)num2=3;
			if(num>185)
			{
				num2=(num-185)/23+3;
			}		
			IRQ=1;
			SPI_RW_Reg(WRITE_REG+STATUS,0xff);
			tx_buf[0]=num0;//油门数据
			//if(k==1)
			//{
				tx_buf[1]=num1;//转向数据
			//}
		  //if(k==2)
			//{
				tx_buf[2]=num2;//上下数据
			//}
			ifnnrf_tx_mode();
			while(IRQ);  			
			sta=SPI_Read(STATUS);              
			SPI_RW_Reg(WRITE_REG+STATUS,0xff); 
      if(sta&STA_MARK_TX)                
			 {
				 delayms(1);
	     } 
		  else
		   {
		 		 ifnnrf_CLERN_ALL();
	     }
	    lock_key=1;
   }	
		
   if(lock_key) 
		{
			lock_key=0;
			ifnnrf_rx_mode();
			IRQ=1;
			while(IRQ==0);
			_delay_us(400);
    }
 }

/*************************串口初始化******************************************/
void uartInit(void)
{ 
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE0;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1  
	EA = 1;
	ES=1; 
}

/*******************************数据发送**************************************/
void UARTSend(char ucData)
{
	SBUF=ucData;
	while(TI==0);
	TI=0;
}
/******************************字符串发送*************************************/
void UART_PutString(unsigned char *pS)
{
	while(*pS)
	UARTSend(*pS++);
}




void delayms(int ms)//延时
{
	int i,j;
	for(i=ms;i>0;i--)
		for(j=845;j>0;j--);
}




/*******************************延迟函数**************************************/
void Delay100ms(void)       
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


//***************************读取ADC结果*************************************/
uchar GetADCResult(unsigned char ch)
{
	ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;//ADC_CONTR=0x8n; 
	_nop_(); //等待4个NOP
	_nop_();
	_nop_();
	_nop_();
	while (!(ADC_CONTR & ADC_FLAG)); //等待ADC转换完成
	ADC_CONTR &= ~ADC_FLAG; //Close ADC
	return ADC_RES; //返回ADC结果
}


//*****************************初始化ADC*************************************/
void InitADC()
{
	P1ASF = 0x80; //设置P1口为AD口
	ADC_RES = 0; //清除结果寄存器
	ADC_CONTR = ADC_POWER | ADC_SPEEDLL;   //ADC_CONTR =0x80;
	delayms(1); //ADC上电并延时
}

接收端

#include "STC15F2K60S2.H"
#include "intrins.h"   
#include "nrf_24l01.h"


uchar rx_buf[TX_PLOAD_WIDTH];
uchar tx_buf[TX_PLOAD_WIDTH];
unsigned char sta;

void Delay100ms(void);
void delayms(int ms);
void uartInit(void);
void UARTSend(char ucData);
void UART_PutString(unsigned char *s);
void Timer0_init(void);


unsigned int ZKB1=0;//占空比变量
unsigned int ZKB2=0;
unsigned int ZKB3=0;
int zhuanxian=0;//转向进入标志位
int shenjiang=0;//升降进入标志位

int flag_1=11;//标志位
int flag_2=11;
int flag_3=11;

void main(void)
{
   while(1)
  {
	unsigned int lock_key=0;
	
	P0M0=0X00;P0M1=0X00;//端口初始化
	P1M0=0X00;P1M1=0X00;
	P2M0=0X00;P2M1=0X00;
	P3M0=0X00;P3M1=0X00;
	P4M0=0X00;P4M1=0X00;
		

  uartInit();	 
	Timer0_init();
	Delay100ms();
  init_nrf24l01_io();
  ifnnrf_rx_mode();//初始化  接收模式
	/***********************************PWM********************************/
  ACC=AUXR1;
  ACC&=0xcf;
  ACC|=0x10;
  AUXR1=ACC;
	CCON = 0; //初始化PCA控制寄存器
	//PCA定时器停止
	//清除CF标志
	//清除模块中断标志
	CL = 0; //复位PCA寄存器
	CH = 0;
	CMOD = 0x04; //设置PCA时钟源   //禁止PCA定时器溢出中断

	PCA_PWM0 = 0x00; //PCA模块0工作于8位PWM
	CCAP0H = CCAP0L = 256-(256*ZKB1/100);
	CCAPM0 = 0x42; 
	
	PCA_PWM1 = 0x00; //PCA模块1工作于7位PWM
	CCAP1H = CCAP1L = 256-(256*ZKB2/100); //PWM1的占空比为75% ((80H-20H)/80H)
	CCAPM1 = 0x42; //PCA模块1为7位PWM模式
	
	PCA_PWM2 = 0x00; //PCA模块2工作于6位PWM
	CCAP2H = CCAP2L = 256-(256*ZKB3/100); //PWM2的占空比为50% ((40H-20H)/40H)
	CCAPM2 = 0x42; //PCA模块2为6位PWM模式
	
	CR = 1; //PCA定时器开始工作

	/****************************接收部分**********************************/		
   IRQ=1;
   if(IRQ==0) 
		{ 	  
			sta=SPI_Read(STATUS);
			SPI_RW_Reg(WRITE_REG+STATUS,0xff);
		if(sta&STA_MARK_RX) 
			{ 
				SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);

			if(rx_buf[0] == 0x00&&flag_1!=0) 
				{
					UART_PutString("油门关闭\r\n");//8-13
          ZKB1=5;

					flag_1=0;
				} 
			if(rx_buf[0] == 0x01&&flag_1!=1) 
				{
					UART_PutString("油门1\r\n");
          ZKB1=6;
					flag_1=1;
				} 
			if(rx_buf[0] == 0x02&&flag_1!=2) 
				{
					UART_PutString("油门2\r\n");
          ZKB1=7;
				  flag_1=2;
				} 
			if(rx_buf[0] == 0x03&&flag_1!=3) 
				{
					UART_PutString("油门3\r\n");
          ZKB1=8;
					flag_1=3;
				} 
			if(rx_buf[0] == 0x04 &&flag_1!=4) 
				{
					UART_PutString("油门4\r\n");
          ZKB1=9;
					flag_1=4;
				}
			if(rx_buf[0] == 0x05&&flag_1!=5) 
				{
					UART_PutString("油门5\r\n");
          ZKB1=10;
					flag_1=5;
				} 

			if(rx_buf[1] == 0x00&&flag_2!=0&&shenjiang==0) 
				{
					UART_PutString("左转3\r\n");
          ZKB2=4;
					zhuanxian=1;
					flag_2=0;
				} 
				
			if(rx_buf[1] == 0x01&&flag_2!=1&&shenjiang==0) 
				{
					UART_PutString("左转2\r\n");
          ZKB2=5;
					zhuanxian=1;
					flag_2=1;
				} 
			if(rx_buf[1] == 0x02&&flag_2!=2&&shenjiang==0) 
				{
					UART_PutString("左转1\r\n");
          ZKB2=6;
			    zhuanxian=1;
					flag_2=2;
				} 
			if(rx_buf[1] == 0x03&&flag_2!=3&&shenjiang==0) 
				{
					UART_PutString("转向归中\r\n");
          ZKB2=7;
					ZKB3=7;
					zhuanxian=0;
					flag_2=3;
				} 
			if(rx_buf[1] == 0x04&&flag_2!=4&&shenjiang==0) 
				{
					UART_PutString("右转1\r\n");
          ZKB3=6;
					zhuanxian=1;
					flag_2=4;
				} 
			if(rx_buf[1] == 0x05&&flag_2!=5&&shenjiang==0) 
				{
					UART_PutString("右转2\r\n");
          ZKB3=5;
					zhuanxian=1;
					flag_2=5;
				} 
	  	if(rx_buf[1] == 0x06&&flag_2!=6&&shenjiang==0) 
				{
					UART_PutString("右转3\r\n");
          ZKB3=4;
					zhuanxian=1;
					flag_2=6;
				} 
	  
			if(rx_buf[2] == 0x00&&flag_3!=0&&zhuanxian==0) 
				{
					UART_PutString("下降3\r\n");
          ZKB2=10;
					ZKB3=10;
					shenjiang=1;
					flag_3=0;
				} 
				
			if(rx_buf[2] == 0x01&&flag_3!=1&&zhuanxian==0) 
				{
					UART_PutString("下降2\r\n");
          ZKB2=9.5;
					ZKB3=9.5;
					shenjiang=1;
					flag_3=1;
				} 
	  	if(rx_buf[2] == 0x02&&flag_3!=2&&zhuanxian==0) 
				{
					UART_PutString("下降1\r\n");
          ZKB2=9;
					ZKB3=9;
					shenjiang=1;
					flag_3=2;
				} 
			if(rx_buf[2] == 0x03&&flag_3!=3&&zhuanxian==0) 
				{
					UART_PutString("上下归中\r\n");
          ZKB2=7;
          ZKB3=7;
					shenjiang=0;
					flag_3=3;
				} 
			if(rx_buf[2] == 0x04&&flag_3!=4&&zhuanxian==0) 
				{
					UART_PutString("上1\r\n");
          ZKB2=6;
					ZKB3=6;
					shenjiang=1;
					flag_3=4;
				} 
			if(rx_buf[2] == 0x05&&flag_3!=5&&zhuanxian==0) 
				{
					UART_PutString("上2\r\n");
          ZKB2=5;
					ZKB3=5;
					shenjiang=1;
					flag_3=5;
				} 
			if(rx_buf[2] == 0x06&&flag_3!=6&&zhuanxian==0) 
				{
					UART_PutString("上3\r\n");
          ZKB2=4;
					ZKB3=4;
					shenjiang=1;
					flag_3=6;
				} 

				rx_buf[0] = 0;
				rx_buf[1] = 0;
				rx_buf[2] = 0;				
			 } 
			else 
			{
				ifnnrf_CLERN_ALL();
				ifnnrf_rx_mode();
				IRQ=1;
				while(IRQ==0);
      }
   } //接收 
  }
}
/*************************串口初始化****************************************/
void uartInit(void)
{ 
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE0;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1  
	EA = 1;
	ES=1; 
}

/***************************数据发送******************************************/
void UARTSend(char ucData)
{
	SBUF=ucData;
	while(TI==0);
	TI=0;
}
/******************************字符串发送*************************************/
void UART_PutString(unsigned char *pS)
{
	while(*pS)
	UARTSend(*pS++);
}




void delayms(int ms)//延时
{
	int i,j;
	for(i=ms;i>0;i--)
		for(j=845;j>0;j--);
}

/*******************************延迟函数***************************************/
void Delay100ms(void)       
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

NRF_24L01.c
SPI通讯采用软件模拟引脚可随意更改

#include "STC15F2K60S2.H"
#include "NRF_24L01.h"

uchar const TX_ADDRESS[TX_ADR_WIDTH]  = {0x21,0x43,0x01,0x10,0x01}; // Define a static TX address
extern unsigned char tx_buf[];
extern unsigned char rx_buf[];
extern unsigned char sta;

/**********************微秒延迟函数*********************************/
void _delay_us(unsigned int _us)
{
    char a=0;
    for(_us;_us;_us--)
        for(a=0;a<1;a++);
}

/*******************模块初始化函数************************/
void init_nrf24l01_io(void)
{
	CE=0;			// chip enable
	CSN=1;			// Spi disable	
	SCK=0;			// Spi clock line init high
}

bdata unsigned char st=0;
sbit st_1=st^0;
sbit st_2=st^1;
sbit st_3=st^2;
sbit st_4=st^3;
sbit st_5=st^4;
sbit st_6=st^5;
sbit st_7=st^6;
sbit st_8=st^7;
bdata unsigned char st1=0;
sbit st_11=st1^0;
sbit st_12=st1^1;
sbit st_13=st1^2;
sbit st_14=st1^3;
sbit st_15=st1^4;
sbit st_16=st1^5;
sbit st_17=st1^6;
sbit st_18=st1^7;

//------IO模拟SPI的功能。将输出字节( MOSI)从MSB循环输出,同时将输入字节( MISO)从LSB 循环移入。上升沿读入,下降沿输出--------------------------
uchar SPI_RW(uchar byte)
{
    st=byte;

    MOSI=st_8;
    SCK = 1;
    st_18=MISO;
    SCK = 0;

    MOSI=st_7;
    SCK = 1;
    st_17=MISO;
    SCK = 0;

    MOSI=st_6;
    SCK = 1;
    st_16=MISO;
    SCK = 0;

    MOSI=st_5;
    SCK = 1;
    st_15=MISO;
    SCK = 0;

    MOSI=st_4;
    SCK = 1;
    st_14=MISO;
    SCK = 0;

    MOSI=st_3;
    SCK = 1;
    st_13=MISO;
    SCK = 0;

    MOSI=st_2;
    SCK = 1;
    st_12=MISO;
    SCK = 0;

    MOSI=st_1;
    SCK = 1;
    st_11=MISO;
    SCK = 0;
		
    return(st1);           		  
}

/**************************寄存器访问函数*****************************/
void SPI_RW_Reg(BYTE reg, BYTE value)
{
	CSN = 0;                   // CSN low, init SPI transaction
	SPI_RW(reg);      // select register
	SPI_RW(value);             // ..and write value to it..
	CSN = 1;                   // CSN high again
}

/*******************读取寄存器值的函数******************************/
BYTE SPI_Read(BYTE reg)
{
	BYTE reg_val;

	CSN = 0;                // CSN low, initialize SPI communication...
	SPI_RW(reg);            // Select register to read from..
	reg_val = SPI_RW(0);    // ..then read registervalue
	CSN = 1;                // CSN high, terminate SPI communication

	return(reg_val);        // return register value
}

/******************接收缓冲区访问函数********************************/
void SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
	uchar byte_ctr;

	CSN = 0;                    		// Set CSN low, init SPI tranaction
	SPI_RW(reg);       		// Select register to write to and read status byte

	for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
		pBuf[byte_ctr] = SPI_RW(0);    // Perform SPI_RW to read byte from nRF24L01

	CSN = 1;                           // Set CSN high again
}

/**************************************************************/
void SPI_Write_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
	uchar byte_ctr;

	CSN = 0;                   // Set CSN low, init SPI tranaction
	SPI_RW(reg);    // Select register to write to and read status byte
	for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
		SPI_RW(*pBuf++);
	CSN = 1;                 // Set CSN high again
}

/****************************设备初始化为接收模式*********************************/
void ifnnrf_rx_mode(void)
{
	CE=0;
	SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device

	SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      // Enable Auto.Ack:Pipe0
	SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  // Enable Pipe0
	SPI_RW_Reg(WRITE_REG + RF_CH, 40);        // Select RF channel 40
	SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width
	SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x27);   // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
	SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);     // Set PWR_UP bit, enable CRC(2 bytes) & Prim:RX. RX_DR enabled..

	CE = 1; // Set CE pin high to enable RX device
}

/****************************模块设置为发射模式*********************************/
void ifnnrf_tx_mode(void)
{
	CE=0;
	
	SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // Writes TX_Address to nRF24L01
	SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack
	SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // Writes data to TX payload

	SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      // Enable Auto.Ack:Pipe0
	SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  // Enable Pipe0
	SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...
	SPI_RW_Reg(WRITE_REG + RF_CH, 40);        // Select RF channel 40
	SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x27);   // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
	SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);     // Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT & TX_DS enabled..
	CE=1;
}

void SPI_CLR_Reg(BYTE R_T)                    //no
{
  CSN = 0; 
	if(R_T==1)                  // CSN low, init SPI transaction
		SPI_RW(FLUSH_TX);             // ..and write value to it..
	else
		SPI_RW(FLUSH_RX);             // ..and write value to it..
  CSN = 1;                   // CSN high again
}

void ifnnrf_CLERN_ALL()
{
  SPI_CLR_Reg(0);
  SPI_CLR_Reg(1);
  SPI_RW_Reg(WRITE_REG+STATUS,0xff);
  IRQ=1;
}

NRF_24L01.h

#ifndef _NRF24L01_
#define _NRF24L01_

#define IRQ             P22   //中断信号。无线通信过程中MCU 主要是通过IRQ 与NRF24L01 进行通信。
#define CE              P36   //芯片的模式控制线。在 CSN 为低的情况下, CE 协同NRF24L01 的CONFIG 寄存器共同决定NRF24L01 的状态
#define CSN             P55   //芯片的片选线, CSN 为低电平芯片工作
#define SCK             P41   //芯片控制的时钟线( SPI 时钟)
#define MOSI            P37   //芯片控制数据线( Master input slave output)
#define MISO            P45   //芯片控制数据线( Master output slave input)

typedef unsigned char uchar;
typedef unsigned char BYTE;

#define TX_ADR_WIDTH    5   // 5  bytes TX(RX) address width

#define TX_PLOAD_WIDTH  32  // 32 bytes TX payload

#define READ_REG        0x00  // Define read command to register
#define 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
#define STA_MARK_RX     0X40
#define STA_MARK_TX     0X20
#define STA_MARK_MX     0X10	    

void NRF24L01_SPI_Init(BYTE Mode);     // Init HW or SW SPI
uchar SPI_RW(BYTE byte);                                // Single SPI read/write
uchar SPI_Read(BYTE reg);                               // Read one byte from nRF24L01
void SPI_RW_Reg(BYTE reg, BYTE byte);                  // Write one byte to register 'reg'
void SPI_Write_Buf(BYTE reg, BYTE *pBuf, BYTE bytes);  // Writes multiply bytes to one register
void SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes);   // Read multiply bytes from one register

void init_nrf24l01_io(void);
void ifnnrf_rx_mode(void);
void ifnnrf_tx_mode(void);
void ifnnrf_CLERN_ALL();

void _delay_us(unsigned int _us);


#endif

![](https://img-blog.csdnimg.cn/20210703020802680.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzU4ODQ0OTY4,size_16,color_FFFFFF,t_70)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STC15单片机 固定翼无人机/航模 飞控程序 的相关文章

  • STM32 串口的使用

    STM32 串口的使用 以串口调试助手为例 64 STM32基本外设 串口介绍 USART Universal Synchronous Asynchronous Receiver and Transmitter 通用同步异步收发器 是一 个
  • 中断里使用延时函数

    中断里使用延时函数 64 STM32和MSP432常见问题 STM32 在实际应用中发现 xff0c 在STM32的中断里使用延时函数HAL Delay Delay 容易出现问题 与SysTick中断的优先级 xff0c 故采用while
  • Python中的PID库

    Python中的PID库 64 树莓派学习笔记 PID 加入了条件积分抗积分饱和 xff0c 加入了一阶低通滤波滤除高频噪声 链接 xff1a https github com EduardoNigro Things DAQ Code bl
  • 数字信号处理上机实验一

    数字信号处理上机实验一 给定信号 x n 61
  • 如何使用arduino 更改传感器寄存器的内容,这里以更改MLX90614的地址为例

    这里参考了这篇文章 xff08 ARDUINO使用MLX90614红外温度传感器研究笔记 雨田大大的博客 CSDN博客 mlx90614红外传感器 xff09 xff0c 构建了一个修改地址的程序关于crc校验的部分 xff08 CRC x
  • linux网络编程之udp

    这里写目录标题 UDP服务器代码UDP客服端代码结果 UDP服务器代码 ucp ser c span class token macro property span class token directive hash span span
  • 【Jetson Orin NX 开发板烧录启动系统】

    64 英伟达Jetson Orin NX 开发板上市有一段时间了 xff0c 其中16G套件能提供100TOPS算力 xff0c 性能是上一代Jetson Xavier NX 的 5 倍 其启动系统安装于之前Jetpack SD 烧录完全不
  • 起航-GitLens使用

    目录 GitLens 插件功能介绍准备工作开始使用加入暂存区 xff0c 和取消修改操作取消暂存区 xff0c 取消add操作加入到本地分支 xff0c 提交到远程提交记录远程被修改提示分支合并功能管理所有分支记录工作区暂存 GitLens
  • 在Docker环境下使用ROS

    在Docker环境下使用ROS Docker安装 参考 https docs docker com install linux docker ce ubuntu 卸载老旧版本 sudo apt get remove docker docke
  • 嵌入式linux项目之智能仓储(基于正点原子IMX6ULL开发板)

    基于正点原子的IMX6ULL开发板的智能仓储项目 提示 xff1a 该项目根据华清远见智能仓储项目改版 xff0c 将他的A9开发板换成了自己的IMX6ULL开发板 同时等我将该项目整个流程完成之后 xff0c 会为大家附上适配正点原子li
  • STM32电路知识学习

    STM32最小系统板电路知识学习 单片机最小系统是指用最少的电路组成单片机可以工作的系统 xff0c 通常最小系统包含 xff1a 电源电路 时钟电路 复位电路 调试 下载电路 xff0c 对于STM32还需要启动选择电路 总之 xff0c
  • ubuntu18.04运行vins-fusion跑通自己的数据集

    博主是双目加imu 命令 xff1a xff08 一定要记得改成自己的路径哦 xff09 cd catkin ws source devel setup bash roslaunch vins vins rviz launch source
  • 17.C语言 常见面试题

    嵌入式工程师必备0x10到题目 宏定义 1 用预处理指令 define声明一个常数 xff0c 用于表明1年中有多少秒 define 宏名 宏体 宏名 xff1a 大写字母表示 define SECOND OF YEAR 365 24 36
  • 自动控制原理第一章

    开环控制系统 xff1a 输入量与输出量没有反向联系 被控量 xff08 输出信号 xff09 xff0c 系统在特定输入下的输出称系统对该输入的响应 控制量 xff08 输入信号 xff09 给定值 扰动 xff1a 破坏控制量与被控量正
  • 利用Mavros控制无人机

    准备 xff1a 1 ubuntu18 04 2 Qgc 3 Mavros 4 ROS 5 PX4 Mavros安装 xff1a 参考安装链接 xff1a Ubuntu18 04安装px4 43 mavros xff08 解决mavros报
  • 5分钟搭建MySQL监控平台(mysql-exporter+Prometheus+Grafana)

    一 工具介绍 Prometheus 普罗米修斯可以简单理解为一个监控工具 xff0c 以时间为单位展示指定数据维度的变化 趋势 span style color fe2c24 strong mysqld exporter strong sp
  • Prometheus环境搭建

    实验环境 xff1a 准备三台虚拟机 xff0c 本文用Centos7为例 xff1b 我这里所使用的的虚拟机地址分别为 xff1a 主机名 xff1a IP prometheus weme 192 168 10 63 agent weme
  • 无人机飞控系统硬件设计

    目录 一 飞行控制系统简介 1 飞控系统功能分析 2 飞控系统基本原理 3 飞控系统的组成部分 3 1 地面部分 3 2 中央处理器 3 3 传感器模块 3 4 传输定位模块 二 飞控系统硬件平台设计 一 飞行控制系统简介 1 飞控系统功能
  • Ubuntu20.04中怎么更换源都不行install或者update始终报错,解决方案

    更换源后安装或者更新依旧报错 xff0c 试试下面两种方法 xff0c 亲测可行 方法一 xff1a 静态ip改成动态ip 如果ip是静态改成动态ip后 xff0c 重新在试试apt update 1 vi etc netplan 00 i
  • AlphaGo 引发的中国象棋之路

    笔者是一位多年的象棋爱好者 xff0c 早在2005 xff0c 中国象棋有款软件奇兵1 04 xff0c 当时打败特级大师于幼华 xff0c 又打败了柳大华 xff0c 后期软件和计算机硬件的发展 xff0c 象棋软件又有了质的飞越 xf

随机推荐

  • linux驱动IO模型

    1 非阻塞 当应用层读取驱动中的数据时 xff0c 无论数据是否准备号 xff0c 都需要立即返回 open 34 dev mycdev 34 O RDWR O NOBLOCK 非阻塞方式打开 默认打开方式为阻塞方式打开 O NOBLIOC
  • ROS学习(一)工作空间,功能包,节点

    本文主要介绍建立一个功能包 xff0c 一个publisher结点 xff0c 实现话题的发布 一工作空间 1创建所需的文件夹 mkdir ros cd ros mkdir src 2工作空间的初始化 cd src catkin init
  • NVIDIA Jetson Xavier NX搭建pytorch gpu环境(超详细)

    NVIDIA Jetson Xavier NX开发套件在搭建tensorflow gpu环境时可以使用指令直接安装或者官网下载whl文件安装 作者在安装pytorch环境时总是安装不上gpu版本 报错 AssertionError Torc
  • uCOS-iii学习笔记(11)——任务信号量和任务消息队列

    理解 xff1a 任务信号量 任务消息队列是跟随任务创建而来的 xff0c 不需要额外创建 xff0c 并且他和多值信号量 消息队列有一些不同 xff0c 多值信号量他们是建立于1对多得关系 xff0c 而我们的任务信号量还有任务消息队列是
  • C语言当中什么情况下形参可以改变实参详细实例及解释

    在 C 语言中 xff0c 形参可以改变实参的值的情况与 C 43 43 类似 xff0c 也有传递指针和传递引用两种方式 传递指针 当我们传递一个指针作为函数的形参时 xff0c 函数内部同样可以通过这个指针来改变指向的实参的值 这是因为
  • git仓库与vscode关联

    git仓库与vscode关联 git安装完后 xff0c 会提示输入用户信息 a 设置用户名 xff1a git config global user name 39 你再github上注册的用户名 39 b 设置用户邮箱 xff1a gi
  • python修改全局变量

    span class token comment 全局变量 span num span class token operator 61 span span class token number 10 span span class toke
  • python函数不能修改全局变量

    span class token comment 全局变量 span num span class token operator 61 span span class token number 10 span span class toke
  • FreeRTOS笔记(六)互斥量mutex

    概念 互斥量是二进制信号量的一个变种 xff0c 开启互斥量需要在头文件FreeRTOSConfig h 设置configUSE MUTEXES 为1 互斥量和信号量的主要区别如下 互斥量用于保护资源时必须要被返还 信号量用于数据同步时不需
  • 完爆面试官!spring可能带来的一个深坑

    4步套路 xff0c 解决动态规划问题 1 确定问题状态 提炼最后一步的问题转化 2 转移方程 xff0c 把问题方程化 3 按照实际逻辑设置初始条件和边界情况 4 确定计算顺序并求解 结合实例感受下 xff1a 你有三种硬币 xff0c
  • 树莓派Raspberry Pi 2B在Kali上使用TightVNCServer灰屏

    1 将 root vnc xstartup改为 span class token shebang important bin sh span unset SESSION MANAGER unset DBUS SESSION BUS ADDR
  • STM32——UCOSIII 简介

    目录 UCOSIII简介 UCOSIII中的任务 组成 任务堆栈 任务控制块 任务函数 任务函数模板 UCOSIII系统任务 组成 空闲任务 时钟节拍任务 统计任务 定时任务 中断服务管理任务 UCOSIII任务状态 组成及状态概念 UCO
  • ARM —— 寄存器的封装

    目录 SFR 直接一对一封装 结构体封装寄存器 SFR 全称 xff1a 特殊功能寄存器 xff08 Special Function Register xff09 作用 xff1a 用于 控制片内外设 xff0c 存放 相应功能部件的 控
  • Ubuntu给Pix2.4.8刷Ardupilot固件

    全文基于waf编译器使用 waf命令 xff0c APM官网对于waf的使用描述 xff1a https github com ArduPilot ardupilot blob master BUILD md 前提 xff1a 已经在ubu
  • 程序猿面试经验总结(经验篇)

    开篇序 金九银十大家都知道吧 xff0c 的确九十月份都是跳槽旺季与招聘旺季 xff0c 无论是找工作的 招聘的单位都是特别特别的多 xff0c 多的你有时候看都看不过来 xff0c 以至于让你有时候很难选择 xff0c 其实选择对应自己的
  • STM32 HAL库和标准库的原理区别

    STM32 HAL库和标准库的原理区别 HAL简介 HAL库 xff0c HAL是Hardware Abstraction Layer的缩写 xff0c 中文名称是 xff1a 硬件抽象层 xff0c 是st公司为了更方便地进行stm32之
  • 【超详细~】js的三大定时器:setTimeout、setInterval、requestAnimationFrame

    setTimeout xff08 表达式 xff0c 时间 xff09 61 gt 是指延迟指定时间后才调用函数 xff0c 调用次数仅一次 xff1b setInterval xff08 表达式 xff0c 时间 xff09 61 gt
  • FreeRTOS的学习(一)——实时操作系统和多任务的介绍

    目录 1 初识FreeRTOS 2 FreeRTOS 任务的状态 3 FreeRTOS 的任务 任务的创建和删除 1 xTaskCreate xff1a 使用静态的方法创建一个任务 2 xTaskCreateStatic xff1a 使用静
  • FreeRTOS的学习(四)—— 信号量之间的优先级翻转问题和互斥信号量

    目录 优先级翻转现象 什么是优先级翻转 互斥信号量 1 互斥信号量简介 2 创建互斥信号量 1 函数 xSemaphoreCreateMutex 2 函数 xSemaphoreCreateMutexStatic 3 释放互斥信号量 4 获取
  • STC15单片机 固定翼无人机/航模 飞控程序

    stc15单片机 固定翼无人机 飞控程序 硬件 stcf2k60s22 4g无线通信模块nrf24l01mg90s数字舵机摇杆无刷电机电调 用到的单片机资源 pwmad转换 程序结构 利用ADC转换读取摇杆值将摇杆数值转换为16进制通过2