赞
踩
目录
- TIM5_PWM_Init(9999,143,TIM5);
-
- IM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
-
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
-
- 设置CCR寄存器
- void SetJointAngle(float angle)
- {
- angle=(u16)(50.0*angle/9.0+249.0);
- // 设置捕获比较寄存器1的值
- TIM_SetCompare1(TIM5,angle);
- }
定义:自动重装载值ARR=9999,预分频系数psc=143
设置自动重装值,当计数器的计数值=arr发生定时器中断,且计数器重新开始计数。
CNT计数器计数值被捕获/比较寄存器获取,当CNT的值=arr时,OCxREF信号极性发生反转,当指定OCx通道的高电平为有效电平时,OCxREF=1为有效电平,OCxREF=0为无效电平,并且会产生比较中断 CCxI,相应的标志位 CCxIF(SR 寄存器中)会置 位。然后 OCxREF 再经过一系列的控制之后就成为真正的输出信号 OCx/OCxN。
- /**********************************************************************************
- PWM初始化
- PWM 信号的频率的计算公式为:F = TIM_CLK/{(ARR+1)*(PSC+1)}。
- 其中 TIM_CLK 等于 72MHZ,ARR 即自动重装载寄存器的值。PSC 即计数器时钟的分频因子。
- PWM 输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。
- PWM 信号主要都是用来控制电机,一般的电机控制用的都是边沿对齐模式,FOC 电机一般用中心对齐模式
- CNT 工作在递增模式为例,在中,ARR=8,CCR=4,CNT 从 0 开始计数,当 CNT<CCR 的值时,OCxREF为有效的高电平于此同时,比较中断寄存器 CCxIF 置位。
- 当CCR=<CNT<=ARR 时,OCxREF 为无效的低电平。然后 CNT 又从 0 开始计数并生成计数器上溢事件,以此循环往复。
- 中心对齐模式:ARR=8,CCR=4。第一阶段计数器 CNT 工作在递增模式下,从 0 开始计数,当 CNT<CCR 的值时,OCxREF 为有效的高电平,当
- CCR=<CNT<<ARR 时,OCxREF 为无效的低电平。
- 第二阶段计数器 CNT 工作在递减模式从 ARR 的值开始递减,当 CNT>CCR 时,OCxREF 为无效的低电平,当 CCR=>CNT>=1时,OCxREF 为有效的高电平
- 模式 计数器 CNT 计算方式 说明
- PWM1 递增 CNT<CCR,通道 CH 为有效,否则为无效
- 递减 CNT>CCR,通道 CH 为无效,否则为有效
-
- PWM2 递增 CNT<CCR,通道 CH 为无效,否则为有效
- 递减 CNT>CCR,通道 CH 为有效,否则为无效
-
- 当使用 PWM 输入模式的时候,因为一个输入通道(TIx)会占用两个捕获通道(ICx),所以一个定时器在使用 PWM 输入的时候最多只能使用两个输入通道(TIx)。
- **********************************************************************************/
-
- void TIMx_PWM_Init(uint16_t OCMode,uint16_t OCPolarity,st_u8 CHx,TIM_TypeDef* TIMx)
- {
- // 定时器比较输出初始化结构体 TIM_OCInitTypeDef 用于输出比较模式,与 TIM_OCxInit 函数配合使用完成指定定时器输出通道初始化配置。高级控制定时器有四个定时器通道,使用时都必须单独设置。
- TIM_OCInitTypeDef TIM_OCInitStructure;
-
- //*--------------------输出比较结构体初始化-------------------*/
-
- TIM_OCInitStructure.TIM_OCMode = OCMode;//TIM_OCMode_PWM1;
- // 输出通道电平极性配置 它决定着定时器通道有效电平
- TIM_OCInitStructure.TIM_OCPolarity = OCPolarity;//TIM_OCPolarity_High;
- // 脉冲值,即输出都是低电平
- TIM_OCInitStructure.TIM_Pulse = 0;
- // 输出使能
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
-
- // 互补输出使能
- // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
-
-
-
- if(CHx==1){
- TIM_OC1Init(TIMx, &TIM_OCInitStructure);
- TIM_CtrlPWMOutputs(TIMx,ENABLE); //MOE 主输出使能
- TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable); //CH1预装载使
- }
- if(CHx==2){
- TIM_OC2Init(TIMx, &TIM_OCInitStructure);
- TIM_CtrlPWMOutputs(TIMx,ENABLE); //MOE 主输出使能 当使用的是通用定时器时,这句不需要
- TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);
- }
- if(CHx==3){
- TIM_OC3Init(TIMx, &TIM_OCInitStructure);
- TIM_CtrlPWMOutputs(TIMx,ENABLE); //MOE 主输出使能
- TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);
- }
- if(CHx==4){
- TIM_OC4Init(TIMx, &TIM_OCInitStructure);
- TIM_CtrlPWMOutputs(TIMx,ENABLE); //MOE 主输出使能
- TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);
- }
-
- //使能ARR、MOE及定时器
- TIM_ARRPreloadConfig(TIMx, ENABLE); //使能TIMx在ARR上的预装载寄存器 占空比
- TIM_Cmd(TIMx, ENABLE);
- }
-
- /******************************************************************************
- 定时器初始化函数
- STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),
- 4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM5、TIM6)
- 定时器时钟经过psc分频后得到驱动计数器计数的计数器时钟(CK_CNT)
- CK_CNT=TIMxCLK/(PSC+1).
- 计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达
- 到自动重装载寄存器的时候产生更新事件,并清零从头开始计数.
- 自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数
- 值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断.
- 定时器的定时时间等于计数器的中断周期乘以中断的次数。
- 计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1))
- 产生一次中断的时间则等于:1/(CK_CLK * ARR)
- 中断服务程序中设置一个变量TIME,记录中断次数,则定时时间:1/CK_CLK * (ARR+1)*time
- *******************************************************************************/
- void TIMx_Init(st_u32 RCC_APB1Periph,st_u16 per,st_u16 psc,st_u16 clk_div,st_u16 Count_mode,TIM_TypeDef* TIMx)
- {
- /*uint32_t RCC_APB1Periph = RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3|RCC_APB1Periph_TIM4
- |RCC_APB1Periph_TIM5|RCC_APB1Periph_TIM6|RCC_APB1Periph_TIM7;*/
- // 定时器结构体
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
-
- //使能定时器时钟 TIM5
- RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
-
- // 设置自动重装载寄存器周期的值 计数到5000为500ms
- // 计数一次的时间1/(TIMxCLK/(PSC+1))=1/1000
- // 定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535。
-
- TIM_TimeBaseInitStructure.TIM_Period = per;
-
- // 设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
- // 定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定
- // TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1 至 65536 分频。
- TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
-
- // 时钟分割 设置时钟分割:TDTS = Tck_tim
- // 时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟
- // 频率分频比,基本定时器没有此功能,不用设置。
- TIM_TimeBaseInitStructure.TIM_ClockDivision =clk_div ;
-
- // 计数模式 TIM向上计数模式
- // 可是在为向上计数(TIM_CounterMode_Up)、向下计数(TIM_CounterMode_Down)以及三种中心对齐模式。TIM_CounterMode_CenterAligned1 TIM_CounterMode_CenterAligned2 TIM_CounterMode_CenterAligne3
- // 基本定时器只能是向上计数,即 TIMx_CNT 只能从 0 开始递增,并且无需初始化。
- TIM_TimeBaseInitStructure.TIM_CounterMode = Count_mode;
-
- TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStructure);
- //TIM_Cmd(TIMx, ENABLE);
- }
-
- #include "public.h"
-
- void PWM_Init(uint16_t arr,uint16_t psc)
- {
- #if 0
- /*************************引脚初始化***************************************/
- // PA0 DJ TIM5_CH1
- GPIOInit(DJ_PORT,DJ_PIN,GPIO_Mode_AF_PP,DJ_RCC);
-
- // PB6 DJ2 TIM4_CH1
- // GPIOInit(DJ2_PORT,DJ2_PIN,GPIO_Mode_AF_PP,DJ2_RCC);
- // PA6 DJ3 TIM3_CH1
- // GPIOInit(DJ3_PORT,DJ3_PIN,GPIO_Mode_AF_PP,DJ3_RCC);
-
- /**************************定时器配置***************************************/
-
- TIMx_Init(RCC_APB1Periph_TIM5,arr, psc,0,TIM_CounterMode_Up,TIM5);
-
- // TIMx_Init(RCC_APB1Periph_TIM4,arr, psc,0,TIM_CounterMode_Up,TIM4);
-
- // TIMx_Init(RCC_APB1Periph_TIM3,arr, psc,0,TIM_CounterMode_Up,TIM3);
-
- /***************************PWM输出比较引脚**********************************/
-
- TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,CH1,TIM5);
- TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,CH2,TIM5);
- //TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,1,TIM4);
- //TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,1,TIM3);
-
- //TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,2,TIM5);
- //TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,2,TIM4);
- //TIMx_PWM_Init(TIM_OCMode_PWM1,TIM_OCPolarity_High,2,TIM3);
- #else
- //定义初始化结构体
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
-
- //使能定时器时钟 TIM5
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
- //使能GPIOA外设时钟使能
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- //初始化GPIO
- //设置服用输出功能TIM5
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //TIM5 PA0
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- //初始化时基
- //设置在下一个更新事件装入活动的自动重装载寄存器周期值50HZ
- TIM_TimeBaseStructure.TIM_Period = arr;
- //设置用来作为TIMx时钟频率除数的预分频值 不分频
- TIM_TimeBaseStructure.TIM_Prescaler =psc;
- //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- //TIM向上计数模式
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
- TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
- //输出模式配置
- //选择定时器模式:TIM脉冲宽度调制模式1
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- //比较输出使能
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = 0;//设置待装入捕获比较寄存器的脉冲值
- //输出极性:TIM输出比较级性高
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
- TIM_OC1Init(TIM5, &TIM_OCInitStructure);
-
- TIM_CtrlPWMOutputs(TIM5,ENABLE); //MOE 主输出使能
-
- TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable); //CH1预装载使能
-
- TIM_OC2Init(TIM5, &TIM_OCInitStructure);
-
- //使能ARR、MOE及定时器
- TIM_ARRPreloadConfig(TIM5, ENABLE); //使能TIMx在ARR上的预装载寄存器
- TIM_Cmd(TIM5, ENABLE); //使能TIM4
- #endif
-
- }
-
-
- // 设置CCR寄存器的值
- void SetJointAngle(st_u8 ID, float angle)
- {
- switch(ID)
- {
- case 0: //-90°~90°
- // 设置TIMx Capture Compare1寄存器值
- angle=(u16)(50.0*angle/9.0+249.0);
- TIM_SetCompare1(TIM5,angle);
- break;
- //0°~180°
- case 1:
- angle=(u16)(4.175*angle+409.25);
- TIM_SetCompare2(TIM3,angle);
- break;
-
-
- case 2: //-150°~0°
- angle=-angle;
- angle=(u16)(4.175*angle+480.0);
- TIM_SetCompare1(TIM4,angle);
- break;
-
- case 3:
- angle=-180-angle;
- angle=-angle;
- angle=(u16)(4.175*angle+315.0);
-
-
- TIM_SetCompare2(TIM4,angle);
- break;
- //-90°~90°
- case 4:
- angle=90.0+angle;
- angle=(u16)(249.0+50.0*angle/9.0);
- TIM_SetCompare3(TIM4,angle);
- break;
-
-
- default: break;
- }
- }
- /*
- * File : board.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2017-07-24 Tanek the first version
- */
- #include <rthw.h>
- #include <rtthread.h>
- #include "board.h"
-
-
- #ifdef __CC_ARM
- #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
- #define RT_HEAP_SIZE 1024
- //从内部SRAM里面分配一部分静态内存来作为rtt的堆空间,这里配置为4KB
- static uint32_t rt_heap[RT_HEAP_SIZE];
- RT_WEAK void *rt_heap_begin_get(void)
- {
- return rt_heap;
- }
-
- RT_WEAK void *rt_heap_end_get(void)
- {
- return rt_heap + RT_HEAP_SIZE;
- }
- #endif
- #endif
-
- extern uint8_t OSRunning;
-
-
-
- /**
- * This function will initial your board.
- */
- void rt_hw_board_init()
- {
- SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
- SysTick_Init(72);
- LED_Init();
- uart_init(115200);
- /*
- PWM频率=72/(arr+1)(psc+1)=50Hz T=1/F=0.02s=20ms=20 000us 每秒50次
- 计数10000 用20ms 计数一次0.002ms
-
- 舵机参数:
- 工作电压:4.8V-6V
- 位置等级:1024级
- 脉冲控制精度为2us
-
- // 设置高电平的持续时间
- TIM_SetCompare1(TIM5,angle);
- 软件
- 0.5ms-------------0度; 2.5% 计数250次 249(arr+1) 250/10000=2.5% 0.5ms=20ms/10000次*angle
- 1.0ms------------45度; 5.0% 计数500次 499
- 1.5ms------------90度; 7.5% 计数750次 749
- 2.0ms-----------135度; 10.0% 计数2000次
- 2.5ms-----------180度; 12.5% 计数2500次
- 调节占空比 angle/9999+1
-
-
- */
- //TIM2_Init(5000,7199);
- //TIM4_PWM_Init(7199,0);
- PWM_Init(9999,143);
-
-
- OSRunning=1;
-
- /* Call components board initial (use INIT_BOARD_EXPORT()) */
- #ifdef RT_USING_COMPONENTS_INIT
- rt_components_board_init();
- #endif
-
- #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
- rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
- #endif
-
- #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
- rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
- #endif
- }
-
- void SysTick_Handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
-
- /* 更新时基 */
- rt_tick_increase();
-
- /* leave interrupt */
- rt_interrupt_leave();
- }
-
- //重映射串口1到rt_kprintf
- void rt_hw_console_output(const char *str)
- {
- /* 进入临界段 */
- rt_enter_critical();
- /* 直到字符串结束 */
- while(*str!='\0')
- {
- if(*str=='\n')
- {
- USART1->DR = (u8) '\r';
- while((USART1->SR&0X40)==0);
- }
- USART1->DR =*str++;
- while((USART1->SR&0X40)==0);
- }
- /* 退出临界段 */
- rt_exit_critical();
- }
- #define ROOT
- #include "public.h"
- /*************************其他控制量******************************/
-
-
- #if 0
- void ST_MCU(void)
- {
- #ifdef TIM
- RCC_PCLK1Config(RCC_HCLK_Div4); // HCLK/4 = 72/4
- RCC_PCLK2Config(RCC_HCLK_Div4);
- TIM2Init();
- #else
- TIM4_Init(1000,36000-1); //定时500ms
- #endif
- }
- #endif
- /*************************定义线程控制块******************************/
- static rt_thread_t led1_thread=RT_NULL;
- static rt_thread_t test_thread=RT_NULL;
-
-
- /*************************线程主体函数******************************/
- static void led1_thread_entry(void*parameter);
- static void test_thread_entry(void*parameter);
-
-
-
- int main(void)
- {
- #ifdef LED_DEBUG
- // 创建led线程
- led1_thread = rt_thread_create("led",
- led1_thread_entry,
- RT_NULL,
- 512,
- 3,
- 20);
-
- // 启动线程,开启调度
- if(led1_thread!=RT_NULL)
- rt_thread_startup(led1_thread);
- else
- return -1;
- #endif
-
- test_thread = rt_thread_create("test",test_thread_entry,RT_NULL,512,3,30);
-
- // 启动线程,开启调度
- if(test_thread!=RT_NULL)
- rt_thread_startup(test_thread);
- else
- return -1;
- }
-
- //LED1线程
- static void led1_thread_entry(void* parameter)
- {
- while(1)
- {
- LED1=~LED1;
- rt_thread_delay(500); /* 延时200个tick */
- LED0=~LED0;
- rt_thread_delay(500); /* 延时200个tick */
-
- }
- }
-
-
- static void test_thread_entry(void*parameter)
- {
-
- // ultrasonic_test();
- while(1){
-
- SetJointAngle(0,90);
- delay_ms(300);
- // TIM_SetCompare1(TIM5,angle);
- SetJointAngle(0,5);
- delay_ms(300);
-
- SetJointAngle(0,175);
- delay_ms(300);
- }
- }
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。