四旋翼无人机光流定位原代码:
通常,我们购买以下光流模块GL9306

串口输出模块光流数据,格式如下:
串口读取代码如下:
#include "usart.h"
// 改写光流定位 串口通讯 // 接线方式 光流模块TX - stm32 PA10 RX void USART1_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure1; USART_InitTypeDef USART_InitStructure1; NVIC_InitTypeDef NVIC_InitStructure1; /* 配置串口1 (USART1) 时钟*/
/*" 第1步:打开GPIO和USART部件的时钟 "*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );//| RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* Configure the NVIC Preemption Priority Bits */
/* 中断串口1 */ NVIC_InitStructure1.NVIC_IRQChannel = USART1_IRQn; //USART1 串口1全局中断 NVIC_InitStructure1.NVIC_IRQChannelPreemptionPriority = 1.//抢占优先级1 NVIC_InitStructure1.NVIC_IRQChannelSubPriority = 1; //子优先级1 /*IRQ通道使能*/ NVIC_InitStructure1.NVIC_IRQChannelCmd = ENABLE; /*根据NVIC_InitStruct初始化外设中指定的参数NVIC寄存器USART1*/ NVIC_Init(&NVIC_InitStructure1);
/*串口GPIO端口配置*/ /* 配置串口1 (USART1 Tx (PA.09))*/ GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure1); /* 配置串口1 USART1 Rx (PA.10)*/ GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure1); //USART 初始化设置 USART_InitStructure1.USART_BaudRate =19200./串口波特率 USART_InitStructure1.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure1.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure1.USART_Parity = USART_Parity_No;///无奇偶校准位 USART_InitStructure1.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure1.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure1); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//打开中断 USART_Cmd(USART1, ENABLE); //使能串口 }
/**************************实现函数********************************************** *功 能: usart发送一个字节 *********************************************************************************/ void usart1_send(u8 data) {
USART1->DR = data; while((USART1->SR&0x40)==0); } /************************************************************************** 函数功能:串口1初始化 入口参数:pclk2:PCLK2 时钟频率(Mhz) bound:波特率 返回 值:无 **************************************************************************/ void uart1_init(u32pclk2,u32 bound) { float temp; u16 mantissa; u16 fraction; temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; RCC->APB2ENR|=1<<0; //开启辅助时钟 RCC->APB2ENR|=1<<3; //使能PORTB口时钟 RCC->APB1ENR|=1<<18; //使能串口时钟 GPIOB->CRH&=0XFFFF0FFF; GPIOB->CRH|=0X00008000;//IO状态设置 GPIOB->ODR|=1<<10;
RCC->APB1RSTR|=1<<18; //复位串口1 RCC->APB1RSTR&=~(1<<18);//停止复位 //波特率设置 USART1->BRR=mantissa; // 波特率设置 USART1->CR1|=0X200C; //1位停止,无校验位. //使能接收中断 USART1->CR1|=1<<8; //PE中断使能 USART1->CR1|=1<<5; //接收缓冲区非空中断使能 // MY_NVIC_Init(0,0,USART1_IRQn,1);//组2,最低优先级 }
/************************************************************************** 函数功能:串口3接收中断 入口参数:无 返回 值:无 **************************************************************************/ int USART1_IRQHandler(void) { static u8 RxBuffer[32]; static u8 _data_cnt = 0; static u8 state = 0; u8 data; u8 sum = 0; if(USART1->SR&(1<<5))//接收到数据 { USART1->SR&=~(1<<0);//清除中断标志位 data=USART1->DR; switch(state) {
case 0: if(data==0xFE) {
state=1; RxBuffer[_data_cnt++]=data; }else state = 0; break; case 1: if(data==0x04) {
state=2; RxBuffer[_data_cnt++]=data; }else state = 0; break; case 2: RxBuffer[_data_cnt++]=data; if(_data_cnt==9) {
state = 0; _data_cnt = 0; sum = (RxBuffer[2] + RxBuffer[3] + RxBuffer[4] + RxBuffer[5]); if((0xAA == data) && (sum == RxBuffer[6])) //和校验 {
count_temp++; //读原始数据 Flow_Pitch = ( (s16)(*(RxBuffer+3)<<8)|*(RxBuffer+2) ); Flow_Roll = ( (s16)(*(RxBuffer+5)<<8)|*(RxBuffer+4) ); //累积求位移 Flow_Pitch_i += Flow_Pitch; Flow_Roll_i += Flow_Roll; if(count_temp>400) { Flag_USART3=1; X_Flow_Pitch_i+= Flow_Pitch_i/(8200.0f/(this_Final_Distance*1.0f));//this_Final_Distance为实际高度 Y_Flow_Roll_i += Flow_Roll_i /(8200.0f/(this_Final_Distance*1.0f));//this_Final_Distance为实际高度 Flow_Pitch_i=0;//使用完后清零,防止高度提升时位移发生变化 Flow_Roll_i =0;//使用完后清零,防止高度提升时位移发生变化 } } } break; default: state = 0; _data_cnt = 0; break; }
} return 0; }
//