(STM32)从零开始的RT-Thread之旅--PWM驱动ST7735调光
创始人
2024-01-29 21:58:58

上一章:

(STM32)从零开始的RT-Thread之旅--SPI驱动ST7735(1)

上一章我们先用SPI读取到了LCD的ID,这一章则是使用PWM调光点亮屏幕,因为测试这块屏幕时,发现直接设置背光引脚为高好像无法点亮,好像必须使用PWM调光,不过反正后面调节亮度还是需要PWM,索性先打通PWM。但这其中官方留的坑还是挺多的,简单的一个PWM因为需要契合内核驱动框架调了半天。

一如之前配置SPI的时候先配置RT-Thread Settings:

如果图形界面没有PWM,随便右键一个图标,点击配置项。

然后还是到board.h中定义相关的宏定义:

看一下介绍,结合上一章所讲,大致调用流程也很清晰。如果你在CubeMX中配置了相关PWM,就会生成这两个函数:

此时编译后会发现存在问题:

打开pwm_config.h中可以看到PWM_CONFIG是从PWM2开始配置的:

如果使用的PWM1则需要仿照现有的添加一个PWM1的:

 这里 tim_handle.Instance 也就是我们的PWM1对应的定时器是TIM1,名字是"pwm1",这个名字和我们之前用SPI4注册"spi40"设备时用的总线名字一样,我们到时候会通过一个函数搜索到它,如官方给的例子:

再次编译发现还回有问题,问题出在drv_pwm_setdrv_pwm_get这两个函数中,这是因为内核没有把H7系列的芯片包含进去:

可以看到这里的内核驱动代码还不完善,其实这里主要是为了获取 tim_clock 这个变量,也就是定时器时钟,但是对于H7来说,确定用的哪个定时器很重要。详细可以参考:

H7定时器

这个应该是硬汉出的教程,别人转载的。这里我讲一下我是用的TIM1是怎么配置的,你可以根据需要配置你自己的定时器。这里讲解一下怎么由时钟树理解时钟走向。

首先我们进到 HAL_RCC_GetPCLK2Freq 这个函数中,如果你定时器挂载在APB1上,则应该使用的是 HAL_RCC_GetPCLK1Freq 这个函数获取PCLK1的频率。为什么需要用这个函数?我们从时钟树上理一下,这部分时钟树如下:

TIM1挂载在APB2下,时钟源是 rcc_timy_ker_ck ,我们需要先确定 rcc_pclk2的频率,也就是APB2总线的频率,它又来自于 rcc_hclk ,也就是AHB1/2的时钟,所以我们进入函数HAL_RCC_GetPCLK2Freq 可以看到:

首先我们通过HAL_RCC_GetHCLKFreq()这个函数获取到HCLK的时钟频率,然后拆分后面的部分,(RCC->D2CFGR & RCC_D2CFGR_D2PPRE2)>> RCC_D2CFGR_D2PPRE2_Pos 是为了获取 RCC_D2CFGR_D2PPRE2 寄存器的值,原理如下:

获取到 RCC_D2CFGR_D2PPRE2 寄存器的值后,查表:

比如这个寄存器的值是 110,即6,D1CorePrescTable[6] = 3,HCLK的时钟右移3,相当于除以8,正好和上图中计算110:rcc_pclk2的情况相同。然后根据这个时钟去计算定时器时钟,这又分为两个情况:

源码中我们可以看到在使用 HAL_RCC_GetPCLK2Freq 获取定时器时钟的情况中只有乘2这一种情况:

但其实应该是两种情况,我这里在CubeMX中 D2PPRE2 寄存器选择的是除以2,所以这里乘2是没有关系的: 

如果在CubeMX中D2PPRE2选择1,你会发现定时器那里会自动选为除以1,但是选1的话可以看到会有如下提示:

APB2最大只能120MHz,选1则系统主频最高只能240MHz了。 

修改完这里,编译即可正常通过。然后我们就可以开始调用官方给的接口函数控制PWM了:

#include 
#include 
#include "mpwm.h"
#include 
struct rt_device_pwm *pwm_lcd;static uint32_t mpulse = 0;void mpwm_set(uint32_t pulse)
{mpulse = pulse;rt_pwm_set(pwm_lcd,2,1000,pulse);}uint32_t mpwm_get(void)
{return mpulse;
}void mpwm_init(void)
{pwm_lcd = (struct rt_device_pwm *)rt_device_find("pwm1");if(!pwm_lcd){rt_kprintf("pwm1 can't find\n");}rt_pwm_enable(pwm_lcd,2);rt_pwm_set(pwm_lcd,2,1000,0);
}

这里简单写了几个接口函数,实际直接使用,发现并没有输出,主要的坑已经全踩过了!懒得给官方提PR了,留给后人完善吧。

STM32的PWM所使用定时的初始化在内核驱动 drv_pwm.c 文件中的 stm32_pwm_init的 stm32_hw_pwm_init 函数里:

注意上图红色方框,你使用哪个定时器就需要添加哪个定时器的时钟使能。其次高级定时器一些额外的设置也需要添加,你如果不知道你用的定时器需不需要添加这些,请参照你使用CubeMX生成的定时器配置,我这里是在main.c中:

根据上面函数的配置,添加到这个函数里: 

我这里使用的TIM1需要配置刹车和死区配置。添加完这些,你会发现还是无法使用PWM输出,这是因为是使能函数有问题:

在同个文件中还有pwm使能函数,这个函数中所使用的 HAL_TIM_PWM_Start 函数只对普通定时器有效,TIM1是高级定时器,所以应该使用的函数是:HAL_TIMEx_PWMN_Start 。我这里不考虑其他情况,只针对我自己的工程做以下修改:

此时再使用PWM即可正常使用。 

给出drv_pwm.c以供参考:

/** Copyright (c) 2006-2018, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2018-12-13     zylx         first version*/#include 
#include
#include#ifdef RT_USING_PWM
#include "drv_config.h"#define DRV_DEBUG
#define LOG_TAG             "drv.pwm"
#include #define MAX_PERIOD 65535
#define MIN_PERIOD 3
#define MIN_PULSE 2extern void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);enum
{
#ifdef BSP_USING_PWM1PWM1_INDEX,
#endif
#ifdef BSP_USING_PWM2PWM2_INDEX,
#endif
#ifdef BSP_USING_PWM3PWM3_INDEX,
#endif
#ifdef BSP_USING_PWM4PWM4_INDEX,
#endif
#ifdef BSP_USING_PWM5PWM5_INDEX,
#endif
#ifdef BSP_USING_PWM6PWM6_INDEX,
#endif
#ifdef BSP_USING_PWM7PWM7_INDEX,
#endif
#ifdef BSP_USING_PWM8PWM8_INDEX,
#endif
#ifdef BSP_USING_PWM9PWM9_INDEX,
#endif
#ifdef BSP_USING_PWM10PWM10_INDEX,
#endif
#ifdef BSP_USING_PWM11PWM11_INDEX,
#endif
#ifdef BSP_USING_PWM12PWM12_INDEX,
#endif
#ifdef BSP_USING_PWM13PWM13_INDEX,
#endif
#ifdef BSP_USING_PWM14PWM14_INDEX,
#endif
#ifdef BSP_USING_PWM15PWM15_INDEX,
#endif
#ifdef BSP_USING_PWM16PWM16_INDEX,
#endif
#ifdef BSP_USING_PWM17PWM17_INDEX,
#endif
};struct stm32_pwm
{struct rt_device_pwm pwm_device;TIM_HandleTypeDef    tim_handle;rt_uint8_t channel;char *name;
};static struct stm32_pwm stm32_pwm_obj[] =
{
#ifdef BSP_USING_PWM1PWM1_CONFIG,
#endif#ifdef BSP_USING_PWM2PWM2_CONFIG,
#endif#ifdef BSP_USING_PWM3PWM3_CONFIG,
#endif#ifdef BSP_USING_PWM4PWM4_CONFIG,
#endif#ifdef BSP_USING_PWM5PWM5_CONFIG,
#endif#ifdef BSP_USING_PWM6PWM6_CONFIG,
#endif#ifdef BSP_USING_PWM7PWM7_CONFIG,
#endif#ifdef BSP_USING_PWM8PWM8_CONFIG,
#endif#ifdef BSP_USING_PWM9PWM9_CONFIG,
#endif#ifdef BSP_USING_PWM10PWM10_CONFIG,
#endif#ifdef BSP_USING_PWM11PWM11_CONFIG,
#endif#ifdef BSP_USING_PWM12PWM12_CONFIG,
#endif#ifdef BSP_USING_PWM13PWM13_CONFIG,
#endif#ifdef BSP_USING_PWM14PWM14_CONFIG,
#endif#ifdef BSP_USING_PWM15PWM15_CONFIG,
#endif#ifdef BSP_USING_PWM16PWM16_CONFIG,
#endif#ifdef BSP_USING_PWM17PWM17_CONFIG,
#endif
};static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg);
static struct rt_pwm_ops drv_ops =
{drv_pwm_control
};static rt_err_t drv_pwm_enable(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration, rt_bool_t enable)
{/* Converts the channel number to the channel number of Hal library */rt_uint32_t channel = 0x04 * (configuration->channel - 1);//    if (!enable)
//    {
//        HAL_TIM_PWM_Stop(htim, channel);
//    }
//    else
//    {
//        HAL_TIM_PWM_Start(htim, channel);
//    }if (!enable){HAL_TIMEx_PWMN_Stop(htim, channel);}else{HAL_TIMEx_PWMN_Start(htim, channel);}return RT_EOK;
}static rt_err_t drv_pwm_get(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration)
{/* Converts the channel number to the channel number of Hal library */rt_uint32_t channel = 0x04 * (configuration->channel - 1);rt_uint64_t tim_clock;#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)if (htim->Instance == TIM9 || htim->Instance == TIM10 || htim->Instance == TIM11)
#elif defined(SOC_SERIES_STM32L4)if (htim->Instance == TIM15 || htim->Instance == TIM16 || htim->Instance == TIM17)
#elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)  || defined(SOC_SERIES_STM32H7)if (0)
#elif defined(SOC_SERIES_STM32H7)if (1)
#endif{
#if !defined(SOC_SERIES_STM32F0) && !defined(SOC_SERIES_STM32G0)tim_clock = HAL_RCC_GetPCLK2Freq() * 2;
#endif}else{
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)tim_clock = HAL_RCC_GetPCLK1Freq();
#elsetim_clock = HAL_RCC_GetPCLK1Freq() * 2;
#endif}if (__HAL_TIM_GET_CLOCKDIVISION(htim) == TIM_CLOCKDIVISION_DIV2){tim_clock = tim_clock / 2;}else if (__HAL_TIM_GET_CLOCKDIVISION(htim) == TIM_CLOCKDIVISION_DIV4){tim_clock = tim_clock / 4;}/* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */tim_clock /= 1000000UL;configuration->period = (__HAL_TIM_GET_AUTORELOAD(htim) + 1) * (htim->Instance->PSC + 1) * 1000UL / tim_clock;configuration->pulse = (__HAL_TIM_GET_COMPARE(htim, channel) + 1) * (htim->Instance->PSC + 1) * 1000UL / tim_clock;return RT_EOK;
}static rt_err_t drv_pwm_set(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration)
{rt_uint32_t period, pulse;rt_uint64_t tim_clock, psc;/* Converts the channel number to the channel number of Hal library */rt_uint32_t channel = 0x04 * (configuration->channel - 1);#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)if (htim->Instance == TIM9 || htim->Instance == TIM10 || htim->Instance == TIM11)
#elif defined(SOC_SERIES_STM32L4)if (htim->Instance == TIM15 || htim->Instance == TIM16 || htim->Instance == TIM17)
#elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)if (0)
#elif defined(SOC_SERIES_STM32H7)if (1)
#endif{
#if !defined(SOC_SERIES_STM32F0) && !defined(SOC_SERIES_STM32G0)tim_clock = HAL_RCC_GetPCLK2Freq() * 2;
#endif}else{
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)tim_clock = HAL_RCC_GetPCLK1Freq();
#elsetim_clock = HAL_RCC_GetPCLK1Freq() * 2;
#endif}/* Convert nanosecond to frequency and duty cycle. 1s = 1 * 1000 * 1000 * 1000 ns */tim_clock /= 1000000UL;period = (unsigned long long)configuration->period * tim_clock / 1000ULL ;psc = period / MAX_PERIOD + 1;period = period / psc;__HAL_TIM_SET_PRESCALER(htim, psc - 1);if (period < MIN_PERIOD){period = MIN_PERIOD;}__HAL_TIM_SET_AUTORELOAD(htim, period - 1);pulse = (unsigned long long)configuration->pulse * tim_clock / psc / 1000ULL;if (pulse < MIN_PULSE){pulse = MIN_PULSE;}else if (pulse > period){pulse = period;}__HAL_TIM_SET_COMPARE(htim, channel, pulse - 1);__HAL_TIM_SET_COUNTER(htim, 0);/* Update frequency value */HAL_TIM_GenerateEvent(htim, TIM_EVENTSOURCE_UPDATE);return RT_EOK;
}static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
{struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)device->parent.user_data;switch (cmd){case PWM_CMD_ENABLE:return drv_pwm_enable(htim, configuration, RT_TRUE);case PWM_CMD_DISABLE:return drv_pwm_enable(htim, configuration, RT_FALSE);case PWM_CMD_SET:return drv_pwm_set(htim, configuration);case PWM_CMD_GET:return drv_pwm_get(htim, configuration);default:return RT_EINVAL;}
}static rt_err_t stm32_hw_pwm_init(struct stm32_pwm *device)
{rt_err_t result = RT_EOK;TIM_HandleTypeDef *tim = RT_NULL;TIM_OC_InitTypeDef oc_config = {0};TIM_MasterConfigTypeDef master_config = {0};TIM_ClockConfigTypeDef clock_config = {0};TIM_BreakDeadTimeConfigTypeDef break_dead_time_config = {0};RT_ASSERT(device != RT_NULL);//Add TIMx CLK enable__HAL_RCC_TIM1_CLK_ENABLE();tim = (TIM_HandleTypeDef *)&device->tim_handle;/* configure the timer to pwm mode */tim->Init.Prescaler = 0;tim->Init.CounterMode = TIM_COUNTERMODE_UP;tim->Init.Period = 200;tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
#if defined(SOC_SERIES_STM32H7)tim->Init.RepetitionCounter = 0;
#endif
#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32H7)tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
#endifif (HAL_TIM_PWM_Init(tim) != HAL_OK){LOG_E("%s pwm init failed", device->name);result = -RT_ERROR;goto __exit;}clock_config.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(tim, &clock_config) != HAL_OK){LOG_E("%s clock init failed", device->name);result = -RT_ERROR;goto __exit;}master_config.MasterOutputTrigger = TIM_TRGO_RESET;
#if defined(SOC_SERIES_STM32H7)master_config.MasterOutputTrigger2 = TIM_TRGO_RESET;
#endifmaster_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(tim, &master_config) != HAL_OK){LOG_E("%s master config failed", device->name);result = -RT_ERROR;goto __exit;}oc_config.OCMode = TIM_OCMODE_PWM1;oc_config.Pulse = 0;oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
#if defined(SOC_SERIES_STM32H7)oc_config.OCNPolarity = TIM_OCNPOLARITY_LOW;
#endifoc_config.OCFastMode = TIM_OCFAST_DISABLE;oc_config.OCNIdleState = TIM_OCNIDLESTATE_RESET;oc_config.OCIdleState  = TIM_OCIDLESTATE_RESET;/* config pwm channel */if (device->channel & 0x01){if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_1) != HAL_OK){LOG_E("%s channel1 config failed", device->name);result = -RT_ERROR;goto __exit;}}if (device->channel & 0x02){if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_2) != HAL_OK){LOG_E("%s channel2 config failed", device->name);result = -RT_ERROR;goto __exit;}}if (device->channel & 0x04){if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_3) != HAL_OK){LOG_E("%s channel3 config failed", device->name);result = -RT_ERROR;goto __exit;}}if (device->channel & 0x08){if (HAL_TIM_PWM_ConfigChannel(tim, &oc_config, TIM_CHANNEL_4) != HAL_OK){LOG_E("%s channel4 config failed", device->name);result = -RT_ERROR;goto __exit;}}
#if defined(SOC_SERIES_STM32H7)break_dead_time_config.OffStateRunMode = TIM_OSSR_DISABLE;break_dead_time_config.OffStateIDLEMode = TIM_OSSI_DISABLE;break_dead_time_config.LockLevel = TIM_LOCKLEVEL_OFF;break_dead_time_config.DeadTime = 0;break_dead_time_config.BreakState = TIM_BREAK_DISABLE;break_dead_time_config.BreakPolarity = TIM_BREAKPOLARITY_HIGH;break_dead_time_config.BreakFilter = 0;break_dead_time_config.Break2State = TIM_BREAK2_DISABLE;break_dead_time_config.Break2Polarity = TIM_BREAK2POLARITY_HIGH;break_dead_time_config.Break2Filter = 0;break_dead_time_config.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;if (HAL_TIMEx_ConfigBreakDeadTime(tim, &break_dead_time_config) != HAL_OK){LOG_E("%s break_dead_time config failed", device->name);result = -RT_ERROR;goto __exit;}
#endif/* pwm pin configuration */HAL_TIM_MspPostInit(tim);/* enable update request source */__HAL_TIM_URS_ENABLE(tim);__exit:return result;
}static void pwm_get_channel(void)
{
#ifdef BSP_USING_PWM1_CH1stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM1_CH2stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM1_CH3stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM1_CH4stm32_pwm_obj[PWM1_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM2_CH1stm32_pwm_obj[PWM2_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM2_CH2stm32_pwm_obj[PWM2_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM2_CH3stm32_pwm_obj[PWM2_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM2_CH4stm32_pwm_obj[PWM2_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM3_CH1stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM3_CH2stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM3_CH3stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM3_CH4stm32_pwm_obj[PWM3_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM4_CH1stm32_pwm_obj[PWM4_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM4_CH2stm32_pwm_obj[PWM4_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM4_CH3stm32_pwm_obj[PWM4_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM4_CH4stm32_pwm_obj[PWM4_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM5_CH1stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM5_CH2stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM5_CH3stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM5_CH4stm32_pwm_obj[PWM5_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM6_CH1stm32_pwm_obj[PWM6_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM6_CH2stm32_pwm_obj[PWM6_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM6_CH3stm32_pwm_obj[PWM6_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM6_CH4stm32_pwm_obj[PWM6_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM7_CH1stm32_pwm_obj[PWM7_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM7_CH2stm32_pwm_obj[PWM7_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM7_CH3stm32_pwm_obj[PWM7_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM7_CH4stm32_pwm_obj[PWM7_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM8_CH1stm32_pwm_obj[PWM8_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM8_CH2stm32_pwm_obj[PWM8_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM8_CH3stm32_pwm_obj[PWM8_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM8_CH4stm32_pwm_obj[PWM8_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM9_CH1stm32_pwm_obj[PWM9_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM9_CH2stm32_pwm_obj[PWM9_INDEX].channel |= 1 << 1;
#endif
#ifdef BSP_USING_PWM9_CH3stm32_pwm_obj[PWM9_INDEX].channel |= 1 << 2;
#endif
#ifdef BSP_USING_PWM9_CH4stm32_pwm_obj[PWM9_INDEX].channel |= 1 << 3;
#endif
#ifdef BSP_USING_PWM12_CH1stm32_pwm_obj[PWM12_INDEX].channel |= 1 << 0;
#endif
#ifdef BSP_USING_PWM12_CH2stm32_pwm_obj[PWM12_INDEX].channel |= 1 << 1;
#endif
}static int stm32_pwm_init(void)
{int i = 0;int result = RT_EOK;pwm_get_channel();for (i = 0; i < sizeof(stm32_pwm_obj) / sizeof(stm32_pwm_obj[0]); i++){/* pwm init */if (stm32_hw_pwm_init(&stm32_pwm_obj[i]) != RT_EOK){LOG_E("%s init failed", stm32_pwm_obj[i].name);result = -RT_ERROR;goto __exit;}else{LOG_D("%s init success", stm32_pwm_obj[i].name);/* register pwm device */if (rt_device_pwm_register(&stm32_pwm_obj[i].pwm_device, stm32_pwm_obj[i].name, &drv_ops, &stm32_pwm_obj[i].tim_handle) == RT_EOK){LOG_D("%s register success", stm32_pwm_obj[i].name);}else{LOG_E("%s register failed", stm32_pwm_obj[i].name);result = -RT_ERROR;}}}__exit:return result;
}
INIT_DEVICE_EXPORT(stm32_pwm_init);
#endif /* RT_USING_PWM */

 

 

上一篇:uni-app框架

下一篇:赞美合欢的一句话

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
函授本科是什么 自考本科还是函... 很多小伙伴在选择学历提升方式的时候,可能会感到很迷茫,不知道报考自考本科还是函授本科,两者有什么区别...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
安徒生童话有哪些 安徒生童话的... 从德国汉堡港乘轮船渡波罗的海抵丹麦王国,就到了安徒生的祖邦。安徒生(1805-1875)以童话作品闻...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...