stm32f103标准库+RT-Thread操作系统实现PWM驱动---1

 

 

转载请注明:https://mp.csdn.net/postedit/84571003

经过一天的实践,将基于标准库+RT-Thread的pwm驱动写完并通过示波器验证,此驱动目前不支持TIM1和TIM8,其他的定时器通道可以在rtconfig.h文件中配置,然后再在驱动文件中加上配置,此驱动目前只实现了TIM3的四个通道

 

typedef struct
{
  TIM_TypeDef                     *Instance;     /*!< Register base address             */
  TIM_TimeBaseInitTypeDef         Init;          /*!< TIM Time Base required parameters */
  uint16_t                       Channel;       /*!< Active channel                    */
}TIM_HandleTypeDef;


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_TypeDef *htim, struct rt_pwm_configuration *configuration, rt_bool_t enable)
{
    if((htim == TIM1) || (htim == TIM8))
    {
        rt_kprintf("The TIMX error\n");
        return RT_ERROR;
    }
    if((configuration->channel != TIM_Channel_1) && (configuration->channel != TIM_Channel_2) && 
        (configuration->channel != TIM_Channel_3) && (configuration->channel != TIM_Channel_4))
    {
        rt_kprintf("The TIMX Chx %d error\n",configuration->channel);
        return RT_ERROR;
    }
    if(enable)
    {
        TIM_CCxCmd(htim,configuration->channel,TIM_CCx_Enable);
    }
    else
    {
        TIM_CCxCmd(htim,configuration->channel,TIM_CCx_Disable);
    }
    return RT_EOK;
}


static rt_err_t pwm_set(TIM_TypeDef *htim, struct rt_pwm_configuration *configuration)
{
    rt_uint32_t period, pulse;
    rt_uint32_t tim_clock, psc;
    
    if((htim == TIM1) || (htim == TIM8))
    {
        rt_kprintf("The TIMX error\n");
        return RT_ERROR;
    }
    if((configuration->channel != TIM_Channel_1) && (configuration->channel != TIM_Channel_2) && 
        (configuration->channel != TIM_Channel_3) && (configuration->channel != TIM_Channel_4))
    {
        rt_kprintf("The TIMX Chx %d error\n",configuration->channel);
        return RT_ERROR;
    }
    TIM_SetAutoreload(htim,configuration->period);
    #ifdef BSP_USING_CH1
        TIM_SetCompare1(htim,configuration->pulse);
    #endif
    
    #ifdef BSP_USING_CH2
        TIM_SetCompare2(htim,configuration->pulse);
    #endif
    
    #ifdef BSP_USING_CH3
        TIM_SetCompare3(htim,configuration->pulse);
    #endif
    #ifdef BSP_USING_CH4
        TIM_SetCompare4(htim,configuration->pulse);
    #endif
    return RT_EOK;
}

static rt_err_t pwm_get(TIM_TypeDef *htim, struct rt_pwm_configuration *configuration)
{
    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->Instance,configuration,RT_TRUE);
        case PWM_CMD_DISABLE:
            return drv_pwm_enable(htim->Instance,configuration,RT_FALSE);
        case PWM_CMD_SET:
            return pwm_set(htim->Instance,configuration);
        case PWM_CMD_GET:
            return pwm_get(htim->Instance,configuration);
        default:
            return RT_EINVAL;
    }
}

TIM_HandleTypeDef htim;

//ĬÈÏ  TIM2 : ch1 = PA0,ch2 = PA1,ch3 = PA2,ch4 = PA3
static rt_err_t Timex_PWMChannelx_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //¸´ÓÃÍÆÍìÊä³ö
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    
    //³õʼ»¯TIMx
    
    htim.Init.TIM_Period = 0;
    htim.Init.TIM_Prescaler = 9;
    htim.Init.TIM_ClockDivision = 0;
    htim.Init.TIM_CounterMode = TIM_CounterMode_Up;
    
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //Ñ¡Ôñ¶¨Ê±Æ÷ģʽ:TIMÂö³å¿í¶Èµ÷ÖÆģʽ2
     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //±È½ÏÊä³öʹÄÜ
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //Êä³ö¼«ÐÔ:TIMÊä³ö±È½Ï¼«ÐÔ¸ß
    
    #ifdef BSP_USING_PWM3
        htim.Instance = TIM3;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    //ʹÄܶ¨Ê±Æ÷3ʱÖÓ
        #ifdef BSP_USING_CH1
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //ʹÄÜGPIOÍâÉèºÍAFIO¸´Óù¦ÄÜÄ£¿éʱÖÓ
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH2
            GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIO
            TIM_OC1Init(htim.Instance, &TIM_OCInitStructure);  //¸ù¾ÝTÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèTIM2 OC2
            TIM_OC1PreloadConfig(htim.Instance, TIM_OCPreload_Enable);  //ʹÄÜTIM3ÔÚCCR2ÉϵÄԤװÔؼĴæÆ÷
        #endif
        #ifdef BSP_USING_CH2
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //ʹÄÜGPIOÍâÉèºÍAFIO¸´Óù¦ÄÜÄ£¿éʱÖÓ
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM_CH2
            GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIO
            TIM_OC2Init(htim.Instance, &TIM_OCInitStructure);  //¸ù¾ÝTÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèTIM2 OC2
            TIM_OC2PreloadConfig(htim.Instance, TIM_OCPreload_Enable);  //ʹÄÜTIM3ÔÚCCR2ÉϵÄԤװÔؼĴæÆ÷
        #endif
        #ifdef BSP_USING_CH3
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  //ʹÄÜGPIOÍâÉèºÍAFIO¸´Óù¦ÄÜÄ£¿éʱÖÓ
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM_CH2
            GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIO
            TIM_OC3Init(htim.Instance, &TIM_OCInitStructure);  //¸ù¾ÝTÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèTIM2 OC2
            TIM_OC3PreloadConfig(htim.Instance, TIM_OCPreload_Enable);  //ʹÄÜTIM3ÔÚCCR2ÉϵÄԤװÔؼĴæÆ÷
        #endif
        #ifdef BSP_USING_CH4
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  //ʹÄÜGPIOÍâÉèºÍAFIO¸´Óù¦ÄÜÄ£¿éʱÖÓ
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM_CH2
            GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIO
            TIM_OC4Init(htim.Instance, &TIM_OCInitStructure);  //¸ù¾ÝTÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèTIM2 OC2
            TIM_OC4PreloadConfig(htim.Instance, TIM_OCPreload_Enable);  //ʹÄÜTIM3ÔÚCCR2ÉϵÄԤװÔؼĴæÆ÷
        #endif
    
    #endif
  
    TIM_TimeBaseInit(htim.Instance, &htim.Init);
 
    TIM_Cmd(htim.Instance, ENABLE); 
}

 

int drv_pwm_init(void)
{
#ifdef BSP_USING_PWM1
    MX_TIM1_Init();
    rt_device_pwm_register(rt_calloc(1, sizeof(struct rt_device_pwm)), "pwm1", &drv_ops, &htim1);
#endif

#ifdef BSP_USING_PWM3
    Timex_PWMChannelx_Config();
    rt_device_pwm_register(rt_calloc(1, sizeof(struct rt_device_pwm)), "pwm3", &drv_ops, &htim);
#endif
    return 0;
}
INIT_DEVICE_EXPORT(drv_pwm_init);

你可能感兴趣的:(stm32f103标准库+RT-Thread操作系统实现PWM驱动---1)