打印
[四轴原创DIY]

召集小伙伴们DIY自己的微型四轴飞行器(STM32主控)

[复制链接]
楼主: mohanwei
手机看帖
扫描二维码
随时随地手机跟帖
61
mohanwei 发表于 2014-12-4 20:44
这几天基本忙完一个通信板,利用晚上的时间搞了一下软件移植,基于这个版本“bitcraze-crazyflie-firmware- ...

去下载最新的好了
我有个移植到keil编译的版本,不过连接PC端有问题
我把CF移植到烈火的小四轴上了,不过控制没用CF的那一套,用的独立遥控器

使用特权

评论回复
62
mohanwei|  楼主 | 2014-12-4 21:03 | 只看该作者
代码改动需求:
1-IO根据我们的新硬件重新配置,要集中到独立的文件“GPIO_Config.c/h”里,而不是像原版那样分散隐藏到很多个文件里(检查、移植都很不方便)
2-不必要的功能删掉,如低功耗管理(这份代码里其实也没有实现)
3-MPU6050(I2C接口)换成BMX055(SPI接口)
4-I2C接口改为IO模拟方式(目前就气压传感器MS5611和温湿度传感器SHTXX,都是可有可无的,速度也要求很低)
5-原版固定频点固定RF地址的nRF24L01驱动(两人一起玩就呵呵了),要改成BK2423(能兼容nRF24L01,功率正常模式最高5dBm,未公开的高功率模式记得是14dBm),带RF地址分配、跳频、多机自组网的协议栈——好在公司有现成的,最多允许16个玩家一起组网玩
6-通信协议要改一下,以适应现有的遥控器
7-参数要加入读写功能,还要能通过无线访问,加入自检、自校准等功能——总之就是当一个正规产品来开发。过程会漫长一点,但学到的东西在工作中能用的上(要玩的话,淘宝两百多块就能搞到一套开箱即玩了)
8- …………

使用特权

评论回复
63
mohanwei|  楼主 | 2014-12-4 21:09 | 只看该作者
wwfiney 发表于 2014-12-4 20:47
去下载最新的好了
我有个移植到keil编译的版本,不过连接PC端有问题
我把CF移植到烈火的小四轴上了,不过 ...

实际使用是遥控器比较方便
接PC主要是调试时分析数据、优化所用吧
只要在通信协议里有控制命令(通过遥控器、PC发出)和调参指令(PC)就可以了,飞机不用关心到底是谁连接了自己

使用特权

评论回复
64
mohanwei|  楼主 | 2014-12-4 21:14 | 只看该作者
改一点贴一点:
IO配置和初始化
说明一下,我比较喜欢这种风格,毕竟一个小MCU,用到的管脚几个到几十个不等,集中到一个地方,只需要对照着原理图很轻松就可以检查一遍;移植起来也很轻松。
GPIO.Config.h

#ifndef _GPIO_Config_h_
#define _GPIO_Config_h_

        ///USB:
        #define Port_USB_DM                        GPIOA
        #define  Pin_USB_DM                        GPIO_Pin_11
        #define Port_USB_DP                        GPIOA
        #define  Pin_USB_DP                        GPIO_Pin_12
        //USB_EN:
        #define Port_USB_EN                        GPIOC
        #define  Pin_USB_EN                        GPIO_Pin_11

        ///Uart1:
        #define Port_TXD1                        GPIOA
        #define  Pin_TXD1                        GPIO_Pin_9
        #define Port_RXD1                        GPIOA
        #define  Pin_RXD1                        GPIO_Pin_10

        ///Uart2:
        #define Port_TXD2                        GPIOA
        #define  Pin_TXD2                        GPIO_Pin_2
        #define Port_RXD2                        GPIOA
        #define  Pin_RXD2                        GPIO_Pin_3

        ///SPI1:接2.4G模块BK2423(兼容nRF24L01)
        #define Port_SPI1                        GPIOA
        #define  Pin_SPI1                        (GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)

        #define Port_BK2423_CS                GPIOA
        #define  Pin_BK2423_CS                GPIO_Pin_4
        #define _CLR_BK2423_CS                GPIO_ResetBits(Port_BK2423_CS, Pin_BK2423_CS)
        #define _SET_BK2423_CS                  GPIO_SetBits(Port_BK2423_CS, Pin_BK2423_CS)

        #define Port_BK2423_CE                GPIOC
        #define  Pin_BK2423_CE                GPIO_Pin_5       
        #define _CLR_BK2423_CE                GPIO_ResetBits(Port_BK2423_CE, Pin_BK2423_CE)
        #define _SET_BK2423_CE                  GPIO_SetBits(Port_BK2423_CE, Pin_BK2423_CE)

        ///SPI2:接IMU传感器模组
        #define Port_SPI2                        GPIOB
        #define  Pin_SPI2                        (GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15)
        //陀螺仪SPI口片选:
        #define Port_Gyro_CS                GPIOA
        #define  Pin_Gyro_CS                GPIO_Pin_8
        #define _CLR_Gyro_CS                GPIO_ResetBits(Port_Gyro_CS, Pin_Gyro_CS)
        #define _SET_Gyro_CS                  GPIO_SetBits(Port_Gyro_CS, Pin_Gyro_CS)
        //地磁传感器SPI口片选:
        #define Port_Magnet_CS                GPIOC
        #define  Pin_Magnet_CS                GPIO_Pin_9
        #define _CLR_Magnet_CS                GPIO_ResetBits(Port_Magnet_CS, Pin_Magnet_CS)
        #define _SET_Magnet_CS                  GPIO_SetBits(Port_Magnet_CS, Pin_Magnet_CS)
        //三轴加速度传感器SPI口片选:
        #define Port_Accel_CS                GPIOC
        #define  Pin_Accel_CS                GPIO_Pin_10
        #define _CLR_Accel_CS                GPIO_ResetBits(Port_Accel_CS, Pin_Accel_CS)
        #define _SET_Accel_CS                  GPIO_SetBits(Port_Accel_CS, Pin_Accel_CS)

        ///SPI3:接SPI接口Flash或SD卡
        #define Port_SPI3                        GPIOB
        #define  Pin_SPI3                        (GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5)

        #define Port_SD_CS                        GPIOA
        #define  Pin_SD_CS                        GPIO_Pin_15
        #define _CLR_SD_CS                        GPIO_ResetBits(Port_SD_CS, Pin_SD_CS)
        #define _SET_SD_CS                          GPIO_SetBits(Port_SD_CS, Pin_SD_CS)

        ///I2C:(STM32的I2C靠不住,所以用IO模拟)
        #define Port_SCL1                        GPIOC
        #define  Pin_SCL1                        GPIO_Pin_6
        #define Port_SDA1                        GPIOB
        #define  Pin_SDA1                        GPIO_Pin_12
        #define Clr_SCL_1()                        GPIO_ResetBits(Port_SCL1, Pin_SCL1)
        #define Set_SCL_1()                          GPIO_SetBits(Port_SCL1, Pin_SCL1)
        #define Clr_SDA_1()                        GPIO_ResetBits(Port_SDA1, Pin_SDA1)
        #define Set_SDA_1()                          GPIO_SetBits(Port_SDA1, Pin_SDA1)

        ///4路空心杯电机:(分配到定时器输出管脚,都是输出高电平有效)
        //TIM3CH4
        #define Port_Moto1                        GPIOB
        #define  Pin_Moto1                        GPIO_Pin_1
        //TIM3CH3       
        #define Port_Moto2                        GPIOB
        #define  Pin_Moto2                        GPIO_Pin_0
        //TIM4CH4
        #define Port_Moto3                        GPIOB
        #define  Pin_Moto3                        GPIO_Pin_9
        //TIM4CH3
        #define Port_Moto4                        GPIOB
        #define  Pin_Moto4                        GPIO_Pin_8

        //按键1:和串口2的RXD2共用
        #define Port_Key1                        Port_RXD2
        #define  Pin_Key1                        Pin_RXD2
        //按键2:本版未接(空间太小,不好走线)
        #define Port_Key2                        GPIOC
        #define  Pin_Key2                        GPIO_Pin_14

        //4个LED,和电机一一对应
        #define Port_LED1                        GPIOA
        #define  Pin_LED1                        GPIO_Pin_0
        #define Port_LED2                        GPIOC
        #define  Pin_LED2                        GPIO_Pin_7
        #define Port_LED3                        GPIOC
        #define  Pin_LED3                        GPIO_Pin_12
        #define Port_LED4                        GPIOA
        #define  Pin_LED4                        GPIO_Pin_1
        //绿色LED:(原板是PB5,临时用我们的LED1顶替)
        #define Port_LED_GREEN                Port_LED1
        #define  Pin_LED_GREEN                Pin_LED1
        #define _GREEN_LED_ON                GPIO_ResetBits(Port_LED_GREEN, Pin_LED_GREEN);
        #define _GREEN_LED_OFF                  GPIO_SetBits(Port_LED_GREEN, Pin_LED_GREEN);
        //红色LED:(原板是PB4,临时用我们的LED2顶替)
        #define Port_LED_RED                Port_LED2
        #define  Pin_LED_RED                Pin_LED2
        #define _RED_LED_ON                        GPIO_ResetBits(Port_LED_RED, Pin_LED_RED);
        #define _RED_LED_OFF                  GPIO_SetBits(Port_LED_RED, Pin_LED_RED);

        //蜂鸣器
        #define Port_BEEP                        GPIOC
        #define  Pin_BEEP                        GPIO_Pin_13


        ///测量电池电压ADC通道:(原板是PB1)
        #define Port_VBat                        GPIOC
        #define  Pin_VBat                        GPIO_Pin_4
        ///测量电机电流ADC通道:(原板没有)
        #define Port_IFB1                        GPIOC
        #define  Pin_IFB1                        GPIO_Pin_3
        #define Port_IFB2                        GPIOC
        #define  Pin_IFB2                        GPIO_Pin_1
        #define Port_IFB3                        GPIOC
        #define  Pin_IFB3                        GPIO_Pin_0
        #define Port_IFB4                        GPIOC
        #define  Pin_IFB4                        GPIO_Pin_2

       
        //原版有一些电源管理相关引脚,我们这个板没有。
        //但MCU有很多空脚,所以可以随便定义一下,避免过多更改程序:
        //控制单键电子开关:
        #define PM_GPIO_SYSOFF_PORT     GPIOB//GPIOA
        #define PM_GPIO_SYSOFF          GPIO_Pin_10//GPIO_Pin_1
        //BQ24075使能脚1:
        #define PM_GPIO_EN1_PORT        GPIOB
        #define PM_GPIO_EN1             GPIO_Pin_11
        //BQ24075使能脚2:
        #define PM_GPIO_EN2_PORT        GPIOB
        #define PM_GPIO_EN2             GPIO_Pin_6
        //BQ24075充电完成状态指示
        #define PM_GPIO_IN_CHG_PORT     GPIOB
        #define PM_GPIO_IN_CHG          GPIO_Pin_7
        //BQ24075输出良好指示
        #define PM_GPIO_IN_PGOOD_PORT   GPIOD
        #define PM_GPIO_IN_PGOOD        GPIO_Pin_2
       
        //锂电测量:(原版分压1/3,我们分压1/2) 前面已经定义了ADC_BAT(PC4)
//        #define PM_GPIO_BAT_PORT        GPIOA
//        #define PM_GPIO_BAT             GPIO_Pin_3

        void SetGPIO(GPIO_TypeDef *Port,u16 pin,GPIOSpeed_TypeDef speed,GPIOMode_TypeDef mode);//设置GPIO
        extern void GPIO_Configuration(void);//配置所有GPIO

#endif

使用特权

评论回复
65
mohanwei|  楼主 | 2014-12-4 21:19 | 只看该作者
GPIO_Config.c
说明一下,只要能精简代码行数,就值得用一个函数封装一下“重复的轮子”,这里用一个SetGPIO()来代替大片重复的结构体赋值语句(开机就执行一遍,无所谓执行效率了,可读性优先),是不是比库函数看起来清爽了很多?

#include "includes.h"
#include "GPIO_Config.h"

void SetGPIO(GPIO_TypeDef *Port,u16 pin,GPIOSpeed_TypeDef speed,GPIOMode_TypeDef mode)//设置GPIO
{
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = pin;
        GPIO_InitStructure.GPIO_Speed = speed;
        GPIO_InitStructure.GPIO_Mode = mode;
        GPIO_Init(Port, &GPIO_InitStructure);
}

void GPIO_Configuration(void)//配置所有GPIO
{
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//仅使用SWD,释放其他调试口引脚

        ///*************************** 配置USB开始 *******************************
        SetGPIO(Port_USB_DM,        Pin_USB_DM,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_USB_DP,        Pin_USB_DP,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_USB_EN,        Pin_USB_EN,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        ///*************************** 配置USB结束 *******************************
       
        ///*************************** 配置串口1开始 *******************************
        SetGPIO(Port_TXD1,        Pin_TXD1,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_RXD1,        Pin_RXD1,        GPIO_Speed_50MHz,GPIO_Mode_IPU);///输入上拉
        ///*************************** 配置串口0结束 *******************************
       
        ///*************************** 配置串口2开始 *******************************
        SetGPIO(Port_TXD2,        Pin_TXD2,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_RXD2,        Pin_RXD2,        GPIO_Speed_50MHz,GPIO_Mode_IPU);///输入上拉
        ///*************************** 配置串口1结束 *******************************
       
        ///*************************** 配置串口3开始 *******************************
///        SetGPIO(Port_TXD3,        Pin_TXD3,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
///        SetGPIO(Port_RXD3,        Pin_RXD3,        GPIO_Speed_50MHz,GPIO_Mode_IPU);///输入上拉
        ///*************************** 配置串口2结束 *******************************
       
        ///**************************** 配置CAN开始 ********************************
        ///**************************** 配置CAN结束 ********************************
       
        ///**************************** 配置SPI1开始 ********************************
        ///SPI1:接2.4G模块BK2423(兼容nRF24L01)
        GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);
        SPI_I2S_DeInit(SPI1);
        SetGPIO(Port_SPI1,        Pin_SPI1,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_BK2423_CS,        Pin_BK2423_CS,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        SetGPIO(Port_BK2423_CE,        Pin_BK2423_CE,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        //拉高SPI从机片选:
        _SET_BK2423_CS;
       
        Config_SPI(SPI_CPOL_High,SPI_CPHA_2Edge,SPI_BaudRatePrescaler_32);//恢复默认2.25M时钟,BCM5325(摩托3模式)
        ///**************************** 配置SPI1结束 ********************************
       
        ///**************************** 配置SPI2开始 ********************************
        ///SPI2:接IMU传感器模组
        SPI_I2S_DeInit(SPI2);
        SetGPIO(Port_SPI2,        Pin_SPI2,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        //陀螺仪SPI口片选:
        SetGPIO(Port_Gyro_CS,        Pin_Gyro_CS,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        //地磁传感器SPI口片选:
        SetGPIO(Port_Magnet_CS,        Pin_Magnet_CS,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        //三轴加速度传感器SPI口片选:
        SetGPIO(Port_Accel_CS,        Pin_Accel_CS,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        //拉高SPI从机片选:
        _SET_Gyro_CS;
        _SET_Magnet_CS;
        _SET_Accel_CS;
       
        Config_SPI(SPI_CPOL_High,SPI_CPHA_2Edge,SPI_BaudRatePrescaler_32);//恢复默认2.25M时钟,BCM5325(摩托3模式)
        ///**************************** 配置SPI2结束 ********************************
       
        ///**************************** 配置SPI1开始 ********************************
        ///SPI3:接SPI接口Flash或SD卡
        SPI_I2S_DeInit(SPI3);
        SetGPIO(Port_SPI3,        Pin_SPI3,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_SD_CS,        Pin_SD_CS,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
        //拉高SPI从机片选:
        _SET_SD_CS;
       
        Config_SPI(SPI_CPOL_High,SPI_CPHA_2Edge,SPI_BaudRatePrescaler_32);//恢复默认2.25M时钟,BCM5325(摩托3模式)
        ///**************************** 配置SPI1结束 ********************************

        ///************************** 配置I2C接口开始 ******************************
        ///I2C:(STM32的I2C靠不住,所以用IO模拟)
        SetGPIO(Port_SCL1,        Pin_SCL1,        GPIO_Speed_50MHz,GPIO_Mode_Out_OD);
        SetGPIO(Port_SDA1,        Pin_SDA1,        GPIO_Speed_50MHz,GPIO_Mode_Out_OD);
        Set_SDA_1();
    Set_SCL_1();
        ///************************** 配置I2C接口结束 ******************************

        ///************************** 配置PWM接口开始 ******************************
        ///4路空心杯电机:(分配到定时器输出管脚,都是输出高电平有效)
        SetGPIO(Port_Moto1,        Pin_Moto1,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_Moto2,        Pin_Moto2,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_Moto3,        Pin_Moto3,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        SetGPIO(Port_Moto4,        Pin_Moto4,        GPIO_Speed_50MHz,GPIO_Mode_AF_PP);
        ///************************** 配置PWM接口结束 ******************************
       
        ///********************** 配置普通数字输出口开始 ***************************
//        ///外部看门狗喂狗:
//        SetGPIO(Port_WDT,        Pin_WDT,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
//        _SET_WDT;
//        _CLR_WDT;
       
        //4个LED,和电机一一对应
        SetGPIO(Port_LED1,        Pin_LED1,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        SetGPIO(Port_LED2,        Pin_LED2,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        SetGPIO(Port_LED3,        Pin_LED3,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        SetGPIO(Port_LED4,        Pin_LED4,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        //绿色LED:(原板是PB5,临时用我们的LED1顶替)
        SetGPIO(Port_LED_GREEN,        Pin_LED_GREEN,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        //红色LED:(原板是PB4,临时用我们的LED2顶替)
        SetGPIO(Port_LED_RED,        Pin_LED_RED,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        //蜂鸣器
        SetGPIO(Port_BEEP,        Pin_BEEP,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
       
//        ///LED_RUN:
//        SetGPIO(Port_LED_RUN,        Pin_LED_RUN,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
//        ///LED_ALARM:
//        SetGPIO(Port_LED_ALARM,        Pin_LED_ALARM,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
//        ///LED_COMM:
//        SetGPIO(Port_LED_COMM,        Pin_LED_COMM,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);
//        ///LED_BEEP:
//        SetGPIO(Port_LED_BEEP,        Pin_LED_BEEP,        GPIO_Speed_50MHz,GPIO_Mode_Out_PP);

        ///********************** 配置普通数字输出口结束 ***************************
       
        ///********************** 配置普通数字输入口开始 ***************************
        ///********************** 配置普通数字输入口结束 ***************************
       
        ///************************ 配置按键输入口开始 *****************************
        //按键1:和串口2的RXD2共用
        SetGPIO(Port_Key1,        Pin_Key1,        GPIO_Speed_50MHz,GPIO_Mode_IPU);
        //按键2:本版未接(空间太小,不好走线)
        SetGPIO(Port_Key2,        Pin_Key2,        GPIO_Speed_50MHz,GPIO_Mode_IPU);
        ///************************ 配置按键输入口结束 *****************************
       
        ///************************* 配置ADC输入口开始 *****************************
        SetGPIO(Port_VBat,        Pin_VBat,        GPIO_Speed_50MHz,GPIO_Mode_AIN);//电池电压ADC
        SetGPIO(Port_IFB1,        Pin_IFB1,        GPIO_Speed_50MHz,GPIO_Mode_AIN);//电机1电流测量ADC
        SetGPIO(Port_IFB1,        Pin_IFB2,        GPIO_Speed_50MHz,GPIO_Mode_AIN);//电机2电流测量ADC
        SetGPIO(Port_IFB1,        Pin_IFB3,        GPIO_Speed_50MHz,GPIO_Mode_AIN);//电机3电流测量ADC
        SetGPIO(Port_IFB1,        Pin_IFB4,        GPIO_Speed_50MHz,GPIO_Mode_AIN);//电机4电流测量ADC
        ///************************* 配置ADC输入口结束 *****************************
       
        //原版有,这里没有的管脚:随便定义几个空脚
        //控制单键电子开关:
        SetGPIO(PM_GPIO_SYSOFF_PORT,        PM_GPIO_SYSOFF,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
       
        //BQ24075使能脚1:
        SetGPIO(PM_GPIO_EN1_PORT,        PM_GPIO_EN1,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);

        //BQ24075使能脚2:
        SetGPIO(PM_GPIO_EN2_PORT,        PM_GPIO_EN2,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);

        //BQ24075充电完成状态指示
        SetGPIO(PM_GPIO_IN_CHG_PORT,        PM_GPIO_IN_CHG,        GPIO_Speed_2MHz,GPIO_Mode_IPU);

        //BQ24075输出良好指示
        SetGPIO(PM_GPIO_IN_PGOOD_PORT,        PM_GPIO_IN_PGOOD,        GPIO_Speed_2MHz,GPIO_Mode_IN_FLOATING);
       
        //锂电测量:(原版分压1/3,我们分压1/2) 前面已经定义了ADC_BAT(PC4)
//        SetGPIO(PM_GPIO_BAT_PORT,        PM_GPIO_BAT,        GPIO_Speed_10MHz,GPIO_Mode_IN_FLOATING);
}

使用特权

评论回复
66
mohanwei|  楼主 | 2014-12-4 21:25 | 只看该作者
所有用到的外设在初始化时一次性使能时钟,道理同上

static void RCC_Configuration(void)//Clock configuration
{
  ErrorStatus HSEStartUpStatus;

  RCC_DeInit();
  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);
  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

        if (HSEStartUpStatus == SUCCESS)
        {
                /* Enable Prefetch Buffer */
                FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
       
                /* Flash 2 wait state */
                FLASH_SetLatency(FLASH_Latency_2);
       
                /* HCLK = SYSCLK */
                RCC_HCLKConfig(RCC_SYSCLK_Div1);
       
                /* PCLK2 = HCLK */
                RCC_PCLK2Config(RCC_HCLK_Div1);
       
                /* PCLK1 = HCLK/2 */
                RCC_PCLK1Config(RCC_HCLK_Div2);
       
                /* ADCCLK = PCLK2/6 = 72 / 6 = 12 MHz*/
                RCC_ADCCLKConfig(RCC_PCLK2_Div6);
       
                /* PLLCLK = 16MHz/2 * 9 = 72 MHz */
                RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9);
       
                /* Enable PLL */
                RCC_PLLCmd(ENABLE);
       
                /* Wait till PLL is ready */
                while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
       
                /* Select PLL as system clock source */
                RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
       
                /* Wait till PLL is used as system clock source */
                while(RCC_GetSYSCLKSource() != 0x08);
        }
        else
        {
                SetGPIO(Port_LED_GREEN,        Pin_LED_GREEN,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
                SetGPIO(Port_LED_RED,        Pin_LED_RED,        GPIO_Speed_10MHz,GPIO_Mode_Out_PP);
        //        _RED_LED_ON;
                _GREEN_LED_ON;//绿常亮色LED
    //Cannot start xtal oscillator!
    while(1);
  }
       
        // Enable DMA clock
//        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//SPI3的DMA用到了
//        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//SPI1的DMA用到了

        //使能外设时钟
        RCC_APB1PeriphClockCmd(
                RCC_APB1Periph_TIM2|
                RCC_APB1Periph_TIM3|
                RCC_APB1Periph_TIM4|
                RCC_APB1Periph_USART2|
                RCC_APB1Periph_USART3|
                RCC_APB1Periph_SPI2|
                RCC_APB1Periph_SPI3
                , ENABLE);
        //使能外设时钟
        RCC_APB2PeriphClockCmd(       
                RCC_APB2Periph_GPIOA|
                RCC_APB2Periph_GPIOB|
                RCC_APB2Periph_GPIOC|
                RCC_APB2Periph_GPIOD|
                RCC_APB2Periph_AFIO        |
                RCC_APB2Periph_TIM1|
                RCC_APB2Periph_ADC1        |
                RCC_APB2Periph_USART1
                |RCC_APB2Periph_SPI1
                , ENABLE);
}

使用特权

评论回复
67
mohanwei|  楼主 | 2014-12-4 21:28 | 只看该作者
config_block.c
改为统一处理参数……道理同上
int configblockInit(void)
{
        memcpy(&configblock, (void*)CONFIG_BLOCK_ADDRESS,sizeof(configblock));//先读取到RAM
  //Verify the config block
  if (configblock.magic!=MAGIC || configblock.version!= VERSION ||
      calculate_cksum(&configblock, sizeof(configblock)) )
  {
          //参数检查失败,原版不做任何改动;这里统一把所有参数用默认值替换:
          configblock.radioChannel = 10; //默认使用信道10(2410MHz)
                configblock.radioSpeed = RADIO_AirRATE_250K; //默认空中速率:250KHz
                configblock.calibPitch = 0;
                configblock.calibRoll = 0;
    return -1;//失败
  }
  else
  {
  return 0;//成功
  }
}

/* Static accessors */
u8 configblockGetRadioChannel(void)
{
    return configblock.radioChannel;
}

RADIO_AirRATE configblockGetRadioSpeed(void)
{
        return configblock.radioSpeed;
}

float configblockGetCalibPitch(void)
{
        return configblock.calibPitch;
}

float configblockGetCalibRoll(void)
{
        return configblock.calibRoll;
}

附上原版的代码:
int configblockInit(void)
{
  configblock = (void*)CONFIG_BLOCK_ADDRESS;

  //Verify the config block
  if (configblock->magic!=MAGIC || configblock->version!= VERSION ||
      calculate_cksum(configblock, sizeof(*configblock)) )
    return -1;

  cb_ok = true;
  
  return 0;
}

/* Static accessors */
int configblockGetRadioChannel(void)
{
  if (cb_ok)
    return configblock->radioChannel;
  else
    return RADIO_CHANEL;
}

int configblockGetRadioSpeed(void)
{
  if (cb_ok)
    return configblock->radioSpeed;
  else
    return RADIO_DATARATE;
}

float configblockGetCalibPitch(void)
{
  if (cb_ok)
    return configblock->calibPitch;
  else
    return 0;
}

float configblockGetCalibRoll(void)
{
  if (cb_ok)
    return configblock->calibRoll;
  else
    return 0;
}

使用特权

评论回复
68
mohanwei|  楼主 | 2014-12-4 21:33 | 只看该作者
这样慢慢改下去,最终CF这份代码将会只保留PID和IMU相关的代码……

使用特权

评论回复
69
mohanwei|  楼主 | 2014-12-4 21:42 | 只看该作者
这种迭代式的开发方法,无论是开发新产品还是维护老产品都能用得到。
如果一上来就埋头开新摊子,看起来速度会很快,但是个人实力不够的话(大部分工程师都这样吧),接下来的反复调试会把前期的优势一下子消耗殆尽;反复迭代的话,每次都只是小改动,不会浪费额外的精力去debug,项目进度可以自己控制。

最近有个客户提出要一款带10个串口的串口服务器+其它定制功能的产品,光从资源分析,用新唐的NUC472会很轻松(自身就有12个串口),成本也比我们现在8串口的同类产品低很多。但从开发风险考虑,还是在原有8串口的基础上通过SPI口外扩一片多串口MCU来实现。

使用特权

评论回复
70
sail8498| | 2014-12-4 22:03 | 只看该作者
我从网上下了个baseflight的代码,还有个baseflightplus,正在学习baseflight呢。
虽然以前没专门学过单片机,但是有几年编程经历,单纯学单片机不难。
最大的麻烦是没学过模/数电路.
我对这个四轴的功能需要做些更改,可能会跟大多数现有的四轴功能有些区别。
还在对四轴能达到的功能和我能完成的功能分析,计划中。。。

使用特权

评论回复
71
mohanwei|  楼主 | 2014-12-4 22:08 | 只看该作者
sail8498 发表于 2014-12-4 22:03
我从网上下了个baseflight的代码,还有个baseflightplus,正在学习baseflight呢。
虽然以前没专门学过单片机 ...

你这种情况,估计MWC更合适……你可以搜一下“MWC”了解一下,一个用arduino的多轴系统(三轴、四轴、六轴、八轴等),各种QQ群都很火爆,买个板子下个固件,杜邦线跳一下就能飞起来,参数可以自己改,有兴趣也可以装个开发环境自己改代码

使用特权

评论回复
72
sail8498| | 2014-12-4 22:42 | 只看该作者
mohanwei 发表于 2014-12-4 22:08
你这种情况,估计MWC更合适……你可以搜一下“MWC”了解一下,一个用arduino的多轴系统(三轴、四轴、六 ...

我说的功能更改,改得挺多的。。。
ATMEGA128这个小板子我怕不够我用。。。
我想在上面挂4G模块,加一些例如自动跟踪着落的功能(比如汽车慢慢行驶,车顶放个特别的信号灯,四轴能自动跟踪信号灯并落到天窗上。

四轴反正儿子3岁以前不打算带他玩,我会给他搭个大框架,只要在能带他玩的时候能飞起来就好,别的功能慢慢完善,在他懂事后慢慢带他一起做。小家伙才不到一岁,不着急。

像我儿子的玩具车(他能坐进去自已开的),我就改了很多,把原来的控制电路全抛弃了,换成STM32和蓝牙接收器,给前后都加了超声波模块,加上缓启动,加上防撞功能,加了他离开座椅就自动停车的功能,能防止他开到阶梯下摔着或撞到小区的汽车和家里的家具。
开始也觉得挺复杂,做下来发现也很简单,跟据障碍距离,电机编码,控制PWM输出来控制车速。

使用特权

评论回复
73
mohanwei|  楼主 | 2014-12-4 23:01 | 只看该作者
sail8498 发表于 2014-12-4 22:42
我说的功能更改,改得挺多的。。。
ATMEGA128这个小板子我怕不够我用。。。
我想在上面挂4G模块,加一些 ...

必须赞一个:handshake

我也是差不多的思路。
现在先给他准备一个比较简单的固定翼泡沫飞机,用公司的一个产品方案改的,两个机翼上各装一个小电机+正反浆,无需舵机,加大油门就会加快+上升,两边差速就会拐弯,等他大点就在尾部加个小电机(还是避免舵机)负责剧烈的翻滚,可以玩很多特效飞行动作。
固定翼的优点是同样300mAh的电池就能玩个四五十分钟,外出一次带两块电池就够尽兴了

使用特权

评论回复
74
mohanwei|  楼主 | 2014-12-7 19:55 | 只看该作者
wwfiney 发表于 2014-12-4 20:47
去下载最新的好了
我有个移植到keil编译的版本,不过连接PC端有问题
我把CF移植到烈火的小四轴上了,不过 ...

到github用svn把Bootloader、firmware、PC端dongle(其它USB单片机)的代码都checkout了一份。
链接地址是:https://bitbucket.org/bitcraze
分别点这几个进去:
Crazyradio firmware Updated 2014-03-03
Crazyflie firmware Updated 2014-03-03
Crazyflie bootloader Updated 2014-03-03

用Ultraedit搜索了一遍.c和.h,发现没什么改善,例如configblock.c还是一样的……不知你有没有研究过?或者有其它途径发布的源码?

使用特权

评论回复
75
mohanwei|  楼主 | 2014-12-7 20:25 | 只看该作者
这个开源项目使用FreeRTOS,是一个惊喜……之前只是调研时了解过这个RTOS,当时相对uCOS的优点是:免费;不同优先级可以抢占+同优先级轮转,这点比uCOS强(当然现在新版本的uCOS也具备了)

首先注释一下配置文件“FreeRTOSConfig.h”,大致了解一下这个程序顶层的情况:

/*
    FreeRTOS V6.0.0 - Copyright (C) 2009 Real Time Engineers Ltd.

    ***************************************************************************
    *                                                                         *
    * If you are:                                                             *
    *                                                                         *
    *    + New to FreeRTOS,                                                   *
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
    *    + Looking for basic training,                                        *
    *    + Wanting to improve your FreeRTOS skills and productivity           *
    *                                                                         *
    * then take a look at the FreeRTOS eBook                                  *
    *                                                                         *
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
    *                  http://www.FreeRTOS.org/Documentation                  *
    *                                                                         *
    * A pdf reference manual is also available.  Both are usually delivered   *
    * to your inbox within 20 minutes to two hours when purchased between 8am *
    * and 8pm GMT (although please allow up to 24 hours in case of            *
    * exceptional circumstances).  Thank you for your support!                *
    *                                                                         *
    ***************************************************************************

    This file is part of the FreeRTOS distribution.

    FreeRTOS is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License (version 2) as published by the
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
    ***NOTE*** The exception to the GPL is included to allow you to distribute
    a combined work that includes FreeRTOS without being obliged to provide the
    source code for proprietary components outside of the FreeRTOS kernel.
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    more details. You should have received a copy of the GNU General Public
    License and the FreeRTOS license exception along with FreeRTOS; if not it
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
    by writing to Richard Barry, contact details for whom are available on the
    FreeRTOS WEB site.

    1 tab == 4 spaces!

    http://www.FreeRTOS.org - Documentation, latest information, license and
    contact details.

    http://www.SafeRTOS.com - A version that is certified for use in safety
    critical systems.

    http://www.OpenRTOS.com - Commercial support, development, porting,
    licensing and training services.
*/

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/

#define configUSE_PREEMPTION        1//1=使用抢占式内核;0-为合作轮转内核。
#define configUSE_IDLE_HOOK         0//1-使用空闲任务钩子(如做一下CPU使用率统计);0-不使用空闲任务钩子
#define configUSE_TICK_HOOK         0//1-使用时间片钩子;0-不使用
#define configCPU_CLOCK_HZ          ( ( unsigned long ) 72000000 )//CPU时钟频率。STM32跑在72MHz
#define configTICK_RATE_HZ          ( ( portTickType ) 1000 )//FreeRTOS滴答时钟频率设为1000Hz,即1ms调度一次
#define configMINIMAL_STACK_SIZE    ( ( unsigned short ) 100 )//空闲任务使用的堆栈大小。
//通常这个值不用少于 FreeRTOSConfig.h file中演示程序提供的。

//#define configTOTAL_HEAP_SIZE       ( ( size_t ) ( 15000 ) )//内核内存池大小。原版RAM只有20KB,分配了不到15KB
#define configTOTAL_HEAP_SIZE       ( ( size_t ) ( 1024*30 ) )//内核内存池大小。我们RAM有48KB,分配30KB
//如果程序中利用例子中内存分配方案(FreeRTOS 源代码提供的),这个值仅仅适用这些。参考内存管理 部分获得更过细节.

#define configMAX_TASK_NAME_LEN     ( 10 )//创建任务时名称的最大长度。这个长度指定符号数目,包括NULL终止字节。
#define configUSE_TRACE_FACILITY    0//1-使用可视化追踪功能。0-不使用。如果使能,必须提供追踪缓冲区。

#define configUSE_16_BIT_TICKS      0//时间片(内核开始执行后,时间片中断的次数)来测量时间。
//时间片计数器定义为可用的portTickType.类型。
//1-把portTickType定义为16位无符号类型;0-使用32位无符号类型。
//使用16位类型,将使在16位或8位单片机大幅度提高性能。但是,这样限制了最大指定可用时间周期(65535时间片)。
//然而,假定时间片频率为250Hz,一个任务在16位上,最大延时或中断时间位262秒,而32位为17179869秒。

#define configIDLE_SHOULD_YIELD     0/* 这个参数控制任务与空闲任务优先级相同时的行为。仅仅有以下影响:
    使用优先级调度
    用户程序创建的任务,运行在空闲任务一样的优先级

任务在时间片轮转中,使用同一优先级。假定没有更高优先级的任务,这样每一个任务,在空闲优先级下,将被分配相同数量
的处理时间。如果,他们的优先级高于空闲任务的优先级,那么这种情况更是如此。 当任务处于空闲优先级下的行为,
会有稍许不同。当configIDLE_SHOULD_YIELD设置为1时,当其他在空闲优先级的任务准备运行时,空闲任务将立刻让出CPU。
当程序的任务调度可用时,要确保空闲任务能够执行的最少时间以上。这个行为,产生了不好的影响(根据应用程序的需要),
如下描述:
上述图表表明,四个在空闲优先级的任务执行模型。任务A, B,和C,是应用程序任务。任务 I是空闲任务。
上下文切换在T0, T1....T6规律的周期间发生。当空闲任务执行时,任务A准备执行,但是空闲任务已经占去了当前时间片的
部分时间。结果是,任务I 和任务A共同分享一个时间片。任务B 和任务C比任务A获得更多的执行时间。
这些可以通过如下避免:
    如果合适,可以使用空闲钩子代替在空闲优先级的分开任务。创建程序任务的优先级高于空闲优先级。
    设置configIDLE_SHOULD_YIELD为1

设置configIDLE_SHOULD_YIELD为1,将阻止空闲任务让出执行时间直到它的时间片用完。
这就确保了所有在空闲优先级的任务分配了相同数量的执行时间。这是以分配给空闲任务更高比例的执行时间为代价。
*/

#define configCHECK_FOR_STACK_OVERFLOW      1 //The 堆栈溢出检测 这页中有详细的细节描述。


/* 关于软件定时器:很多操作都需要临时关闭中断——同时RTOS也无法调度,所以软件定时器就会有误差……
所以精度要求比较高时,需要自己定义一个硬件的定时器,这里提供了us_Timestamp_48bit(),应用程序可以
调用这个函数获取48bit的时间戳,单位是us*/
#define configUSE_TIMERS          1 //1-使能软件定时器功能
#define configTIMER_TASK_PRIORITY 1 //设置软件定时器任务的优先级
#define configTIMER_QUEUE_LENGTH  20//设置软件定时器任务中用到的命令队列的长度
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE//设置软件定时器任务需要的任务堆栈大小跟空闲任务一样

#define configMAX_PRIORITIES        ( ( unsigned portBASE_TYPE ) 5 )//应用程序任务中可用优先级的数目.
//任何数量的任务,都可以分配同一优先级。 任务单独分配优先级。参考configMAX_CO_ROUTINE_PRIORITIES。
//内核分配的每个可用的优先级都消耗RAM,因此这个值不应该设置为高于实际应用程序中需要的。

#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )//合作式应用程序优先级数目。任何合作式程序可使用同一优先级
#define configUSE_CO_ROUTINES       0 //1-使用(协同例程)合作轮转式程序;0-不使能。使能时,必须包含Croutine.c

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
//屏蔽不需要的API函数,可以节约Flah和RAM:
#define INCLUDE_vTaskPrioritySet        0 //我们创建任务时就固定好优先级,所以不需要这个API函数
#define INCLUDE_uxTaskPriorityGet       0 //我们使用固定优先级,所以不需要这个API函数
#define INCLUDE_vTaskDelete             0 //我们的任务都是固定的,不需要动态修改
#define INCLUDE_vTaskCleanUpResources   0 //设为1可以回收删除任务后的资源(RAM等),我们的任务是固定的,不需要
#define INCLUDE_vTaskSuspend            0 //设为1可以挂起任务,我们不需要
#define INCLUDE_vTaskDelayUntil         1 //裸奔用delay可耻,在OS里就是正道了^_^
#define INCLUDE_vTaskDelay              1 //裸奔用delay可耻,在OS里就是正道了^_^

#define configUSE_MUTEXES 1 //1-使能互斥;0-不使能。读者应该明白FreeRTOS中互斥型和二进制型信号量之间的不同。
#define configUSE_RECURSIVE_MUTEXES 0 //1-使能递归互斥功能;0-不使能
#define configUSE_COUNTING_SEMAPHORES 0 //1-使能计数器型信号量功能;0-不使能
#define configUSE_ALTERNATIVE_API 0 //1-包含替代队列函数;0-不包含。替代API在queue.h头文件中有详细的描述。

#define configKERNEL_INTERRUPT_PRIORITY     255 //内核中断一般应该设置为最低优先级(不能影响外设硬件中断)
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 143 /* equivalent to 0x08, or priority 8. */
/* configKERNEL_INTERRUPT_PRIORITY应该设置为最低优先级。
注意如下讨论中,以"FromISR" 结尾的API函数仅能够在中断服务函数中调用。
那些仅仅设置configKERNEL_INTERRUPT_PRIORITY的接口
内核本身为 configKERNEL_INTERRUPT_PRIORITY设置优先级。调用API函数的中断,也必须以这个优先级执行。
没有调用API函数的中断,可以有更高的优先级,因此内核调动,他们执行从不延时(在他们硬件限制的范围内)。
那些在这两种情况下:
configKERNEL_INTERRUPT_PRIORITY and configMAX_SYSCALL_INTERRUPT_PRIORITY执行的接口。
内核本身为configKERNEL_INTERRUPT_PRIORITY设置优先级。可以设置configMAX_SYSCALL_INTERRUPT_PRIORITY为从调用FreeRTOS
API 函数的中断设置更高的优先级。
可以设置configMAX_SYSCALL_INTERRUPT_PRIORITY高于 (一个很高优先级的水平)configKERNEL_INTERRUPT_PRIORITY来
获得中断全嵌套模式。没有调用API函数的中断可以在高于configMAX_SYSCALL_INTERRUPT_PRIORITY 优先级下执行,
因此是不会被内核执行延时。例如,假定一个微控制器,为8级中断优先级水平——0是最低优先级,7为最高
(参考Cortex M3用户在这部分的结尾特别注意的地方)。如下图片,描述了在每一个优先级下什么可以和什么不可以,
两个常量被设置为4和0。

中断优先级配置例子
这些参数配置允许很灵活的中断处理:
中断处理的任务,像系统里其他任务一样,书写和分配优先级。这些任务都是被一个中断激活。
ISR本身编写的应该尽可能的短小——仅仅为了唤醒更高优先级的任务而占用RAM。
ISR返回,直接进入要唤醒的任务——因此中断处理是及时的好像所有是中断本身做的一样。
这样的好处是:执行处理的任务时,所有的中断都允许。
执行 configMAX_SYSCALL_INTERRUPT_PRIORITY的接口提供更多——在内核中断和configMAX_SYSCALL_INTERRUPT_PRIORITY
之间允许全嵌套模式嵌套和程序调用API函数。中断优先级在configMAX_SYSCALL_INTERRUPT_PRIORITY执行从不延时。
运行在高于系统调用最大优先级的ISR,从不会被内核本身屏蔽,所以他们的响应性不被内核功能所影响。
对于那些需要瞬间高精度的中断来说是个好方法——例如:执行发动机换向的中断。但这样的ISR不能够使用FreeRTOS API函数
为了利用这个方案,应用程序必须遵守如下原则:任何使用FreeRTOS.org API的中断必须设置为同一优先级,
像内核(configKERNEL_INTERRUPT_PRIORITY配置的一样),或者处于或低于configMAX_SYSCALL_INTERRUPT_PRIORITY(
为了接口包含了这个功能)。
Cortex M3 用和特别要注意的地方: 记住,Cortex M3 核心数值上使用低优先级来代替高优先级的中断(
这样看起来反常规和容易忘记)。如果希望分配够中断一个低优先级,不要分配为0优先级(或其他低数值),
因为这样实际上在系统中这个中断为最高优先级——如果设置优先级在configMAX_SYSCALL_INTERRUPT_PRIORITY可能使系统崩溃。
在Cortex M3核心 最低优先级实际上是255——然而不同于 Cortex M3 卖主说明的不同数目的优先级位和支持库函数(
期待优先级使用不同方法指定)。例如在STM32 ,在ST驱动库中能够指定的最低优先级是15——最高优先级可以指定为0。
configKERNEL_INTERRUPT_PRIORITY and configMAX_SYSCALL_INTERRUPT_PRIORITY
configKERNEL_INTERRUPT_PRIORITY一般适用于Cortex-M3, PIC24, dsPIC and PIC32 接口。
configMAX_SYSCALL_INTERRUPT_PRIORITY一般PIC32和Cortex M3 接口中可用。其他接口将很快更新。

*/
//Map the port handler to the crt0 interruptions handlers
#define xPortPendSVHandler PendSV_Handler //任务上下文切换中断,这里实际没用到
#define xPortSysTickHandler SysTick_Handler //滴答时钟定时器中断。改个名称提高可移植性吧
#define vPortSVCHandler SVC_Handler //同样没用到

//Milliseconds to OS Ticks
#define M2T(X) ((unsigned int)(X*(configTICK_RATE_HZ/1000.0))) //毫秒转换为滴答时钟数目
#define F2T(X) ((unsigned int)((configTICK_RATE_HZ/X))) //用于设置delay相关API的增量?

// DEBUG SECTION
#define configUSE_APPLICATION_TASK_TAG  1 //使能任务标签
#define configQUEUE_REGISTRY_SIZE       10 /* 队列记录有两个功能,都这涉及到内核相关的调试:
允许一个队列相关的名称,可以在GUI调试中容易定义。
包含了调试器所需的信息,来定位每个记录的队列和信号量。队列记录除了进行内核相关的调试外,没有什么目的。
configQUEUE_REGISTRY_SIZE定义了可以记录的队列和信号量的最大数目。这些仅能够在使用内核相关调试时需要记录的。
查看API中vQueueAddToRegistry() 和 vQueueUnregisterQueue()参考文档,获得更多信息。*/

//以下是Crazyflie作者定义的任务标签值:(不是必须的)
#define TASK_LED_ID_NBR         1
#define TASK_RADIO_ID_NBR       2
#define TASK_STABILIZER_ID_NBR  3
#define TASK_ADC_ID_NBR         4
#define TASK_PM_ID_NBR          5

#define traceTASK_SWITCHED_IN() \
  { \
    extern void debugSendTraceInfo(unsigned int taskNbr); \
    debugSendTraceInfo((int)pxCurrentTCB->pxTaskTag); \
  }


#endif /* FREERTOS_CONFIG_H */

使用特权

评论回复
76
mohanwei|  楼主 | 2014-12-7 20:31 | 只看该作者
根据我们的新硬件,把外设都梳理了一遍,编译,下载进去,红绿两个LED(板上没有,随便用电机旁边的4个LED代替)可以闪起来,IDE也可以看到FreeRTOS的任务信息,算是一个良好的开端……

使用特权

评论回复
77
wwfiney| | 2014-12-9 22:58 | 只看该作者
mohanwei 发表于 2014-12-7 19:55
到github用svn把Bootloader、firmware、PC端dongle(其它USB单片机)的代码都checkout了一份。
链接地址 ...

他们的源码确实不是这么结构化,很多都是hardcode进去的一些配置
可能是人手问题,而且他们只针对cf平台
最新的刚release了2.0,在2.0这个branch,还没有合并到master

使用特权

评论回复
78
wwfiney| | 2014-12-9 23:09 | 只看该作者
他们现在代码管理有点乱,cf2.0的分支对比master基本所有文件都变了,diff的结果差异也不少,一次更新这么多进去,log已经没意义了

使用特权

评论回复
79
longren007| | 2014-12-10 18:52 | 只看该作者
有兴趣,已加群

使用特权

评论回复
80
mohanwei|  楼主 | 2014-12-10 20:42 | 只看该作者
wwfiney 发表于 2014-12-9 22:58
他们的源码确实不是这么结构化,很多都是hardcode进去的一些配置
可能是人手问题,而且他们只针对cf平台
...

不管怎么说,作者能提供这样一个平台已经很好了,后来者可以在此基础上阅读、理解、改进。这种资源有限的嵌入式产品的确是没必要搞得太通用、庞大,像uboot那样的一个引导程序已经搞得比绝大部分的产品都复杂了,完整看一遍代码都几乎成了不可能。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则