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,总 ...
随机推荐
- 通俗易懂之Tensorflow summary类 & 初识tensorboard
前面学习的cifar10项目虽小,但却五脏俱全.全面理解该项目非常有利于进一步的学习和提高,也是走向更大型项目的必由之路.因此,summary依然要从cifar10项目说起,通俗易懂的理解并运用sum ...
- 01 uni-app框架学习:项目创建及底部导航栏tabBar配置
1.创建一个项目类型选择uniapp 2. pages里新建3个页面如下 3.在pages.json中配置底部导航tabBar 效果展示:
- 转:Citrix虚拟化--转自CSDN
http://blog.csdn.net/kkfloat/article/category/1430751/3
- USB枚举过程【转】
转自:http://blog.csdn.net/myarrow/article/details/8270029 1. 枚举是什么? 枚举就是从设备读取一些信息,知道设备是什么样的设备,如 ...
- 初始ASP.NET数据控件【续 DataList】
DataList控件 DataList控件也是一个常用的数据绑定控件,相对于GridView控件虽然没它那么强大的功能,但是灵活性却很强势.因为其本身就是一个富有弹性的控件.DataList控件可以 ...
- HTTP2.0新特性
参考:http://www.tuicool.com/articles/mq2qm26
- nodejs抓取别人家的页面的始末
内容:分析并获取页面调取数据的API(接口),并跨域获取数据保存在文档中(nodejs做代理-CORS) 事由以及动机 2015年9月份全国研究生数学建模竞赛的F题,旅游线路规划问题.其中需要自己去查 ...
- Java基础86 MySQL数据库基础知识
本文知识点(目录): 1.MySQL数据库的概述 2.MySQL数据库的管理[对数据库的操作](查询.删除.创建数据库,以及查询和修改数据库的编码模式) 3.表的管理[对数据库 表的操作] ...
- SecureCRT中常用linux命令 -《转载》
常用命令: 一.ls 只列出文件名 (相当于dir,dir也可以使用) -A:列出所有文件,包含隐藏文 件. -l:列表形式,包含文件的绝大部分属性. -R:递归显示. --help:此命令的帮助. ...
- maven待整理
http://blog.csdn.net/column/details/yuguiyang-maven.html?&page=2