这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【更新四轴姿态解算知识储备】snake0301四轴飞行器进程

共161条 4/17 |‹ 2 3 4 5 6 7 ›| 跳转至
高工
2014-04-03 12:52:42     打赏
31楼

所言极是,能把51的资源用尽也是一代高手

 我准备后期在遥控器上扩展一个LCD 

 到时候字库、图案库啥的一上 不知道够不够啊

 肤浅理解啊


高工
2014-04-03 16:56:45     打赏
32楼

NRF24L01发送实验

相对比较顺利

接收实验倒腾了一晚上

发现连NRF24L01都检测不到

怀疑是管脚配置有问题

详情:http://forum.eepw.com.cn/thread/249476/1

欢迎各路大神来喷


NRF24L01的控制字不少

其实这个实验用到的并不多


/*******************************************************/
#define TX_ADDR_WITDH 5//发送地址宽度设置为5个字节
#define RX_ADDR_WITDH 5//接收地址宽度设置为5个字节
#define TX_DATA_WITDH 4//发送数据宽度1个字节
#define RX_DATA_WITDH 4//接收数据宽度1个字节
/*******************命令寄存器***************************/
#define  R_REGISTER      0x00//读取配置寄存器
#define  W_REGISTER      0x20//写配置寄存器
#define  R_RX_PAYLOAD 0x61//读取RX有效数据
#define  W_TX_PAYLOAD 0xa0//写TX有效数据
#define  FLUSH_TX 0xe1//清除TXFIFO寄存器
#define  FLUSH_RX 0xe2//清除RXFIFO寄存器
#define  REUSE_TX_PL     0xe3//重新使用上一包有效数据
#define  NOP             0xff//空操作
/******************寄存器地址****************************/
#define  CONFIG          0x00//配置寄存器
#define  EN_AA 0x01//使能自动应答
#define  EN_RXADDR       0x02//接收通道使能0-5个通道
#define  SETUP_AW        0x03//设置数据通道地址宽度3-5
#define  SETUP_RETR      0x04//建立自动重发
#define  RF_CH           0x05//射频通道设置
#define  RF_SETUP        0x06//射频寄存器
#define  STATUS          0x07//状态寄存器
#define  OBSERVE_TX      0x08//发送检测寄存器
#define  CD              0x09//载波
#define  RX_ADDR_P0      0x0a//数据通道0接收地址
#define  RX_ADDR_P1      0x0b//数据通道1接收地址
#define  RX_ADDR_P2      0x0c//数据通道2接收地址
#define  RX_ADDR_P3      0x0d//数据通道3接收地址
#define  RX_ADDR_P4      0x0e//数据通道4接收地址
#define  RX_ADDR_P5      0x0f//数据通道5接收地址
#define  TX_ADDR         0x10//发送地址
#define  RX_PW_P0        0x11//P0通道数据宽度设置
#define  RX_PW_P1        0x12//P1通道数据宽度设置
#define  RX_PW_P2        0x13//P2通道数据宽度设置
#define  RX_PW_P3        0x14//P3通道数据宽度设置
#define  RX_PW_P4        0x15//P4通道数据宽度设置
#define  RX_PW_P5        0x16//P5通道数据宽度设置
#define  FIFO_STATUS     0x17//FIFO状态寄存器

 

SPI1的配置


比较常规,可以参考数据手册和函数说明


void SPI1_Config(void)
{ SPI_InitTypeDef SPI_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);                //使能SPI1时钟
    
    /*  配置SPI1的复用GPIO  */
      //  PA5--CLK PA7--MOSI  复用推挽输入
    
      GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_5|GPIO_Pin_7; 
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
      //PA6--MISO  输入浮空
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /*PB2--CE    PA1--NSS   (GPIOA1驱动CSN) */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_2; 
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
    GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
 
 /*PA3--IRQ      */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;  
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
 SPI1_CE_LOW();
   SPI1_NRF_CSN_HIGH();//拉高CSN 失能片选
    
    /*  配置SPI1模块 初始化*/
                                     //声明用来初始化的结构体
      SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工
      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                     //主模式
      SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                  //一次传输8位
      SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                        //空闲电平低电平
      SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                      //第一个上升沿采样
      SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                         //NSS管理为软件件模式
      SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8; //波特率预分频8  9MHz
      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;       //数据传输低位在前
      SPI_InitStructure.SPI_CRCPolynomial = 7;                           //CRC校验方式
    SPI_Init(SPI1, &SPI_InitStructure);                                  //初始化
    
   // SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
    
  
    SPI_Cmd(SPI1, ENABLE); //使能SPI1
}//SPI1_Config()

 

然后是NRF24L01的一系列子函数


这块片子其实比较傻瓜

通信过程全部硬件实现了

仅仅需要进行控制和读写


/*************************************************************
**函数名: SPI_RW_Byte(SPI_TypeDef* SPIx,unsigned char Byte);
**描述  :   SPI写Byte
**参数  : 
**返回值: u8 STATUS寄存器的内容
**注意  :         
************************************************************/
u8 SPI_RW_Byte(SPI_TypeDef* SPIx,unsigned char Byte)
{
      while( SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);  //查发送缓冲器是否为空,空即可以发送
      SPI_I2S_SendData(SPIx, Byte);   //库函数:发送一个字节
      //当SPI接收缓冲器为空时等待
      while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
   return SPI_I2S_ReceiveData(SPIx);
}//SPI_RW_Byte()

/*************************************************************
**函数名: SPI_NRF_Write(char CMD,char* WBuff,char ByteNUM);
**描述  :   SPI1写NRF
**参数  : 
**返回值: u8 STATUS
**注意  :         
************************************************************/
u8 SPI_NRF_Write(SPI_TypeDef* SPIx,char CMD,unsigned char* WBuff,unsigned char ByteNUM)
{
 unsigned char i,status; 
 SPI1_CE_LOW();
 SPI1_NRF_CSN_LOW();//使能片选
 
 status=SPI_RW_Byte( SPIx , CMD);
 for(i=0;i<ByteNUM;i++)
 {
     SPI_RW_Byte( SPIx,*WBuff++);
   // printf("写入第%d个数据\r\n",ByteNUM);   
 }
 SPI1_NRF_CSN_HIGH();//
 return status;
}//SPI_NRF_Write()

/*************************************************************
**函数名: SPI_NRF_Read(SPI_TypeDef* SPIx,char CMD,char* RBuff,char ByteNUM);
**描述  :   SPI1写NRF
**参数  : 
**返回值: u8 status
**注意  :         
************************************************************/
u8 SPI_NRF_Read(SPI_TypeDef* SPIx,char CMD,unsigned char* RBuff,unsigned char ByteNUM)
{
 unsigned char i,status;
  
 SPI1_CE_LOW();
 SPI1_NRF_CSN_LOW(); 
 status=SPI_RW_Byte( SPIx , CMD);
 for(i=0;i< ByteNUM ;i++)
 {    
     RBuff[i]=SPI_RW_Byte(SPIx,NOP);          // 取接收缓冲器,一个字节
    //printf("读出第%d个数据\r\n",ByteNUM);   
 }
  
 
 SPI1_NRF_CSN_HIGH(); 
 return status; 
}//SPI_NRF_Read()

/*************************************************************
**函数名: SPI_NRF_MOD_TX()
**描述  :   配置NRF进入 发送模式 
**参数  :
**返回值: 
**注意  :  仅用于测试 无参无返  可改成带配置参数的模块函数
   Tx通道0 地址TX_ADDR=0x05B6B5B4B3
************************************************************/
void SPI_NRF_MOD_TX(void)
{
    u8 TX_Array[5];
 u8 _TX_RX_ADDR_[5]={0xB3,0xB4,0xB5,0xB6,0x05};
  
 SPI1_CE_LOW();//CE=0 待机模式 
  TX_Array[0]=0x03;//设置地址宽度 11--5字节 10--4字节 01-3字节 00--不合法
 SPI_NRF_Write(SPI1,W_REGISTER+SETUP_AW,TX_Array,1); 
  TX_Array[0]=0xf3;//建立自动重发 间隔‘1111‘--等待4000+86us   15次
 SPI_NRF_Write(SPI1,W_REGISTER+SETUP_RETR,TX_Array,1); 
  TX_Array[0]=0x02;//射频通道 X000 0010
 SPI_NRF_Write(SPI1,W_REGISTER+RF_CH,TX_Array,1);
  TX_Array[0]=0x0f;//射频参数寄存器 0000 1111 2Mbps 发射功率 00-18dBm 01-12dBm 10-6dBm 11-0dBm  1--低噪声放大器增益
 SPI_NRF_Write(SPI1,W_REGISTER+RF_SETUP,TX_Array,1);
  TX_Array[0]=0x3f;//xx11 1111 0-5接收通道允许 
 SPI_NRF_Write(SPI1,W_REGISTER+EN_RXADDR,TX_Array,1);
  TX_Array[0]=0x3f;//xx11 1111 0-5通道允许自动应答
 SPI_NRF_Write(SPI1,W_REGISTER+EN_AA,TX_Array,1); 
   
 
 SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
 SPI_NRF_Write(SPI1,W_REGISTER+RX_ADDR_P0,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
 
 
 TX_Array[0]=0x0e;//中断全开 发送模式 PRIM_RX=0 PWR_UP=1 
 SPI_NRF_Write(SPI1,W_REGISTER+CONFIG,TX_Array,1);
 
 TX_Array[0]=0xfe;//1111 xxxx STATUS寄存器 写‘1’清除所有标志
 SPI_NRF_Write(SPI1,W_REGISTER+STATUS,TX_Array,1);
 
 SPI1_CE_HIGH();//CE=1 使能发射模式 
 delay_us(100);//CE拉高需要一定的延时才能进行发送 延时之后 即可通过SPI接口发送TX_PLD
}
/*************************************************************
**函数名: SPI_NRF_MOD_RX()
**描述  :   配置NRF进入 接收模式 
**参数  :
**返回值: 
**注意  :  仅用于测试 无参无返  可改成带配置参数的模块函数
   RX通道0 地址TX_ADDR=0xB3B4B5B605
************************************************************/
void SPI_NRF_MOD_RX(void)
{
    u8 TX_Array[5];
 u8 _TX_RX_ADDR_[5]={0xB3,0xB4,0xB5,0xB6,0x05};
 
 SPI1_CE_LOW();//CE=0 待机模式 
  TX_Array[0]=0x03;//允许接收通道0000 0011
 SPI_NRF_Write(SPI1,W_REGISTER+EN_RXADDR,TX_Array,1);
  TX_Array[0]=0x03;//设置地址宽度 11--5字节 10--4字节 01-3字节 00--不合法
 SPI_NRF_Write(SPI1,W_REGISTER+SETUP_AW,TX_Array,1); 
  TX_Array[0]=0x20;//射频通道 X000 0010
 SPI_NRF_Write(SPI1,W_REGISTER+RF_CH,TX_Array,1);
  TX_Array[0]=0x0f;//射频参数寄存器 0000 1111 2Mbps 发射功率 00-18dBm 01-12dBm 10-6dBm 11-0dBm  1--低噪声放大器增益
 SPI_NRF_Write(SPI1,W_REGISTER+RF_SETUP,TX_Array,1);
  TX_Array[0]=0x3f;//xx11 1111 0-5通道允许自动应答
 SPI_NRF_Write(SPI1,W_REGISTER+EN_AA,TX_Array,1); 
  TX_Array[0]=0x04;//xx11 1111 数据通道0 有效数据宽度 (1-32)字节
 SPI_NRF_Write(SPI1,W_REGISTER+RX_PW_P0,TX_Array,1);
  TX_Array[0]=0xfe;//1111 xxxx STATUS寄存器 写‘1’清除所有标志
 SPI_NRF_Write(SPI1,W_REGISTER+STATUS,TX_Array,1);
 
 SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
 SPI_NRF_Write(SPI1,W_REGISTER+RX_ADDR_P0,_TX_RX_ADDR_,5);//写入接收发送数据的地址,这个地址是接收端收件的凭证
 
 
 
 TX_Array[0]=0x0f;//接收模式 PRIM_RX=1 PWR_UP=1 允许接收终端
 SPI_NRF_Write(SPI1,W_REGISTER+CONFIG,TX_Array,1);
 
 SPI1_CE_HIGH();//CE=1 使能发射模式 
 delay_us(100);//CE拉高需要一定的延时才能进行发送 延时之后 即可通过SPI接口发送TX_PLD
 //轮询中断24L01中断的到来 NRF_Read_IRQ()
}

/*************************************************************
**函数名: SPI_NRF_TX_DATAS()
**描述  :   配置NRF发送 数据
**参数  : TBuff[ByteNUM] ByteNUM
**返回值: ErrorStatus
**注意  :   
************************************************************/
ErrorStatus SPI_NRF_TX_DATAS(u8* TBuff,u8 ByteNUM)
{ 
   u8 Status[1];
 do{
  SPI1_CE_LOW();//拉低待机
   SPI_NRF_Write(SPI1,W_TX_PAYLOAD,TBuff,ByteNUM);//发送TBuff数组
  SPI1_CE_HIGH();//拉低待机
   }
	 while(NRF_Read_IRQ()!=0);//中断产生时,IRQ引脚低电平
 SPI_NRF_Write(SPI1, FLUSH_TX,TBuff,0);
 SPI1_CE_LOW();//拉低待机
 delay_us(100);
 SPI_NRF_Read(SPI1,R_REGISTER+STATUS,Status,1);//读取Status
 if(Status[0]&0x10)
 {
  Status[0]&=0x10;
  SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);// 
  printf("Tx Error!\r\n");//重发超时 发送失败
  return ERROR;
 }
 else
 {
  Status[0]&=0x20;
  SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);// 
  printf("Tx Success\r\n");//发送成功
  return SUCCESS;
 }
}
/*************************************************************
**函数名: SPI_NRF_RX_DATAS()
**描述  :   配置NRF发送 数据
**参数  : RBuff[ByteNUM] ByteNUM
**返回值: ErrorStatus
**注意  :   
************************************************************/
ErrorStatus SPI_NRF_RX_DATAS(u8* RBuff)
{
   ErrorStatus RX_Status=SUCCESS;
    u8 Status[1];
 while(NRF_Read_IRQ()!=0);//中断产生时,IRQ引脚低电平
 SPI1_CE_LOW();//拉低待机,才能操作寄存器
 delay_us(100);
 SPI_NRF_Read(SPI1,R_REGISTER+STATUS,Status,1);//读取Status
 switch(Status[0]&0x0e) 
 {
 case 0x0e: RX_Status=ERROR; break; //RX_FIFO 空
 default : printf("Rx Success!\r\n");//RX_FIFO非空
    break;
 /*  
 case 0x00: break; //通道0
 case 0x02: break; //通道1
 case 0x04: break; //通道2
 case 0x06: break; //通道3
 case 0x08: break; //通道4
 case 0x0A: break; //通道5*/
 }
 
 SPI_NRF_Read(SPI1,R_RX_PAYLOAD,RBuff,4);//读RX_FIFO
 SPI_NRF_Write(SPI1,W_REGISTER+STATUS,Status,1);//处理状态寄存器标志
 return RX_Status;
}

/*************************************************************
**函数名: NRF_Check
**描述  :   检测器件
**参数  : 
**返回值: 0:正常,1:有误
**注意  :   
************************************************************/
u8 NRF_Check(void)
{
	u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
	u8 i;   	 
	SPI_NRF_Write(SPI1,W_REGISTER+TX_ADDR,buf,5);
	SPI_NRF_Read(SPI1,TX_ADDR,buf,5); 
	for(i=0;i<5;i++)
  if(buf[i]!=0XA5)
		break;	 							   
	if(i!=5)
		return 1;//检测有误
	return 0;		 //检测无误
}	 

 

还是把USART1初始化了一下


方便调试


/*************************************************************
**函数名: usart_Configuration()
**描述  :   配置USART1
**参数  : 
**返回值: 
**注意  :   
************************************************************/
void usart_Configuration()
{
	USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* PA10 USART1_Rx  */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* USARTx configured as follow:
        - BaudRate = 115200 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;     
    USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;      
    USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;      
    USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
    USART_ClockInit(USART1, &USART_ClockInitStructure);
  USART_Init(USART1, &USART_InitStructure);
  USART_Cmd(USART1, ENABLE);
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
 USART_Cmd(USART1, ENABLE);
 
  /* Configure four bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  /* Enable the USART1 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

 

看看主函数的内容


其实就是USAT1、SPI1初始化

检测NRF24L01的在线情况

然后进入一个数据发送的无条件循环


	usart_Configuration();
  printf("USART1测试成功!!!!!\r\n");
	SPI1_Config();
	printf("SPI初始化成功!!!!!!\r\n");
	while(NRF_Check());
	printf("NRF2401正常在线!!!!\r\n");
	SPI_NRF_MOD_TX();
  printf("NRF2401发送模式!!!!\r\n");
	while(1)
	{
		Errcode = SPI_NRF_TX_DATAS(Tx_buf,5);	
		SPI_RW_Byte(SPI1,FLUSH_TX);//清空FIFO
		LED_On;
    if(Errcode == 1)		
		{printf("Yeah,All Data TXed\r\n");}
		else
		{printf("Shit,All Data can not TX\r\n");}
		LED_Off;
		delay_ms(2500);
	}

 

看看视频:



视频地址:http://player.youku.com/player.php/sid/XNjkzNzMxMDIw/v.swf











工程师
2014-04-04 07:49:32     打赏
33楼
要看最新版的原理图

工程师
2014-04-04 07:51:56     打赏
34楼
COOL!加精华,你这个贴子是代码量最多的贴子,继续吧,有空我传一些相关的教程上来。

高工
2014-04-05 20:47:17     打赏
35楼

五年前的cp2102,usb to uart终于寿终正寝了(个人判断,求大神科普)。

只要一接收数据或者发送数据就出现code 22错误,更换各种串口工具也不能解决(个人判断,求大神科普),不会是电脑的u口出问题了吧?

不好调试了,果断淘宝,入手传说中最稳定的ft系列。

千万不要是电脑嗝屁了啊......


专家
2014-04-09 10:10:07     打赏
36楼
关注

工程师
2014-04-09 19:43:27     打赏
37楼
支持一下,学习

工程师
2014-04-10 21:05:58     打赏
38楼
试试看

院士
2014-04-13 17:17:19     打赏
39楼

源代码 源代码~~

coding coding~~


生命不息,代码不止。

楼主 期待 code updating


高工
2014-04-13 21:07:42     打赏
40楼
大神也来一发哈

共161条 4/17 |‹ 2 3 4 5 6 7 ›| 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]