STM32 怎么控制DMA每次只传一个打印机数据只传输一半

STM32之DMA彻底研究_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
STM32之DMA彻底研究
上传于|0|0|文档简介
&&STM32之DMA彻底研究
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩9页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢拒绝访问 |
| 百度云加速
请打开cookies.
此网站 () 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(389a15ecc4e843e9-ua98).
重新安装浏览器,或使用别的浏览器STM32输入捕获模式设置并用DMA接收数据 - ARM单片机 - 电子工程世界网
STM32输入捕获模式设置并用DMA接收数据
10:04:10来源: eefocus
参考:&的PWM输入并用
Input capture mode
The input stage samples the corresponding TIx input to generate a filtered signal TIxF.
Then, an edge detector with polarity selection generates a signal (TIxFPx)
which can be&uses trigger input by the slave mode controller or as the capture command.
It is&presca before the capture register (ICxPS).
In Input capture mode, the Capture/Compare Registers (TIMx_CCRx) are used to latch the&value of the counter
after a transition detected by the corresponding ICx signal.
When a&capture occurs, the corresponding CCXIF flag (TIMx_SR register) is set and an
or&a DMA rest can be sent if they are enabled.
If a capture occurs while the CCxIF flag was&already high, then the over-capture flag CCxOF (TIMx_SR register) is set.
CCxIF can be&cleared by software by writing it to &0& or by reading the captured data stored in the&TIMx_CCRx register.
CCxOF is cleared when you write it to &0&.&
The following example shows how to capture the counter value in TIMx_CCR1 when TI1&input rises.
To do this, use the following procedure:
? Select the active input:&
TIMx_CCR1 must be linked to the TI1 input, so write the CC1S&bits to 01 in the TIMx_CCMR1 register.&
As soon as CC1S becomes different from 00,&the channel is configured in input and the TIMx_CCR1 register becomes read-only.
? Program the input filter duration you need with respect to the signal you connect to the&timer&
(by programming ICxF bits in the TIMx_CCMRx register if the input is a TIx input).
Let&s imagine that, when toggling, the input signal is not stable during at must 5 internal&clock cycles.&
We must program a filter duration longer than these 5 clock cycles.&
We&can validate a transition on TI1 when 8 consecutive samples with the new level have&been detected (sam at fDTS frequency).&
Then write IC1F bits to 0011 in the&TIMx_CCMR1 register.
? Select the edge of the active transition on the TI1 channel by writing CC1P and CC1NP&bits to 0&
in the TIMx_CCER register (rising edge in this case).
? Program the input prescaler. In our example, we wish the capture to be performed at&each valid transition,&
so the prescaler is disabled (write IC1PS bits to &00& in the&TIMx_CCMR1 register).
? Enable capture from the counter into the capture register by setting the CC1E bit in the&TIMx_CCER register.
? If needed, enable the related interrupt request by setting the CC1IE bit in the&TIMx_DIER register,&
and/or the DMA request by setting the CC1DE bit in the&TIMx_DIER register.
When an input capture occurs:
? The TIMx_CCR1 register gets the value of the counter on the active transition.
? CC1IF flag is set (interrupt flag). CC1OF is also set if at least two consecutive captures&occurred whereas the flag was not cleared.
? An interrupt is generated depending on the CC1IE bit.
? A DMA request is generated depending on the CC1DE bit.
In order to handle the overcapture, it is recommended to read the data before the&overcapture flag.&
This is to avoid mng an overcapture which could happen after reading&the flag and before reading the data.
IC interrupt and/or DMA requests can be generated by software by setting the&corresponding CCxG bit in the TIMx_EGR register.
STM32模式设置并用DMA接收数据
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh
开发环境:MDK4.72
MCU:STM32F103
项目中需要进行红外学习,于是采用输入捕获取得电平变化时间.并将数据放在DMA中.这样可以避免频繁中断消耗CPU资源.
采用的是PB1脚,对应TIM3的通道4.
/*********************************************************************
接口函数:初始化红外学习模块
**********************************************************************/
void inf_infrared_study_init(void)
//初始化io口
inf_init_io();
//初始化中断
//inf_init_irq();
//初始化定时器
inf_init_timer();
inf_infrared_study_open_dma(1);
//打开定时器
inf_infrared_study_open_timer(1);
/*********************************************************************
初始化io口
**********************************************************************/
static void inf_init_io(void)
//定义IO初始化结构体
GPIO_InitTypeDef GPIO_InitS
//初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//管脚初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
//设置为输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*********************************************************************
初始化中断
**********************************************************************/
static void inf_init_irq(void)
//定义外部中断结构体
EXTI_InitTypeDef EXTI_InitS
//初始化中断脚复用时钟
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_F
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_I
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/*********************************************************************
初始化定时器
**********************************************************************/
static void inf_init_timer(void)
//定义定时器结构体
TIM_TimeBaseInitTypeDef timInitS
//输入捕获结构体
TIM_ICInitTypeDef tim_
//定义DMA结构体
DMA_InitTypeDef DMA_InitS
//启动DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//DMA1通道3配置
DMA_DeInit(DMA1_Channel3);
//外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&TIM3->CCR4);
//内存地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Rx_Buf_Tim_D
//dma传输方向单向
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//设置DMA在传输时缓冲区的长度
DMA_InitStructure.DMA_BufferSize = RX_LEN_TIM_DMA;
//设置DMA的外设递增模式,一个外设
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
//设置DMA的内存递增模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
//外设数据字长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW
//内存数据字长
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW
//设置DMA的传输模式
//DMA_InitStructure.DMA_Mode = DMA_Mode_N
DMA_InitStructure.DMA_Mode = DMA_Mode_C
//设置DMA的优先级别
DMA_InitStructure.DMA_Priority = DMA_Priority_H
//设置DMA的2个memory中的变量互相访问
DMA_InitStructure.DMA_M2M = DMA_M2M_D
DMA_Init(DMA1_Channel3,&DMA_InitStructure);
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//重新将Timer设置为缺省值
TIM_DeInit(TIM3);
//采用内部时钟给TIM3提供时钟源
TIM_InternalClockConfig(TIM3);
timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
//计数频率为500ns跳转1次
timInitStruct.TIM_Prescaler = SystemCoreClock / 2 - 1;
//向上计数
timInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
timInitStruct.TIM_RepetitionCounter = 0;
//这个值实际上就是TIMX->ARR,延时开始时重新设定即可
timInitStruct.TIM_Period = 0
//初始化定时器3
TIM_TimeBaseInit(TIM3, &timInitStruct);
//输入捕获配置
//选择通道
tim_icinit.TIM_Channel = TIM_Channel_4;
//硬件滤波
tim_icinit.TIM_ICFilter = 0x0;
//触发捕获的电平
tim_icinit.TIM_ICPolarity = TIM_ICPolarity_F
//每次检测到触发电平都捕获
tim_icinit.TIM_ICPrescaler= TIM_ICPSC_DIV1;
//通道方向选择
tim_icinit.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM3,&tim_icinit);
//禁止ARR预装载缓冲器
TIM_ARRPreloadConfig(TIM3, DISABLE);
//输入跳变选择
TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);
//从机模式:复位模式
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
//主从模式选择
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
//配置定时器的DMA
TIM_DMAConfig(TIM3,TIM_DMABase_CCR4,TIM_DMABurstLength_2Bytes);
//产生DMA请求信号
TIM_DMACmd(TIM3, TIM_DMA_CC4, ENABLE);
//打开定时器
TIM_Cmd(TIM3, ENABLE);
/*********************************************************************
接口函数:打开定时器
*参数:state:状态:0:关闭,1:打开
**********************************************************************/
void inf_infrared_study_open_timer(uint8_t state)
if (state)
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM3, DISABLE);
/*********************************************************************
接口函数:打开中断
*参数:state:状态:0:关闭,1:打开
**********************************************************************/
void inf_infrared_study_open_irq(uint8_t state)
//定义中断结构体
NVIC_InitTypeDef NVIC_InitS
if (state)
//打开中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
//通道设置为外部中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//中断抢占先等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//中断响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//打开中断
NVIC_Init(&NVIC_InitStructure);
//关闭中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
//通道设置为外部中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//中断抢占先等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//中断响应优先级
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_Cmd(DMA1_Channel3,ENABLE);
DMA_Cmd(DMA1_Channel3,DISABLE);
/*********************************************************************
接口函数:得到DMA接收帧长
*返回:帧长
**********************************************************************/
uint16_t inf_infrared_study_dma_rx_len(void)
//获得接收帧帧长
return (RX_LEN_TIM_DMA - DMA_GetCurrDataCounter(DMA1_Channel3));
除TIM6和TIM7之外的定时器都只能采用上升沿或者下降沿捕捉而不能采用双边沿捕捉.
TIM_ICPolarity_Rising
((uint16_t)0x0)
TIM_ICPolarity_Falling
((uint16_t)0x2)
TIM_ICPolarity_BothEdge
((uint16_t)0xA)
#define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising)
((POLARITY) == TIM_ICPolarity_Falling))
#define IS_TIM_IC_POLARITY_LITE(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising)
((POLARITY) == TIM_ICPolarity_Falling)
((POLARITY) == TIM_ICPolarity_BothEdge))
关键字:&&&&&&&&
编辑:什么鱼 引用地址:
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
微信扫一扫加关注 论坛活动 E手掌握
微信扫一扫加关注
芯片资讯 锐利解读
大学堂最新课程
汇总了TI汽车信息娱乐系统方案、优质音频解决方案、汽车娱乐系统和仪表盘参考设计相关的文档、视频等资源
热门资源推荐
频道白皮书
何立民专栏
北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。stm32之DMA彻底研究
我的图书馆
stm32之DMA彻底研究
前言:接触MCU的编程已经有几年的历史,刚开始是从PLC(C语言的)学习与应用,后来有学习了8bits的AVR单片机,对MCU有一定的了解;最近接触了STM32的Chip,发现其优点不只是单单宣传的32bits的MCU的速度,而且在编程的风格上也有了较大的变化(与我原有的编程习惯);特别是有一个与CPU并行运行的模块:DMA,对它印象深刻。现在就和大家一起讨论学习这个Module,谈谈我在学习中一些感悟和大家一起分享;如有对DMA理解和应用上的错误和偏差,欢迎“拍砖”和提出更正,虾米在此感谢大家了。哈哈!什么是STM32的DMA?其全称是:Direct Memory Access;根据ST公司提供的相关信息,DMA是STM32中一个独立与Cortex-M3内核的模块,有点类似与ADC、PWM、TIMER等模块;主要功能是通信“桥梁”的作用,可以将所有外设映射的寄存器“连接”起来,这样就可以高速问各寄存器,其传输不受CPU的支配,传输还是双向的;例如,从“表面”上看,它可以将flash中的数据与储存器中变量建立通讯,还可以将一外设的积存器或缓冲器与另外设的寄存器或缓冲器建立双向通讯,有点像把外设硬件之间用“导线”连接在一起了。其间的通讯不占CPU资源,访问速度高,对于实时性强的应用将是一个很好的选择;当然,对于实时性非常强的,建议还是采用专用的DSP芯片。过程:怎样启用DMA?首先,众所周知的是初始化,任何设备启用前都要对其进行初始化,要对模块初始化,还要先了解该模块相应的结构及其函数,以便正确的设置;由于DMA较为复杂,我就只谈谈DMA的基本结构和和常用函数,这些都是ST公司提供在库函数中的。1、 下面代码是一个标准DMA设置,当然实际应用中可根据实际情况进行裁减:DMA_DeInit(DMA_Channel1);上面这句是给DMA配置通道,根据ST提供的资料,STM3210Fx中DMA包含7个通道(CH1~CH7),也就是说可以为外设或memory提供7座“桥梁”(请允许我使用桥梁一词,我觉得更容易理解,哈哈,别“拍砖”呀!);DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_A上面语句中的DMA_InitStructure是一个DMA结构体,在库中有声明了,当然使用时就要先定义了;DMA_PeripheralBaseAddr是该结构体中一个数据成员,给DMA一个起始地址,好比是一个buffer起始地址,数据流程是:外设寄存器à DMA_PeripheralBaseAddàmemory中变量空间(或flash中数据空间等),ADC1_DR_Address是我定义的一个地址变量;DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedV上面这句很显然是DMA要连接在Memory中变量的地址,ADC_ConvertedValue是我自己在memory中定义的一个变量;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;上面的这句是设置DMA的传输方向,就如前面我所说的,DMA可以双向传输,也可以单向传输,这里设置的是单向传输,如果需要双向传输:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。DMA_InitStructure.DMA_BufferSize = 2;上面的这句是设置DMA在传输时缓冲区的长度,前面有定义过了buffer的起始地址:ADC1_DR_Address ,为了安全性和可靠性,一般需要给buffer定义一个储存片区,这个参数的单位有三种类型:Byte、HalfWord、word,我设置的2个half-word(见下面的设置);32位的MCU中1个half-word占16 bits。DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D上面的这句是设置DMA的外设递增模式,如果DMA选用的通道(CHx)有多个外设连接,需要使用外设递增模式:DMA_PeripheralInc_E我的例子里DMA只与ADC1建立了联系,所以选用DMA_PeripheralInc_DisableDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E上面的这句是设置DMA的内存递增模式,DMA访问多个内存参数时,需要使用DMA_MemoryInc_Enable,当DMA只访问一个内存参数时,可设置成:DMA_MemoryInc_Disable。DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW上面的这句是设置DMA在访问时每次操作的数据长度。有三种数据长度类型,前面已经讲过了,这里不在叙述。DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW与上面雷同。在此不再说明。DMA_InitStructure.DMA_Mode = DMA_Mode_C上面的这句是设置DMA的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_NormalDMA_InitStructure.DMA_Priority = DMA_Priority_H上面的这句是设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.DMA_InitStructure.DMA_M2M = DMA_M2M_D上面的这句是设置DMA的2个memory中的变量互相访问的DMA_Init(DMA_Channel1,&DMA_InitStructure);前面那些都是对DMA结构体成员的设置,在次再统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。/*DMA Enable*/DMA_Cmd(DMA_Channel1,ENABLE);哈哈哈!这一句我想我就不罗嗦了,大家一看就明白。至此,整个DMA总算设置好了,但是,DMA通道又是怎样与外设联系在一起的呢?哈哈,这也是我当初最想知道的一个事情,别急!容我想喝口茶~~~~~~哈哈哈!要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有 一个xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用ADC_DMACmd(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。下面就以我的一个实例来和大家一起学习。这个实例仿真是成功的,我使用的是IAR Embedded Workbench IDE(v4.42) 和Manley Mini-kit评估板+ST-Link II来调试,是一个USART+ADC+DMA的例子。首先,按照相关的资料提示,建立好项目路径、拷贝库文件和相关必要的文件,并建立一个新工程;还有就是设置好IAR IDE的相关设置。一切准备就绪后就开始修改相关的文档:conf.h文档的修改是根据应用中有启用的相关功能Module。如下图:ADC模块的启用设置:DMA模块的启用设置:USART模块启用的设置:其他的如flash、GPIO、RCC、NVIC、HSE等就不一一举例,因为这些几乎每个工程都要用到。再回头看看我的main.c文档,下图是相关的私有定义USART的配制如下(9600,8, N,1):DMA的配置如下:ADC的配置如下图(采用了2路A/D多通道的ADC模式):给各个模块配置的时钟使能如下图;在此想罗嗦一句就是在这个位置的设置我没有给DMA配置时钟,造成DMA功能无法正常使用,也就是前面所有说的与我原先的编程风格有较大的变化的原因,想说一句:在项目中所使用的所有功能模块都要在此配置时钟才能正常工作。GPIO的配置如果有开中断子程序,请在在NVIC中配置,还可以定义每个中断子程序的优先级别,由于我的工程没有用到,在此就不罗嗦了。我项目应用到的文件目录如下图:我的项目仿真结果如下;PA0与GND间接了一个1.5V的干电池,其结果是如中ADC_ConvertedValue[0]的值;PA1悬空,未接模拟信号。我的硬件仿真平台如下2图:红色的是我AVR mega16L Mini开发板,主要是利用了其中的POWER和RS232用PC端USART数据采集结果:(图中的显示是我将ADC转换后的值给字符串化了)ST-link II仿真窗口的测试结果与USART采集到的数据结果差异说明:由于Manley 的stme32 Mini-kit评估板套件无法给ADC和USART同时组合仿真,我是分别分开仿真和USART数据传输的,所以出现差异。心得: 1、这次学习STM32的MCU,最大的心得是改变我原有的编程思维,原来学习AVR的时候,文件库需要自己写,属于底层操作,如要自己写直接操作各外设的寄存器,复杂的还需要自己写设置函数,对底层要有非常的清楚的认识,编写的代码的工作量也比较大;稍有不慎,容易把寄存器弄错;调试也会花费较大的时间。而STM32的编程风格给我一个全新的视角(哈哈!别拍砖,虽然属菜鸟级别,但比较容易接受新的东西),感觉只要按其提供的资料建立起工程的基本构架,很多都是ST公司提供封装好的接口(类似windows的API),直接调用接口和做少许修改就可以完成你想要的工程结果。2、 清晰的工程构架:ST提供一些工程案例的基本构架,只要熟悉这些构架,对构架做一些适当的修改,你将很轻松的完成你的任务,开发周期也可以缩短很多。请记住:牢记工程构架;3、 哈哈!不想罗嗦的是STM32的速度和丰富的外设。(再罗嗦可能会被成批的砖头拍死,哈哈哈哈!)4、 更有信心用STM32做其他更复杂一些的项目。祝大家好运!(别拍砖头呀!哈哈!)
TA的最新馆藏[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢

我要回帖

更多关于 手机数据只有上传 的文章

 

随机推荐