DMAUSARTWord格式.docx

上传人:b****3 文档编号:17817157 上传时间:2022-12-11 格式:DOCX 页数:10 大小:69.84KB
下载 相关 举报
DMAUSARTWord格式.docx_第1页
第1页 / 共10页
DMAUSARTWord格式.docx_第2页
第2页 / 共10页
DMAUSARTWord格式.docx_第3页
第3页 / 共10页
DMAUSARTWord格式.docx_第4页
第4页 / 共10页
DMAUSARTWord格式.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

DMAUSARTWord格式.docx

《DMAUSARTWord格式.docx》由会员分享,可在线阅读,更多相关《DMAUSARTWord格式.docx(10页珍藏版)》请在冰豆网上搜索。

DMAUSARTWord格式.docx

  这里将DMA设置为从内存到外设的半字(2个字节)环形传输。

开启DMA全满和半满中断,在中断处理函数中不断填充新的时刻值,即可保证产生的波形不间断。

假设存放时刻值的缓冲长度为N,则每N/2个点才中断一次,这样CPU就不需要频繁进入中断,执行效率比较高。

由此也可以看出,缓冲越大,对中断响应的实时性要求也越低,当然这时中断的处理时间也越长。

以下为示例代码:

  需要注意的是,比较/捕获寄存器的预加载功能必须禁止掉。

我们需要的是写入比较/捕获寄存器的值立即与计数器相比较输出,而无需等待一个更新事件。

  采用DMA+TIMx的方式来捕获上升沿和下降沿时刻,有利于提高系统的实时性和执行效率。

通过TIMx的捕获功能将方波的电平跳变时刻记录在比较/捕获寄存器中,然后DMA将该值自动传输到内存,只有当DMA触发半满或全满事件时CPU才需要进入中断处理数据。

通过记录方波的上升沿和下降沿时刻,然后将两个时刻相减,进而就能得到所有低沿和高沿的宽度,最后进行后续的分析处理。

这种方式下中断频率仅为方波频率的4/N(N为缓冲区大小)。

  测试中STM32系列微控制器工作在36MHz,可产生出1路最高1.5MHz的方波,可捕获1MHz的方波,而此时CPU的执行几乎不受影响。

这里采用DMA来实现方波的产生和捕获,极大地提高了系统的实时性和执行效率,减少了中断次数,节省了宝贵的资源。

这种方案也可以用来实现高效的模拟串口。

另外,若有多个DMA同时工作,应考虑最坏情况下DMA的响应时间,以避免错误发生。

 

乒乓模式双缓冲模式环形缓冲

STM32学习笔记三竹天笑

前言:

开始学USART+DMA的时候看到帖子《STM32UARTDMA实现未知数据长度接收》,觉得方法妙极了。

此下出自此帖子——(整体的思路是这样的,一开始设置好DMA接收,可以把缓冲区长度设置为帧最大长度,我们可以把RX连接到定时器的管脚输入端,并且一开始设置输入并且使能引脚下降沿中断,当帧的第一个字节发送时,因为起始位为低电平,空闲时UART为高电平,满足条件,进入中断,禁止中断,并且在中断中开启定时器,该定时器工作在复位模式,上升沿复位,并且设置好定时器输出比较值为超时时间,比如20ms,这样,在传输后面字节时,肯定会有高低电平出现,即便是传输的是0x00,0xFF,虽然UART数据区不变,但是都为1,或都为0,但是因为起始位为低电平,停止位是高电平,所以肯定会有上升沿,定时器会一直复位,输出定时器的计数器一直到达不了输出比较值,当一帧传输结束后,定时在最后一个字节复位后,由于没有数据继续到达,无法复位,则计数器就能计到输出比较值,这时发出中断,在定时器中断中可以计算出接收数据的长度,并且通知外部数据已经接收完毕。

今天我在工作中调通了另一种USART+DMA接收未知数据长度的接收,使用的是USRAT空闲总线中断接收,这种方法也在网站上比较多见,以前没试过,今天才知道如此的爽,另外我使用DMA发送USART数据替代了以前的查询法发送,发现更加爽了。

其速度快了很多,尤其是在大量数据传输与发送的时候其优势更加明显。

我举个例子:

1、后台数据->

USART1->

USART2->

其它设备,其它设备数据->

USART2->

USART1->

后台,这两个数据过程也可能同时进行。

2、由于硬件的限制,USART1和USART2的传输波特率不一样,比如USART1使用GPRS通信,USART2使用短距离无线通信;

或者USART1使用以太网通信,USART2使用485总线通信。

由于在寝室只有笔记本电脑,只有一个串口转USB,没办法实现两个串口之间的数据转发了,只好实现串口各自的数据转发。

现在我把我实现的过程简单描述一下:

1、 

 

初始化设置:

USART1_RX+DMA1_Channel5,USART2_RX+DMA1_Channel6,USART1_TX+DMA1_Channel4,USART2_TX+DMA1_Channel7(具体设置请看程序包)。

2、 

当数据发送给USART1接收完毕时候会引起USART1的串口总线中断,计算DMA1_Channel5内存数组剩余容量,得到接收的字符长度。

将接收的字符复制给DMA1_Channel4内存数组,启动DMA1_Channel4通道传输数据,(传输完成需要关闭。

)下一次数据接收可以在启动DMA1_Channel4时候就开始,不需要等待DMA1_Channel4数据传输完成。

但是上一次DMA1_Channel4完成之前,不可以将数据复制给DMA1_Channel4内存数组,会冲掉以前数据。

3、 

USART2类同USART1。

呵呵,下面贴程序:

IO口定义:

voidGPIO_Configuration(void)

{

GPIO_InitTypeDefGPIO_InitStructure;

/*第1步:

打开GPIO和USART部件的时钟*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

/*第2步:

将USARTTx的GPIO配置为推挽复用模式*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&

GPIO_InitStructure);

/*第3步:

将USARTRx的GPIO配置为浮空输入模式

由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的

但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数

*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;

打开GPIO和USART2部件的时钟*/

//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);

将USART2Tx的GPIO配置为推挽复用模式*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;

将USART2Rx的GPIO配置为浮空输入模式

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;

/*第3步已经做了,因此这步可以不做

}

串口初始化:

voidUSART_Configuration(void)

USART_InitTypeDefUSART_InitStructure;

/*第4步:

配置USART参数

-BaudRate=115200baud

-WordLength=8Bits

-OneStopBit

-Noparity

-Hardwareflowcontroldisabled(RTSandCTSsignals)

-Receiveandtransmitenabled

USART_InitStructure.USART_BaudRate=19200;

USART_InitStructure.USART_WordLength=USART_WordLength_8b;

USART_InitStructure.USART_StopBits=USART_StopBits_1;

USART_InitStructure.USART_Parity=USART_Parity_No;

USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;

USART_Init(USART1,&

USART_InitStructure);

//空闲中断

USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);

/*第5步:

使能USART,配置完毕*/

USART_Cmd(USART1,ENABLE);

/*CPU的小缺陷:

串口配置好,如果直接Send,则第1个字节发送不出去

如下语句解决第1个字节无法正确发送出去的问题*/

USART_ClearFlag(USART1,USART_FLAG_TC);

/*清发送外城标志,TransmissionCompleteflag*/

USART_InitStructure.USART_BaudRate=9600;

USART_Init(USART2,&

USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);

//开启空闲,帧错,噪声,校验错中断 

USART_Cmd(USART2,ENABLE);

USART_ClearFlag(USART2,USART_FLAG_TC);

DMA配置:

voidDMA_Configuration(void)

DMA_InitTypeDefDMA_InitStructure;

/*DMAclockenable*/

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

//DMA1

/*DMA1Channel4(triggeredbyUSART1Txevent)Config*/

DMA_DeInit(DMA1_Channel4);

DMA_InitStructure.DMA_PeripheralBaseAddr=0x40013804;

DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)USART1_SEND_DATA;

DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize=512;

DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority=DMA_Priority_High;

DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;

DMA_Init(DMA1_Channel4,&

DMA_InitStructure);

DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);

DMA_ITConfig(DMA1_Channel4,DMA_IT_TE,ENABLE);

/*EnableUSART1DMATXrequest*/

USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);

DMA_Cmd(DMA1_Channel4,DISABLE);

/*DMA1Channel5(triggeredbyUSART2Txevent)Config*/

DMA_DeInit(DMA1_Channel7);

DMA_InitStructure.DMA_PeripheralBaseAddr=0x40004404;

DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)USART2_SEND_DATA;

DMA_Init(DMA1_Channel7,&

DMA_ITConfig(DMA1_Channel7,DMA_IT_TC,ENABLE);

DMA_ITConfig(DMA1_Channel7,DMA_IT_TE,ENABLE);

USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);

DMA_Cmd(DMA1_Channel7,DISABLE);

/*DMA1Channel5(triggeredbyUSART1Rxevent)Config*/

DMA_DeInit(DMA1_Channel5);

DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)USART1_RECEIVE_DATA;

DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;

DMA_Init(DMA1_Channel5,&

DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);

DMA_ITConfig(DMA1_Channel5,DMA_IT_TE,ENABLE);

/*EnableUSART1DMARXrequest*/

USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);

DMA_Cmd(DMA1_Channel5,ENABLE);

/*DMA1Channel6(triggeredbyUSART1Rxevent)Config*/

DMA_DeInit(DMA1_Channel6);

DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)USART2_RECEIVE_DATA;

DMA_InitStructure.DMA_Priority=DMA_Priorit

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 中医中药

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1