OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11855|回复: 8

求指导啊,我想用TIM4来做PWM

[复制链接]

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2013-6-30
在线时间
0 小时
发表于 2013-7-17 21:30:11 | 显示全部楼层 |阅读模式
书上写的是“要配置PA7为复用端口,因为TIM_CH2通道是以IO复用的形式连接到PA7上的”
如果我用TIM4_CH2通道,那该怎么设置?我还选哪个端口为复用端口?
还有就是我这个配置编的对吗?


TIM4->ARR=arr;//设定计数器自动重装值 
TIM4->SC=psc;//预分频器不分频
TIM4->CCMR1|=7<<12; //CH2 PWM2模式  
TIM4->CCMR1|=1<<11; //CH2预装载使能   

TIM4->CCER|=1<<4;   //OC2 输出使能   

TIM4->CR1=0x8000;   //ARPE使能 
TIM4->CR1|=0x01;    //使能定时器4
逐渐成长需要过程!!!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2013-6-30
在线时间
0 小时
 楼主| 发表于 2013-7-17 21:32:49 | 显示全部楼层
第一行写错了,应该是“要配置PA7为复用端口,因为TIM3_CH2通道是以IO复用的形式连接到PA7上的”
逐渐成长需要过程!!!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-7-17 22:57:33 | 显示全部楼层
看原理图哦.TIM4_CH2是连接在PB7上的
原理图一般都有写的,比如我们的原理图:



我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2013-6-30
在线时间
0 小时
 楼主| 发表于 2013-7-18 21:30:40 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
我终于知道原理图是这么看的!谢谢了大神~
逐渐成长需要过程!!!
回复 支持 反对

使用道具 举报

15

主题

53

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
283
金钱
283
注册时间
2013-4-19
在线时间
0 小时
发表于 2013-7-20 15:11:27 | 显示全部楼层
pwm.c


#include "pwm.h"
#include "led.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////  
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//定时器 驱动代码   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/4
//版本:V1.1
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved  
//********************************************************************************
//V1.1 20120904
//1,增加TIM3_PWM_Init函数。
//2,增加LED0_PWM_VAL宏定义,控制TIM3_CH2脉宽  
//////////////////////////////////////////////////////////////////////////////////  


//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =3;  //先占优先级3级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
}
}


//TIM3 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer3 部重映射 
   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; // PWM2 ~ PWM4

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO
 
   //初始化TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM3 Channel1 PWM模式  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
//初始化TIM3 Channel2 PWM模式  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
//初始化TIM3 Channel3 PWM模式  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC3Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
//初始化TIM3 Channel4 PWM模式  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC4Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
TIM_Cmd(TIM3, ENABLE);  //使能TIM3
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/*====== 通用定时器4中断初始化 ======*/
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器4!
void TIM4_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断

NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;  //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

TIM_Cmd(TIM4, ENABLE);  //使能TIMx外设  
}

/* ====== 定时器4中断服务程序 ======*/
void TIM4_IRQHandler(void)   //TIM4中断
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
}
}


/*====== TIM4 PWM 部分初始化 ======*/ 
// TIM4_CH1 PB6 PWM3 (heater)
// TIM4_CH2 PB7 PWM
// TIM4_CH4 PB8 PWM
// TIM4_CH4 PB9 PWM

//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM4_PWM_Init(u16 arr,u16 psc) 
{  
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
GPIO_PinRemapConfig(GPIO_Remap_TIM4, DISABLE); //TIM4复用功能映射  TIM4_CH2->B5    
   //设置该引脚为复用输出功能,输出TIM4 CH1的PWM脉冲波形 GPIOB.6
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
 
/*====== 初始化TIM4 ======*/
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位


/*====== 初始化TIM4 Channel1 PWM模式 Heater 12~17======*/ 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式1
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM_OCPolarity_High 输出极性:TIM输出比较极性高
// TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //TIM_OCPolarity_Low 输出极性:TIM输出比较极性低
TIM_OC1Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC1
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR1上的预装载寄存器
 
 /*=================================
/====== 初始化TIM4 Channel2 PWM模式 ======/  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
//TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //TIM_OCPolarity_Low 输出极性:TIM输出比较极性低
TIM_OC2Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC2
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR2上的预装载寄存器
 
/====== 初始化TIM4 Channel3 PWM模式 ======/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式3
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC3
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR3上的预装载寄存器
 
/====== //初始化TIM4 Channel4 PWM模式 ======/  
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式4
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC4Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC4
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR4上的预装载寄存器
 ===================================*/

TIM_Cmd(TIM4, ENABLE);  //使能TIM4
}




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
pwm.h





#ifndef __PWM_H
#define __PWM_H
#include "sys.h"

//////////////////////////////////////////////////////////////////////////////////  
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//定时器 驱动代码   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/4
//版本:V1.1
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved  
//********************************************************************************

void TIM3_Int_Init(u16 arr,u16 psc);  
void TIM3_IRQHandler(void);
void TIM3_PWM_Init(u16 arr,u16 psc);
void TIM4_Int_Init(u16 arr,u16 psc);
void TIM4_IRQHandler(void);
void TIM4_PWM_Init(u16 arr,u16 psc);


#endif







戰艦 2.8 吋螢幕 如換成 3.5 吋螢幕 請教問題1: 戰鑑库函数版本3.5吋觸控螢幕無法設成橫式顯示
回复 支持 反对

使用道具 举报

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2013-6-30
在线时间
0 小时
 楼主| 发表于 2013-7-20 18:51:05 | 显示全部楼层
回复【5楼】hmhuang98:
---------------------------------
虽然我用的是寄存器操作,不懂库函数,但还是很感谢你的回复!
逐渐成长需要过程!!!
回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2013-7-18
在线时间
0 小时
发表于 2013-7-20 20:47:45 | 显示全部楼层
回复【6楼】w348029046:
---------------------------------
楼主,你当初学stm32的时候,为什么会选择使用操作寄存器而不是库函数?
回复 支持 反对

使用道具 举报

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2013-6-30
在线时间
0 小时
 楼主| 发表于 2013-7-20 21:16:12 | 显示全部楼层
回复【7楼】海_海行者:
---------------------------------
因为我感觉寄存器好理解,学过51单片机后看STM32的寄存器操作的代码,我感觉上手还是挺快的,编写一些小程序的时候,用寄存器来的快一些
逐渐成长需要过程!!!
回复 支持 反对

使用道具 举报

15

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
132
金钱
132
注册时间
2013-4-27
在线时间
0 小时
发表于 2013-7-20 21:34:52 | 显示全部楼层
个人建议用库 但是一定得看看中文参考手册  理解  库的原理
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-17 13:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表