iNavFlight飞控固件学习-4《LED初始化》
目录
文章目录
- 目录
- 1.简介
- 2.LED 原理图
- 3.LED 板层文件配置
- 4.LED 初始化
1.简介
本节主要记录INAV LED 初始化的过程,欢迎批评指正!!!
2.LED 原理图
1.首先看下原理图
以上是LED的初始化,主要用的引脚是:
LED0---->PC15;
LED1---->PC14;
3.LED 板层文件配置
打开inav/src/target/自己板子
上面是修改:LED0,LED1的配置文件。
4.LED 初始化
void init(void)
{......//初始化LEDledInit(false);......
}
//LED 初始化
void ledInit(bool alternative_led)
{//LED 指示灯
#if defined(LED0_A) || defined(LED1_A) || defined(LED2_A)if (alternative_led) {ledOffset = LED_NUMBER;}
#elseUNUSED(alternative_led);
#endif//关闭LEDLED0_OFF;LED1_OFF;LED2_OFF;//配置相关初始化for (int i = 0; i < LED_NUMBER; i++){//有定义LEDif (leds[i + ledOffset]){//IO信息,自己是什么,类型,序号IOInit(leds[i + ledOffset], OWNER_LED, RESOURCE_OUTPUT, RESOURCE_INDEX(i));IOConfigGPIO(leds[i + ledOffset], IOCFG_OUT_PP);}}//关闭信息LED0_OFF;LED1_OFF;LED2_OFF;
}
我们看下LED0_OFF 的实现过程!!!
# define LED0_OFF ledSet(0, false) //led设置0
# define LED1_OFF ledSet(1, false) //led设置1
# define LED2_OFF ledSet(2, false) //led设置2
void ledSet(int led, bool on)
{//ledPolarity led的极性;inverted默认是0const bool inverted = (1 << (led + ledOffset)) & ledPolarity;//写入IOWrite(leds[led + ledOffset], on ? inverted : !inverted);
}
//我们看下IO写的初始化
IOWrite(leds[led + ledOffset], on ? inverted : !inverted);
假如我们设置的是LED0 LED1 LED2 我们可以看出传入的参数是:ledOffset=0;led=0;led=1;led=2
leds[led + ledOffset]
leds[led + ledOffset]
leds[led + ledOffset]
因此传入的参数是:leds[0],leds[1],leds[2]
我们看下leds的定义:
static const IO_t leds[] = {//定义信息LED0;LED1;LED2
#ifdef LED0DEFIO_IO(LED0), //LED0初始化
#elseDEFIO_IO(NONE),
#endif
#ifdef LED1DEFIO_IO(LED1), //LED1初始化
#elseDEFIO_IO(NONE),
#endif
#ifdef LED2DEFIO_IO(LED2), //LED2初始化
#elseDEFIO_IO(NONE),
#endif//定义信息LED0_A;LED1_A;LED2_A
#if defined(LED0_A) || defined(LED1_A) || defined(LED2_A)
#ifdef LED0_ADEFIO_IO(LED0_A),
#elseDEFIO_IO(NONE),
#endif
#ifdef LED1_ADEFIO_IO(LED1_A),
#elseDEFIO_IO(NONE),
#endif
#ifdef LED2_ADEFIO_IO(LED2_A),
#elseDEFIO_IO(NONE),
#endif
#endif
};
上面主要实现
leds[0] DEFIO_REC__PC15
leds[1] DEFIO_REC__PC14
可以看出leds实际是
static const IO_t leds[]
其中IO_t 就是一个指针
typedef void* IO_t; // type specifying IO pin. Currently ioRec_t pointer, but this may change
下面我们来看IOWrite 函数
void IOWrite(IO_t io, bool hi)
{//判断信息是否有信息if (!io){return;}
#if defined(USE_HAL_DRIVER)if (hi){HAL_GPIO_WritePin(IO_GPIO(io),IO_Pin(io),GPIO_PIN_SET);} else{HAL_GPIO_WritePin(IO_GPIO(io),IO_Pin(io),GPIO_PIN_RESET);}
#elif defined(STM32F4) if (hi){IO_GPIO(io)->BSRRL = IO_Pin(io); } else {IO_GPIO(io)->BSRRH = IO_Pin(io); }
#elif defined(AT32F43x)IO_GPIO(io)->scr = IO_Pin(io) << (hi ? 0 : 16);
#else//初始化IO_GPIO(io)->BSRR = IO_Pin(io) << (hi ? 0 : 16);
#endif
}
重点看IO_GPIO(io)->BSRR = IO_Pin(io) << (hi ? 0 : 16); 这个代码实现
这个寄存器BSRR是置位/复位寄存器
uint16_t IO_Pin(IO_t io)
{//初始化const ioRec_t *ioRec = IO_Rec(io); //初始化,实际就是把指针转换给对应的数据//返回return ioRec->pin;
}
ioRec_t* IO_Rec(IO_t io)
{ASSERT(io != NULL);//这里有强制转换ASSERT((ioRec_t*)io >= &ioRecs[0]);ASSERT((ioRec_t*)io < &ioRecs[DEFIO_IO_USED_COUNT]);return io;
}
typedef struct ioRec_s {GPIO_TypeDef *gpio; //类型uint16_t pin; //引脚resourceOwner_e owner; //资源resourceType_e resource; //数据源uint8_t index; //序号信息
} ioRec_t;
整体可以看下图所示:
我们看下LED初始化配置的实现过程!!!
//配置相关初始化for (int i = 0; i < LED_NUMBER; i++){//有定义LEDif (leds[i + ledOffset]){//IO信息,自己是什么,类型,序号IOInit(leds[i + ledOffset], OWNER_LED, RESOURCE_OUTPUT, RESOURCE_INDEX(i));IOConfigGPIO(leds[i + ledOffset], IOCFG_OUT_PP);}}
声明IO引脚,设置所有者和资源
//
void IOInit(IO_t io, resourceOwner_e owner, resourceType_e resource, uint8_t index)
{if (!io) {return;}ioRec_t *ioRec = IO_Rec(io); //io寄存器结构体ioRec->owner = owner; //拥有源ioRec->resource = resource; //类型源ioRec->index = index; //序号
}
配置IO相关,避免gcc/g++警告
void IOConfigGPIO(IO_t io, ioConfig_t cfg)
{UNUSED(io);UNUSED(cfg);
}
到这里可以看出led初始化实际就是先设置LED关闭,配置LED后再次设置关闭的过程。