STM32的PWM输入模式设置并用DMA接收数据
参考 :STM32输入捕获模式设置并用DMA接收数据
PWM input mode
This mode is a particular case of input capture mode.
The procedure is the same except:
Two ICx signals are mapped on the same TIx input.
These 2 ICx signals are active on edges with opposite polarity.
One of the two TIxFP signals is selected as trigger input and the slave mode controller is configured in reset mode.
For example, you can measure the period (in TIMx_CCR1 register) and the duty cycle (in TIMx_CCR2 register)
of the PWM applied on TI1 using the following procedure (depending on CK_INT frequency and prescaler value):
Select the active input for TIMx_CCR1: write the CC1S bits to 01 in the TIMx_CCMR1 register (TI1 selected).
Select the active polarity for TI1FP1 (used both for capture in TIMx_CCR1 and counter clear): write the CC1P and CC1NP bits to ‘0’ (active on rising edge).
Select the active input for TIMx_CCR2: write the CC2S bits to 10 in the TIMx_CCMR1 register (TI1 selected).
Select the active polarity for TI1FP2 (used for capture in TIMx_CCR2): write the CC2P and CC2NP bits to ‘1’ (active on falling edge).
Select the valid trigger input: write the TS bits to 101 in the TIMx_SMCR register (TI1FP1 selected).
Configure the slave mode controller in reset mode: write the SMS bits to 100 in the TIMx_SMCR register.
Enable the captures: write the CC1E and CC2E bits to ‘1’ in the TIMx_CCER register.

STM32的PWM输入模式设置并用DMA接收数据
项目中需要进行红外学习,如果采用输入捕获的方式,因为定时器只能捕获上升沿或者下降沿,
所以只能获得周期,而不能得到具体的红外波的高低电平的时间.
所以采用PWM输入的方式进行捕获. 采用的是PA8脚,对应TIM1的通道1.
/*********************************************************************
* 函数
**********************************************************************/ /*********************************************************************
* 接口函数:初始化红外学习模块
**********************************************************************/ void inf_infrared_study_init( void )
{
//初始化io口
inf_init_io( );
//初始化中断
//inf_init_irq();
//初始化定时器
inf_init_timer( ); //打开DMA
inf_infrared_study_open_dma( );
//打开定时器
inf_infrared_study_open_timer( );
} /*********************************************************************
* 初始化io口
**********************************************************************/ static void inf_init_io( void )
{
//定义IO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure; //初始化时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
//管脚初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
//设置为输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//初始化
GPIO_Init( GPIOA, &GPIO_InitStructure );
} /*********************************************************************
* 初始化中断
**********************************************************************/ static void inf_init_irq( void )
{
//定义外部中断结构体
EXTI_InitTypeDef EXTI_InitStructure; //初始化中断脚复用时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
//配置中断源
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB, GPIO_PinSource1 );
// 配置下降沿触发
EXTI_ClearITPendingBit( EXTI_Line1 );
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init( &EXTI_InitStructure );
} /*********************************************************************
* 初始化定时器
**********************************************************************/ static void inf_init_timer( void )
{
//定义定时器结构体
TIM_TimeBaseInitTypeDef timInitStruct;
//输入捕获结构体
TIM_ICInitTypeDef tim_icinit;
//定义DMA结构体
DMA_InitTypeDef DMA_InitStructure; //启动DMA时钟
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
//DMA1通道配置
DMA_DeInit( DMA1_Channel2 );
//外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) ( &TIM1->CCR1 );
//内存地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) Rx_Buf_Tim_Dma1;
//dma传输方向单向
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_BufferSize = RX_LEN_TIM_DMA;
//设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//设置DMA的内存递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//外设数据字长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
//内存数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
//设置DMA的传输模式
//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
//设置DMA的优先级别
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//设置DMA的2个memory中的变量互相访问
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init( DMA1_Channel2, &DMA_InitStructure ); //启动DMA时钟
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
//DMA1通道配置
DMA_DeInit( DMA1_Channel3 );
//外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) ( &TIM1->CCR2 );
//内存地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) Rx_Buf_Tim_Dma2;
//dma传输方向单向
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_BufferSize = RX_LEN_TIM_DMA;
//设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//设置DMA的内存递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//外设数据字长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
//内存数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
//设置DMA的传输模式
//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
//设置DMA的优先级别
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//设置DMA的2个memory中的变量互相访问
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init( DMA1_Channel3, &DMA_InitStructure ); //开启时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );
//重新将Timer设置为缺省值
TIM_DeInit( TIM1 );
//采用内部时钟提供时钟源
TIM_InternalClockConfig( TIM1 );
//预分频
timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
//计数频率为500ns跳转1次
timInitStruct.TIM_Prescaler = SystemCoreClock / - ;
//向上计数
timInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
timInitStruct.TIM_RepetitionCounter = ;
//这个值实际上就是TIMX->ARR,延时开始时重新设定即可
timInitStruct.TIM_Period = 0xffff;
//初始化定时器
TIM_TimeBaseInit( TIM1, &timInitStruct ); //输入捕获配置
//选择通道
tim_icinit.TIM_Channel = TIM_Channel_1;
//硬件滤波
tim_icinit.TIM_ICFilter = 0x0;
//触发捕获的电平
tim_icinit.TIM_ICPolarity = TIM_ICPolarity_Falling;
//每次检测到触发电平都捕获
tim_icinit.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//通道方向选择
tim_icinit.TIM_ICSelection = TIM_ICSelection_DirectTI;
//初始化
//TIM_ICInit(TIM1,&tim_icinit);
TIM_PWMIConfig( TIM1, &tim_icinit );
//禁止ARR预装载缓冲器
//TIM_ARRPreloadConfig(TIM1, DISABLE); //输入跳变选择
TIM_SelectInputTrigger( TIM1, TIM_TS_TI1FP1 );
//从机模式:复位模式
TIM_SelectSlaveMode( TIM1, TIM_SlaveMode_Reset );
//主从模式选择
TIM_SelectMasterSlaveMode( TIM1, TIM_MasterSlaveMode_Enable ); //配置定时器的DMA
TIM_DMAConfig( TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_2Bytes );
//产生DMA请求信号
TIM_DMACmd( TIM1, TIM_DMA_CC1, ENABLE ); //配置定时器的DMA
TIM_DMAConfig( TIM1, TIM_DMABase_CCR2, TIM_DMABurstLength_2Bytes );
//产生DMA请求信号
TIM_DMACmd( TIM1, TIM_DMA_CC2, ENABLE ); //打开定时器
TIM_Cmd( TIM1, ENABLE );
} /*********************************************************************
* 接口函数:打开定时器
*参数:state:状态:0:关闭,1:打开
**********************************************************************/ void inf_infrared_study_open_timer( uint8_t state )
{
if ( state )
{
TIM_Cmd( TIM1, ENABLE );
}
else
{
TIM_Cmd( TIM1, DISABLE );
}
} /*********************************************************************
* 接口函数:打开中断
*参数:state:状态:0:关闭,1:打开
**********************************************************************/ void inf_infrared_study_open_irq( uint8_t state )
{
//定义中断结构体
NVIC_InitTypeDef NVIC_InitStructure; if ( state )
{
//打开中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //通道设置为外部中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ; //中断抢占先等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; //中断响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断
NVIC_Init( &NVIC_InitStructure ); //初始化
}
else
{
//关闭中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //通道设置为外部中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ; //中断抢占先等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; //中断响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; //打开中断
NVIC_Init( &NVIC_InitStructure ); //初始化
}
} /*********************************************************************
* 接口函数:打开DMA
*参数:state:状态:0:关闭,1:打开
**********************************************************************/ void inf_infrared_study_open_dma( uint8_t state )
{
if ( state )
{
//设置传输数据长度
//DMA_SetCurrDataCounter(DMA1_Channel3,RX_LEN_TIM_DMA);
//打开DMA
DMA_Cmd( DMA1_Channel2, ENABLE );
DMA_Cmd( DMA1_Channel3, ENABLE );
}
else
{
DMA_Cmd( DMA1_Channel2, DISABLE );
DMA_Cmd( DMA1_Channel3, ENABLE );
}
} /*********************************************************************
* 接口函数:得到DMA接收帧长
*返回:帧长
**********************************************************************/ uint16_t inf_infrared_study_dma_rx_len( void )
{
//获得接收帧帧长
return ( RX_LEN_TIM_DMA - DMA_GetCurrDataCounter( DMA1_Channel2 ) );
}
STM32的PWM输入模式设置并用DMA接收数据的更多相关文章
- STM32输入捕获模式设置并用DMA接收数据
参考: STM32的PWM输入模式设置并用DMA接收数据 Input capture mode The input stage samples the corresponding TIx input ...
- STM32—无需中断来实现使用DMA接收串口数据
本节目标: 通过DMA,无需中断,接收不定时长的串口数据 描述:当在串口多数据传输下,CPU会产生多次中断来接收串口数据,这样会大大地降低CPU效率,同时又需要CPU去做其它更重要的事情,我们应该如何 ...
- STM32串口DMA接收数据错位——暴力解决方法
背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...
- STM32之串口DMA接收不定长数据
STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...
- STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷
STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...
- STM32 串口USART DMA方式发送接收数据
硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 文章目录 头文件 USART3_DR的地址 DMA的通道 DMA的中断 USART接收回调函数 头 ...
- STM32之PWM波形输出配置总结
一. TIMER分类: STM32中一共有11个定时器,其中TIM6.TIM7是基本定时器:TIM2.TIM3.TIM4.TIM5是通用定时器:TIM1和TIM8是高级定时器,以及2个看门狗定时器 ...
- stm32之PWM学习
下图是一个STM32普通PWM形成的图形原理说明 自动重装载寄存器(ARR)用于确定波形的频率(即周期).捕获比较寄存器(CCRx)(用于确定占空比的) PWM的工作过程如下:首先ARR寄存器里面的值 ...
- STM32之PWM君
PWM..英语好的人估计又知道这三个大写字母代表哪三个英语单词了.小弟不才,就说中文意思好了:脉冲宽度调制,玩过飞思卡尔的人估计对PWM非常的不陌生吧.电机驱动需要PWM,控制舵机的转向需要PWM,总 ...
随机推荐
- 如何解决Mac只能登QQ不能联网
如何解决Mac只能登QQ不能联网,路由正常,Wifi帐号密码正确,但wifi中断不能联网的问题.
- 03 uni-app框架学习:轮播图组件的使用
1.轮播图组件的使用 参照官方文档 2.在页面上加入这个组件 3.在页面中引去css样式 并编写样式 ps:upx单位是什么 简单来说 就相当于小程序中的rpx 是一个自适应的单位 会根据屏幕宽度自动 ...
- lucene修改索引——(六)
原理: 修改的原理是先删除,后增加一个,这也是常用的一种修改的方式. 删除的文档的id不会被新增加的文档占用,类似于mysql的自增,当删除一个id=2时,以后id=2就是空着的,不会上来一个把2给占 ...
- JQuery效果隐藏/显示
hide() 方法 语法 $(selector).hide(speed,callback) show() 方法 语法 $(selector).show(speed,callback) 参数 描述 sp ...
- springboot整合rabbirmq(3.7.9)中使用mandatory参数获取匹配失败的消息以及存入rabbitmq备份交换器中!
先说下这个参数的作用: /** * Mandatory为true时,消息通过交换器无法匹配到队列会返回给生产者 * 为false时,匹配不到会直接被丢弃 */在一些特定场景下还是有用处的!接下来说一下 ...
- 设计模式及Python实现
设计模式是什么? Christopher Alexander:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心.这样你就能一次又一次地使用该方案而不必做重复劳动.” 设计 ...
- HTTPS-HTTPS原理
楔子 谣言粉碎机前些日子发布的<用公共WiFi上网会危害银行账户安全吗?>,文中介绍了在使用HTTPS进行网络加密传输的一些情况,从回复来看,争议还是有的.随着网络越来越普及,应用越来越广 ...
- norbert-构建服务器集群感知的 Java 应用程序
http://www.ibm.com/developerworks/cn/java/j-zookeeper/index.html
- 【LOJ】#2270. 「SDOI2017」天才黑客
题解 显然要记录每个点来的状态,这样会扩充出点度的平方条边,就gg了 删掉所有的点,把每个边拆成两个点,连一条边权为c 这个时候我们考虑对于原先的每个点,将所有与其相连边所需要的节点(不管是进入还是出 ...
- 【BZOJ】4560: [JLoi2016]字符串覆盖
题解 先用kmp求出来一个ed[i][j]表示在母串的第i位是第j个子串的结尾 考虑状压一个二进制位表示这个子串覆盖过没有 对于最大值,记一个dp[S][i]表示子串的使用状况为S,当前为母串的第i位 ...