如何利用stm32的中断和计数器即西门子上升沿和下降沿下降沿捕获电平时长

如何利用stm32的中断和计数器即上升沿下降沿捕获电平时长
> 如何利用stm32的中断和计数器即上升沿下降沿捕获电平时长
如何利用stm32的中断和计数器即上升沿下降沿捕获电平时长
/*************************************************************名称: Timer4_CFG() 72M时钟晶振功能: 初始化timer4
100us定时发生器输出参数:作者:v******************************************************************/void Timer4_CFG(){TIM_TimeBaseInitTypeDef TIM_TimeBaseSRCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);GPIO_InitTypeDef GPIO_InitSTIM_TimeBaseStructure.TIM_Prescaler = 3599; //TIM_CKD_DIV1 72MHz/( 000 HZ 50uSTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM_TimeBaseStructure.TIM_Period = 200;
// ARR基准值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//TIM_PrescalerConfig(TIM4,35,TIM_PSCReloadMode_Immediate);//TIM_ARRPreloadConfig(TIM4,DISABLE);TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);TIM_ITConfig(TIM4,TIM_IT_Trigger,ENABLE);TIM_Cmd(TIM4, DISABLE);}/*************************************************************名称 ;外部中断函数 启用第12个中断源 作为中断引脚功能:
中端配置初始化 引脚初始化输出参数:无作者:v******************************************************************/void EXTIX_Init(void){EXTI_InitTypeDef EXTI_InitS
NVIC_InitTypeDef NVIC_InitSGPIO_InitTypeDef GPIO_InitSRCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO , ENABLE);GPIO_InitStructure.GPIO_Pin = IR_LED_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(IR_LED_PORT, &GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOE ,GPIO_PinSource12);EXTI_InitStructure.EXTI_Line = EXTI_Line12;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_IEXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_F //上升下降沿都触发中断EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
//中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//强占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//次优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//通道中断不使能,有切换需要的时候使能
NVIC_Init(&NVIC_InitStructure);}#if 0/*************************************************************名称: Remote_Scan()功能:输出参数:作者:v******************************************************************/static u8 Remote_Scan(){u16 TIMt=0;u16//超时退出u8 i,if(RDATA()!=0)//先判断是否为0 排除干扰{return 0;}
TIM_SetCounter(TIM4,0);//TIM4->CNT=0;TIM_Cmd(TIM4, ENABLE);waitquit=60000;do{waitquit--;}while((!RDATA())&&(waitquit));//检查高电平的时间4msTIM_Cmd(TIM4, DISABLE);TIMt=TIM_GetCounter(TIM4);if((TIMt120)){return 0;}TIM_SetCounter(TIM4,0); TIM_Cmd(TIM4, ENABLE);waitquit=60000;do{waitquit--;}while((RDATA())&&( waitquit));//接收高电平TIMt=TIM_GetCounter(TIM4);TIM_Cmd(TIM4, DISABLE);if((TIMt>120)||(TIMt<60))//同样 4MS{return 0;}////////////引导码接收完毕///////开始接收客户码//////////////////////////////for(i=0;i<3;i++)//接收3个字节 24位码{for(ia=0;ia<8;ia++){TIM_Cmd(TIM4, ENABLE);while(!RDATA());//等待高TIM_SetCounter(TIM4,0);waitquit=60000;//可根据实测调整do{waitquit--;}while((RDATA())&&( waitquit));//接收高电平TIM_Cmd(TIM4, DISABLE);TIMt=TIM_GetCounter(TIM4);////////////////////////////高电平结束/////////////////////////user_code[i]>>=1;if((TIMt>45)){return 0;}if((TIMt>35)&&(TIMt<45))//经过实测 在2ms以上为1 小于一般为 9 为0{user_code[i]|=0x80;}}}REM_FLG=1;return 1;}#endif/************************************************* Function:
EXTI15_10_IRQHandler Description:
F103切换信号中断 Input:
无 Output:
无 Return:
无 Others:
需要切换时,打开此中断*************************************************/#if 1u8 EXTI15_10_IRQHandler(){//NVIC_InitTypeDef NVIC_InitSif(EXTI_GetITStatus(EXTI_Line14)!= RESET){EXTI_ClearITPendingBit(EXTI_Line14);//调用康工切换函数,g_SDISrc,g_SDIDst//UserSwitch(g_SW_Src,g_SW_Dst); ////GPIO_SetBits(GPIOE,GPIO_Pin_6);/* Enable the EXTI15 Interrupt for 控制板F103*///NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //中断通道//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//强占优先级//NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//次优先级//NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; //通道中断不使能,有切换需要的时候使能//NVIC_Init(&NVIC_InitStructure);}if(EXTI_GetITStatus(EXTI_Line12)!= RESET){if(RDATA()==0)//说明是下降沿到来{
TIM_Cmd(TIM4, ENABLE);if(lead_flg==0)//说明是第一次接收引导码{TIM_SetCounter(TIM4,0);//TIM4->CNT=0; (1)
lead_flg=1;}else if(lead_flg==2){
ir_cnt= TIM_GetCounter(TIM4);
TIM_SetCounter(TIM4,0);lead_flg=3;if((ir_cnt90))//测试表明为79 或80{lead_flg=0; //超出范围 退出
}}else if(lead_flg==3)//获得高电平时间{ir_cnt= TIM_GetCounter(TIM4);TIM_SetCounter(TIM4,0);//接收3个字节 24位码
high_cnt++;//加到24位
每8次为1个字节
if(high_cnt<=8){user_code[0]>>=1;}
if(high_cnt<=16){user_code[1]>>=1;}
if(high_cnt<=24){user_code[2]>>=1;}
if((ir_cnt>35)&&(ir_cnt<45))//我们认为是 bit 1 2ms{
if(high_cnt<=8){user_code[0]|=0x80;}
if(high_cnt<=16){user_code[1]|=0x80;}
if(high_cnt<=24){user_code[2]|=0x80;}
if(high_cnt>24)//说明接受完毕{lead_flg = 0;high_cnt = 0;REM_FLG = 1;//采集完毕 清除标志位TIM_Cmd( TIM4,DISABLE);}
}}else if(RDATA()!=0)//说明是第一次接收引导码的高电平{
if(lead_flg==0)
else if(lead_flg==1)//我们只接受一次低电平即可
{ir_cnt= TIM_GetCounter(TIM4);TIM_SetCounter(TIM4,0);lead_flg=2;if((ir_cnt90)){lead_flg=0;//不是我们要的 退出
}}else if(lead_flg==3)//非引导码进入中断
上升沿触发的{
ir_cnt= TIM_GetCounter(TIM4);TIM_SetCounter(TIM4,0);if((ir_cnt20))//测试数据为 ir_cnt =9 10 稳定值 0.5ms{lead_flg=0;
return 0;//不是我们要的 退出
}}}}EXTI_ClearITPendingBit(EXTI_Line12);}本文引用地址:
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(6360)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'STM32 计数器模式',
blogAbstract:'&输入捕获模式
库函数例程位置: STM32F10x_StdPeriph_Lib_V3.3.0\\Project\\STM32F10x_StdPeriph_Examples\\TIM\\InputCapture
在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当捕获事件发生时,相应的CCxIF标志(TIMx_SR寄存器)被置’1’,如果使能了中断或者DMA操作,则将产生中断或者DMA操作。
在捕获模式下,捕获发生在影子寄存器上,然后再复制到预装载寄存器中。',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:4,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}查看: 12633|回复: 0
stm32的定时器输入捕获与输出比较
本帖最后由 lianyiqun 于
18:18 编辑
& &明确一点对比AD的构造,stm32有3个AD,每个AD有很多通道,使用哪个通道就配置成哪个通道,这里定时器也如此,有很多定时器TIMx,每个定时器有很多CHx(通道),可以配置为输入捕捉-------测量频率用,也可以配置为输出比较--------输出PWM使用
输入捕捉:可以用来捕获外部事件,并为其赋予时间标记以说明此事件的发生时刻。
外部事件发生的触发信号由单片机中对应的引脚输入(具体可以参考单片机的datasheet),也可以通过模拟比较器单元来实现。
时间标记可用来计算频率,占空比及信号的其他特征,以及为事件创建日志,主要是用来测量外部信号的频率。
输出比较:定时器中计数寄存器在初始化完后会自动的计数。从bottom计数到top。并且有不同的工作模式。
另外还有个比较寄存器。一旦计数寄存器在从bottom到top计数过程中与比较寄存器匹配则会产生比较中断(比较中断使能的情况下)。
然后根据不同的工作模式计数寄存器将清零或者计数到top值。<font color="#、朋友,可以解释一下输入捕获的工作原理不?很简单,当你设置的捕获开始的时候,cpu会将计数寄存器的值复制到捕获比较寄存器中并开始计数,当再次捕捉到电平变化时,这是计数寄存器中的值减去刚才复制的值就是这段电平的持续时间,你可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获。它没多大用处,最常用来测频率。 计数寄存器的初值,是自己写进去的吗?是的,不过默认不要写入 我如果捕获上升沿,两个值相减,代表的时两个上升沿中间那段电平的时间。对不?是的 timer1有五个通道(对应五个IO引脚),在同一时刻,只能捕获一个引脚的值,对不?那是肯定的,通道很像ADC通道,是可以进行切换的。 那输出比较的原理你可以帮我介绍一下不?这里有两个单元:一个计数器单元和一个比较单元,比较单元就是个双缓冲寄存器,比较单元的值是可以根据不同的模式设置的,与此同时,计数器在不停的计数,并不停的与比较寄存器中的值进行比较,当计数器的值与比较寄存器的值相等的时候一个比较匹配就发生了,根据自己的设置,匹配了是io电平取反、变低、还是变高,就会产生不同的波形了。 比较单元的值是人为设进去的吧?是的,但是他要根据你的控制寄存器的配置,来初始化你的比较匹配寄存器。
上面这个总看不懂,好像不不止你说的那几种情况:“匹配了是io电平取反、变低、还是变高,就会产生不同的波形了”就是比较匹配了你要IO电平怎么办?是清0还是置1?还是怎么样?这样才能产生波形啊 要不然你要比较单元有什么用呢? 设置输出就是置1,清除输出就是置0,切换输出就是将原来的电平取反,对不?是的 你理解的很快
<font color="#1:计数器向上计数达到最大值时将引脚置1,达到0时,引脚电平置0,,对不?恩 定时器1的输出比较模式怎么用。利用这个功能输出一个1KHZ,占空比为10%的程序怎么写啊?求高人指点1、陪定时器1的功能为特殊功能,不是普通IO&&在PERCFG这里
2、P1SEL引脚选择
3、P1DIR设为输出
4、T3CC0设置周期
5、T3CC1设置占空比
6、T3CCTL0 设置通道0
7、T3CCTL1 设置通道1
8、T3CTL设为模模式
9、用T3CTL打开即可************以下是用定时器做频率源,用定时器测量该频率的应用程序!!!***********调试STM32的定时器好几天了,也算是对STM32的定时器有了点清楚的认识了。我需要测量4路信号的频率然后通过DMA将信号的频率传输到存储器区域,手册说的很明白每个定时器有4个独立通道。然后我就想能不能将这4路信号都连接到一个定时器的4个通道上去。理论上应该是行的通的。刚开始俺使用的是TIM2的123通道,TIM4的2通道来进行频率的测量。由于没有频率发生器,所以我用tim3作为信号源,用TIM2,TIM4来进行测量就ok了(刚好4个通道了)。  请看一开始的程序,以TIM2的1,3通道为例子(2通道设置方法一样):  TIM_ICInitStructure.TIM_ICMode =TIM_ICMode_ICAP;& && && && && & //配置为输入捕获模式& && && &  TIM_ICInitStructure.TIM_Channel =TIM_Channel_1;& && && && && && &&&//选择通道1  TIM_ICInitStructure.TIM_ICPolarity =TIM_ICPolarity_R& && &//输入上升沿捕获   TIM_ICInitStructure.TIM_ICSelection =TIM_ICSelection_DirectTI;& &//通道方向选择&&  TIM_ICInitStructure.TIM_ICPrescaler =TIM_ICPSC_DIV1;& && && && &&&//每次检测到捕获输入就触发一次捕获  TIM_ICInitStructure.TIM_ICFilter =0x0;& && && && && && && && && &//滤波  TIM_ICInit(TIM2, &TIM_ICInitStructure);& &//TIM2通道1配置完毕   TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP;& &&&//配置为输入捕获模式& &&&  TIM_ICInitStructure.TIM_Channel =TIM_Channel_3;& && && && && &&&//选择通道3  TIM_ICInitStructure.TIM_ICPolarity =TIM_ICPolarity_R& && &//输入上升沿捕获   TIM_ICInitStructure.TIM_ICSelection =TIM_ICSelection_DirectTI;&&//& &  TIM_ICInitStructure.TIM_ICPrescaler =TIM_ICPSC_DIV1;& && && && & //每次检测到捕获输入就触发一次捕获   TIM_ICInitStructure.TIM_ICFilter = 0x0;& && && && & //滤波  TIM_ICInit(TIM2, &TIM_ICInitStructure);& &//TIM2通道3配置完毕   以上是输入捕获配置  还需要做的工作就是(参考stm32参考手册的TIM的结构框图):     &&TIM_SelectInputTrigger(TIM2,TIM_TS_TI1FP1);& && && && && && && &//参考TIM结构图选择滤波后的TI1输入作为触发源,触发下面程序的复位     &&TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);& && && &//复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号     &&TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);& && &   //主从模式选择  这样我们就可以很轻松的就得到了连接在TIM2的通道1上的信号的频率,但是3通道的频率的值永远都是跳动的不准,测试了半天也没有找到根本原因,请看TIM的结构框图的一部分  红色箭头所指,这才找到原因,触发的信号源只有这四种,而通道3上的计数器的值不可能在接受到信号的上升沿时候,有复位这个动作,找到原因了。这就是3通道上的数据不停跳动的原因,要想得到信号的频率也是有办法的,可以取连续两次捕捉的值之差,这个值就是信号的周期,自己根据实际情况去算频率吧。  有以上可以得到:  stm32的TIM2的四个通道可以同时配置成输入捕捉模式,但是计算CH3,CH4信号的频率步骤有点繁琐(取前后捕捉的差值),但是他的CH1,和CH2可以轻松得到:  通道1     &&TIM_SelectInputTrigger(TIM2,TIM_TS_TI1FP1);& && && && && && && &//参考TIM结构图选择滤波后的TI1输入作为触发源,触发下面程序的复位     &&TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);& && && &//复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号  TIMx-&CRR1的值即为信号的周期  通道2:  &&TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2);& && && && && && &&&//参考TIM结构图选择滤波后的TI1输入作为触发源,触发下面程序的复位      &&TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);& && && &//复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号  TIMx-&CRR2的值即为信号的周期
STM32的定时器外设功能强大得超出了想像力,STM32一共有8个都为16位的定时器。其中TIM6、TIM7是基本定时器;TIM2、TIM3、TIM4、TIM5是通用定时器;TIM1和TIM8是高级定时器。这些定时器使STM32具有定时、信号的频率测量、信号的PWM测量、PWM输出、三相6步电机控制及编码器接口等功能,都是专门为工控领域量身订做的。
& && & 基本定时器:具备最基本的定时功能,下面是它的结构:
我们来看看它的启动代码:
void TIM2_Configuration(void)
{&& 基本定时器TIM2的定时配置的结构体(包含定时器配置的所有元素例如:TIM_Period= 计数值)
& &TIM_TimeBaseInitTypeDef&&TIM_TimeBaseS
& &设置TIM2_CLK为72MHZ(即TIM2外设挂在APB1上,把它的时钟打开。)& && &
& &RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 ,ENABLE);
& &设置计数值位1000
& &TIM_TimeBaseStructure.TIM_Period=1000;
& &将TIM2_CLK为72MHZ除以72 = 1MHZ为定时器的计数频率
& &TIM_TimeBaseStructure.TIM_Prescaler= 71;
& &这个TIM_ClockDivision是设置时钟分割,这里不分割还是1MHZ的计数频率
& &TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
& &设置为向上计数模式;(计数模式有向上,向下,中央对齐1,中央对齐2,中央对齐3)
& &TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
& &将配置好的设置放进stm32f10x-tim.c的库文件中
& & TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
& &清除标志位
& & TIM_ClearFlag(TIM2,TIM_FLAG_Update);
& &使能TIM2中断
& &TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
& &使能TIM2外设& && &
& & TIM_Cmd(TIM2,ENABLE);& && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && &
& && &通用定时器:就比基本定时器复杂得多了。除了基本的定时,它主要用在测量输入脉冲的频率、脉冲宽与输出PWM脉冲的场合,还具有编码器的接口。
我们来详细讲解:如何生成PWM脉冲
通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。
这里直接举例说明定时器的PWM输出工作过程:若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR(相当于库函数写法的TIM_Period的值N)被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。
而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平),相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。
如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为A/(N+1)。
如果不想看的可以直接看我标注的红色字体,就大体可以理解。
下面我们来编写具体代码和讲解:
void TIM3_GPIO_Config(void)
{配置TIM3复用输出PWM的IO
&&GPIO_InitTypeDefGPIO_InitS
&&打开TIM3的时钟
&&RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
&&打开GPIOA和GPIOB的时钟
&&RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB, ENABLE);
&&配置PA6.PA7的工作模式
&&GPIO_InitStructure.GPIO_Pin=&&GPIO_Pin_6 |GPIO_Pin_7;
&&GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;& && &
&&GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
&&GPIO_Init(GPIOA,&GPIO_InitStructure);
&&配置PB0.PB1的工作模式
&&GPIO_InitStructure.GPIO_Pin=&&GPIO_Pin_0 |GPIO_Pin_1;
&&GPIO_Init(GPIOB,&GPIO_InitStructure);
void TIM3_Mode_Config(void)
& && & TIM_TimeBaseInitTypeDef&&TIM_TimeBaseS//初始化TIM3的时间基数单位
& && & TIM_OCInitTypeDef&&TIM_OCInitS//初始化TIM3的外设
& && &&&u16 CCR1_Val= 500;& && &
& && &&&u16 CCR2_Val= 375;
& && &&&u16 CCR3_Val= 250;
& && &&&u16 CCR4_Val= 125;//PWM信号电平跳变值(即计数到这个数值以后都是低电平之前都是高电平)
&&TIM3的时间基数单位设置(如计数终止值:999,从0开始;计数方式:向上计数)& && &
&&TIM_TimeBaseStructure.TIM_Period= 999;& && &
&&TIM_TimeBaseStructure.TIM_Prescaler= 0;& && && &
&&TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1 ;& && &
&&TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;
&&TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
&&TIM3的外设的设置
&&TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1;& && &//TIM脉冲宽度调制模式1& &
&&TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_E//这个暂时不知道,stm32固件库里没有搜到。应该是定时器输出声明使能的意思& && &
&&TIM_OCInitStructure.TIM_Pulse =CCR1_V//设置了待装入捕获比较寄存器的脉冲值& && &
&&TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_H //TIM输出比较极性高
&&TIM_OC1Init(TIM3,&TIM_OCInitStructure);
&&TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
&&下面3路PWM输出和上面的一样不再解说
&&TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_E
&&TIM_OCInitStructure.TIM_Pulse =CCR2_V& && &
&&TIM_OC2Init(TIM3,&TIM_OCInitStructure);& && &
&&TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
&&TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_E
&&TIM_OCInitStructure.TIM_Pulse =CCR3_V& && &
&&TIM_OC3Init(TIM3,&TIM_OCInitStructure);& && &
&&TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
&&TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_E
&&TIM_OCInitStructure.TIM_Pulse =CCR4_V& && &
&&TIM_OC4Init(TIM3,&TIM_OCInitStructure);& && &
&&TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
&&TIM_ARRPreloadConfig(TIM3,ENABLE);& && & //使能TIM3重载寄存器ARR& && && &&&
&&TIM_Cmd(TIM3,ENABLE);//使能TIM3& && && &
太累了边看边写都这个点了日0:24:13在自己床上写的。下面是看看我们程序达到的4路PWM的效果:
可以看到明显占空比不同的4路pwm波。
这一节终于讲完,个人觉得敲一遍代码学起来还是蛮容易懂的。希望看到的人也能搞懂。
最后补充一点pwm具体能干什么?&&特别是对广大电子DIY爱好者的应用:
智能小车的电机控制:我们可以利用pwm来控制我们的智能小车的车速;
机器人:给“机器人关节”舵机周期一定(我以前玩过具体多少毫秒忘记了)pwm波就可以控制舵机的转动角度了;
呼吸灯:输入不同的pwm波就可以达到明暗渐明渐暗的效果。
还有别的应用大家一起发挥想象力给予补充。我们可以一起交流,希望大家支持。
Powered by21ic官方微信-->
后使用快捷导航没有帐号?
查看: 5662|回复: 11
在STM32F051的EXTI的ISR中怎么分辨是上升沿还是下降沿触发的中断
&&已结帖(20)
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
extern void KEYS_Init(void)
& & & & GPIO_InitTypeDef GPIO_InitS
& & & & EXTI_InitTypeDef EXTI_InitS
& & & & NVIC_InitTypeDef NVIC_InitS
& & & & /* config the extiline(PB0) clock and AFIO clock */
& & & & RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
& & & & RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
& & & && &
& & & & /* Configyre P[A|B|C|D|E]0&&NIVC&&*/
& & & & NVIC_InitStruct.NVIC_IRQChannel = EXTI4_15_IRQn;
& & & & NVIC_InitStruct.NVIC_IRQChannelPriority = 0x00;
& & & & NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
& & & & NVIC_Init(&NVIC_InitStruct);
& & & & /* EXTI line gpio config(PF7) */& & & &
& & & & GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
& & & & GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
& & & & GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_2;
& & & & GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
& & & & GPIO_Init(GPIOF, &GPIO_InitStruct);
& & & & /* EXTI line(PF7) mode config */
& & & & SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOF, EXTI_PinSource7);
& & & & EXTI_InitStruct.EXTI_Line = EXTI_Line7;
& & & & EXTI_InitStruct.EXTI_Mode = EXTI_Mode_I
& & & & EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_F//EXTI_Trigger_F// | EXTI_Trigger_R
& & & & EXTI_InitStruct.EXTI_LineCmd = ENABLE;
& & & & EXTI_Init(&EXTI_InitStruct);
我设置了PF7为外部中断,触发方式为上升沿和下降沿。在ISR里面,我需要对上升沿和下降沿有不同的处理,所以需要分辨当前触发了中断时是上升沿还是下降沿,不知道代码怎么写,最好是用到固件库的方式,不要直接操作寄存器,这样移植性好点。现在我正在找合适的范例,不知道找不找得到。
满意回复+10
在ISR中读IO电平
嗯楼上的办法不错, 如果还担心误判, 可以只设置 EXTI_Trigger_Rising, EXTI_Trigger_Falling 的一种, 在中断服务中修改这个设置. ...
是不是可以进入中断后用GPIO_ReadInputDataBit读一下信号引脚电平,SET 或 RESET?
设置成EXTI_Trigger_Rising_Falling触发,中断程序再判断是IO的当前电平,就知道是上升沿还是下降沿了;
2,3楼都不错
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
中级工程师, 积分 3309, 距离下一级还需 1691 积分
中级工程师, 积分 3309, 距离下一级还需 1691 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
中级工程师, 积分 3309, 距离下一级还需 1691 积分
中级工程师, 积分 3309, 距离下一级还需 1691 积分
EXTI_Trigger_Rising_Falling是1种,应该还有EXTI_Trigger_Rising和EXTI_Trigger_Falling
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
高级工程师, 积分 5365, 距离下一级还需 2635 积分
高级工程师, 积分 5365, 距离下一级还需 2635 积分
主题帖子积分
专家等级:结帖率:60%
主题帖子积分
高级工程师, 积分 5365, 距离下一级还需 2635 积分
高级工程师, 积分 5365, 距离下一级还需 2635 积分
在ISR中读IO电平
以太网 WIFI 音乐 语音 DLAN airplay&&玩具 音箱
主题帖子积分
---------------------
主题帖子积分
---------------------
专家等级:结帖率:98%打赏:0.00受赏:43.00
主题帖子积分
---------------------
嗯楼上的办法不错, 如果还担心误判, 可以只设置 EXTI_Trigger_Rising, EXTI_Trigger_Falling 的一种, 在中断服务中修改这个设置.
欢迎进入 !
主题帖子积分
主题帖子积分
专家等级:结帖率:46%打赏:135.80受赏:32.50
主题帖子积分
2,3楼都不错
←← +→→←←
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
aozima 发表于
在ISR中读IO电平
嗯,目前我也只能用读IO电平的方法了,本来是想有个固件库函数可以返回中断时是上升沿还是下降沿,发现没有这样的库函数,再想去找中断标志寄存器,以为有某个标志寄存器可以记录当前是上升沿中断还是下降沿中断,也没找到。
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
airwill 发表于
嗯楼上的办法不错, 如果还担心误判, 可以只设置 EXTI_Trigger_Rising, EXTI_Trigger_Falling 的一种, 在中 ...
你说的这个方法感觉也应该是可以的。
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
中级工程师, 积分 3516, 距离下一级还需 1484 积分
中级工程师, 积分 3516, 距离下一级还需 1484 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
中级工程师, 积分 3516, 距离下一级还需 1484 积分
中级工程师, 积分 3516, 距离下一级还需 1484 积分
本帖最后由 gxliu08 于
10:30 编辑
是不是可以进入中断后用GPIO_ReadInputDataBit读一下信号引脚电平,SET 或 RESET?
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
主题帖子积分
专家等级:结帖率:0%打赏:0.00受赏:38.00
主题帖子积分
设置成EXTI_Trigger_Rising_Falling触发,中断程序再判断是IO的当前电平,就知道是上升沿还是下降沿了;
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
主题帖子积分
专家等级:结帖率:100%
主题帖子积分
高级技术员, 积分 645, 距离下一级还需 355 积分
高级技术员, 积分 645, 距离下一级还需 355 积分
问题已解决了,试过了可以。
在ISR中读取IO电平状态:
#if& & & & & & & & (MODE_POLLING == KEY_MODE)
#elif& & & & & & & & (MODE_INTERRUPTE == KEY_MODE)
extern void EXTI4_15_IRQHandler(void)
&&if(EXTI_GetITStatus(EXTI_Line6) != RESET){& & & &
& & & & & & & & if(0 == GPIO_ReadInputDataBit(KEYS_PORT,KEY1_PIN)){// ?? 1/2 u??
& & & & & & & & & & & & & & & & LED1_ON();
& & & & & & & & }else{//??????
& & & & & & & & & & & & & & & & LED1_OFF();
& & & & & & & & }
& & EXTI_ClearITPendingBit(EXTI_Line6);
&&}else if(EXTI_GetITStatus(EXTI_Line7) != RESET){
& & & & & & & & if(0 == GPIO_ReadInputDataBit(KEYS_PORT,KEY2_PIN)){// ?? 1/2 u??
& & & & & & & & & & & & & & & & LED2_ON();
& & & & & & & & }else{//??????
& & & & & & & & & & & & & & & & LED2_OFF();
& & & & & & & & }
& & & & & & & &
& & EXTI_ClearITPendingBit(EXTI_Line7);& & & &
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
中级技术员, 积分 234, 距离下一级还需 66 积分
中级技术员, 积分 234, 距离下一级还需 66 积分
主题帖子积分
专家等级:结帖率:0%
主题帖子积分
中级技术员, 积分 234, 距离下一级还需 66 积分
中级技术员, 积分 234, 距离下一级还需 66 积分
真好需需要
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
主题帖子积分
高级技术员, 积分 901, 距离下一级还需 99 积分
高级技术员, 积分 901, 距离下一级还需 99 积分
主题帖子积分
专家等级:结帖率:95%
主题帖子积分
高级技术员, 积分 901, 距离下一级还需 99 积分
高级技术员, 积分 901, 距离下一级还需 99 积分
正需要,思想重要。
21ic公开课,21ic网友共同的学习圈子!学单片机、嵌入式、模拟、电源……就看这里
移步更多21ic独家微课:
技术高手奖章
人才类勋章
时间类勋章
甘甜之泉水
发帖类勋章
精华达人奖章
等级类勋章
湍急之河流
发帖类勋章
时间类勋章
技术导师奖章
人才类勋章
突出贡献奖章
等级类勋章
沉静之湖泊
发帖类勋章
时间类勋章
荣誉元老奖章
等级类勋章
坚毅之洋流
发帖类勋章
技术领袖奖章
人才类勋章
技术奇才奖章
人才类勋章
时间类勋章
技术新星奖章
人才类勋章
时间类勋章
时间类勋章
晶莹之水滴
发帖类勋章

我要回帖

更多关于 stm32 pwm下降沿中断 的文章

 

随机推荐