折腾了一段时间Ardupilot的代码,先从例程开始学起,既然搞飞控,自然想到先从串口着手,下面分析一下UART_test的学习心得。(欢迎一起探讨,欢迎拍砖)
打开源码最让人疑惑的就是这行代码:
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
首先它涉及到一个HAL类,它是属于AP_HAL空间的,所有要使用这个类而不再AP_HAL空间就需要加AP_HAL::HAL,而后引用了一个hal对象,(这里涉及到一个问题,及为什么要使用引用,以我目前的理解,应该是使用引用,可以很方便的操作pixhawk的相关寄存器)并对他进行赋值,从右值可以看出,get_HAL()的返回值肯定应该是一个HAL类型的定位到实现看看,
const AP_HAL::HAL &AP_HAL::get_HAL()
{
return halInstance;
}
返回值是一个halInstancd值,再定位
static HAL_Linux halInstance;
class HAL_Linux : public AP_HAL::HAL {
public:
HAL_Linux();
void run(int argc, char* const* argv, Callbacks* callbacks) const override;
void setup_signal_handlers() const;
static void exit_signal_handler(int);
protected:
bool _should_exit = false;
};
class HAL_Linux : public AP_HAL::HAL {
public:
HAL_Linux();
void run(int argc, char* const* argv, Callbacks* callbacks) const override;
void setup_signal_handlers() const;
static void exit_signal_handler(int);
protected:
bool _should_exit = false;
};
可以看出,HAL_Linux是HAL的子类,定位到构造函数的实现
HAL_Linux::HAL_Linux() :
AP_HAL::HAL(
&uartADriver,
&uartBDriver,
&uartCDriver,
&uartDDriver,
&uartEDriver,
&uartFDriver,
&i2c_mgr_instance,
&spi_mgr_instance,
&analogIn,
&storageDriver,
&uartADriver,
&gpioDriver,
&rcinDriver,
&rcoutDriver,
&schedulerInstance,
&utilInstance,
&opticalFlow)
{}
可以看出使用的是初始化参数列表进行赋值,继续
static UARTDriver uartADriver(true);
#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO || \
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_NAVIO2 || \
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BH
static SPIUARTDriver uartBDriver;
#else
uartADriver是一个UARTDriver类,而后应该就是利用串口类进行串口设置,发送,接收等,就先不展开了。
回头看开HAL类:
class AP_HAL::HAL {
public:
HAL(AP_HAL::UARTDriver* _uartA, // console
AP_HAL::UARTDriver* _uartB, // 1st GPS
AP_HAL::UARTDriver* _uartC, // telem1
AP_HAL::UARTDriver* _uartD, // telem2
AP_HAL::UARTDriver* _uartE, // 2nd GPS
AP_HAL::UARTDriver* _uartF, // extra1
AP_HAL::I2CDeviceManager* _i2c_mgr,
AP_HAL::SPIDeviceManager* _spi,
AP_HAL::AnalogIn* _analogin,
AP_HAL::Storage* _storage,
AP_HAL::UARTDriver* _console,
AP_HAL::GPIO* _gpio,
AP_HAL::RCInput* _rcin,
AP_HAL::RCOutput* _rcout,
AP_HAL::Scheduler* _scheduler,
AP_HAL::Util* _util,
AP_HAL::OpticalFlow *_opticalflow)
:
uartA(_uartA),
uartB(_uartB),
uartC(_uartC),
uartD(_uartD),
uartE(_uartE),
uartF(_uartF),
i2c_mgr(_i2c_mgr),
spi(_spi),
analogin(_analogin),
storage(_storage),
console(_console),
gpio(_gpio),
rcin(_rcin),
rcout(_rcout),
scheduler(_scheduler),
util(_util),
opticalflow(_opticalflow)
{
AP_HAL::init();
}
AP_HAL::HAL &AP_HAL::get_HAL()
是利用HAL的子类对父类的一个赋值,
子类用初始化参数进行赋值的成员,赋值给父类的构造函数参数,又通过父类的初始化参数列表给父类成员赋值,而且整个过程运用的是引用,对父类成员的操作能直接影响到子类成员。
再来看看UART_test的具体内容
static void setup_uart(AP_HAL::UARTDriver *uart, const char *name)
{
if (uart == nullptr) {
// that UART doesn't exist on this platform
return;
}
uart->begin(57600);
}
void setup(void)
{
/*
start all UARTs at 57600 with default buffer sizes
*/
setup_uart(hal.uartA, "uartA"); // console
setup_uart(hal.uartB, "uartB"); // 1st GPS
setup_uart(hal.uartC, "uartC"); // telemetry 1
setup_uart(hal.uartD, "uartD"); // telemetry 2
setup_uart(hal.uartE, "uartE"); // 2nd GPS
}
static void test_uart(AP_HAL::UARTDriver *uart, const char *name)
{
if (uart == nullptr) {
// that UART doesn't exist on this platform
return;
}
uart->printf("Hello on UART %s at %.3f seconds\n",
name, AP_HAL::millis()*0.001f);
}
void loop(void)
{
test_uart(hal.uartA, "uartA");
test_uart(hal.uartB, "uartB");
test_uart(hal.uartC, "uartC");
test_uart(hal.uartD, "uartD");
test_uart(hal.uartE, "uartE");
#if HAL_OS_POSIX_IO
::printf("Hello on debug console at %.3f seconds\n", AP_HAL::millis()*0.001f);
#endif
hal.scheduler->delay(1000);
}
AP_HAL_MAIN();