USART与DMA的区别与联系.docx

上传人:b****6 文档编号:4577205 上传时间:2022-12-06 格式:DOCX 页数:8 大小:18.26KB
下载 相关 举报
USART与DMA的区别与联系.docx_第1页
第1页 / 共8页
USART与DMA的区别与联系.docx_第2页
第2页 / 共8页
USART与DMA的区别与联系.docx_第3页
第3页 / 共8页
USART与DMA的区别与联系.docx_第4页
第4页 / 共8页
USART与DMA的区别与联系.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

USART与DMA的区别与联系.docx

《USART与DMA的区别与联系.docx》由会员分享,可在线阅读,更多相关《USART与DMA的区别与联系.docx(8页珍藏版)》请在冰豆网上搜索。

USART与DMA的区别与联系.docx

USART与DMA的区别与联系

STM32笔记---DMA(USART)的演示

分类:

 编程语言/ Flash/ 文章

 这里有个小小的例子,来演示DMA模块与系统程序并行工作。

  用串口以低波特率发送一个10K的数据,花费近10s时间,此时按照以往方法,CPU要不断等待数据发送、送数据;或者送数据、进中断、送数据,处理起来比较消耗时间。

  使用了DMA功能以后,用户程序中只需配置好DMA,开启传输后,再也不需要操心,10K数据完成后会有标志位或中断产生,期间可以做任何想做的事,非常方便。

  这个是相应的代码例子,基于STM32F103VBT6

/******************************************************************************

*本文件实现串口发送功能(通过重构putchar函数,调用printf;或者USART_SendData()

*这里是一个用串口实现大量数据传输的例子,使用了DMA模块进行内存到USART的传输

*每当USART的发送缓冲区空时,USART模块产生一个DMA事件,

*此时DMA模块响应该事件,自动从预先定义好的发送缓冲区中拿出下一个字节送给USART

*整个过程无需用户程序干预,用户只需启动DMA传输传输即可

*在仿真器调试时,可以在数据传输过程中暂停运行,此时DMA模块并没有停止

*串口依然发送,表明DMA传输是一个独立的过程。

*同时开启接收中断,在串口中断中将数据存入缓冲区,在main主循环中处理

*作者:

jjldc(九九)

*代码硬件基于万利199元的EK-STM32F开发板,CPU=STM32F103VBT6

*******************************************************************************/

/*Includes------------------------------------------------------------------*/

#include"stm32f10x_lib.h"

#include"stdio.h"

/*Privatetypedef-----------------------------------------------------------*/

/*Privatedefine------------------------------------------------------------*/

#defineUSART1_DR_Base 0x40013804

/*Privatemacro-------------------------------------------------------------*/

/*Privatevariables---------------------------------------------------------*/

#defineSENDBUFF_SIZE  10240

vu8SendBuff[SENDBUFF_SIZE];

vu8RecvBuff[10];

vu8recv_ptr;

/*Privatefunctionprototypes-----------------------------------------------*/

void RCC_Configuration(void);

void GPIO_Configuration(void);

void NVIC_Configuration(void);

void DMA_Configuration(void);

void USART1_Configuration(void);

int fputc(int ch, FILE *f);

void Delay(void);

/*Privatefunctions---------------------------------------------------------*/

/*******************************************************************************

*FunctionName :

main

*Description   :

Mainprogram.

*Input         :

None

*Output        :

None

*Return        :

None

*******************************************************************************/

int main(void)

{

   u16i;

#ifdefDEBUG

   debug();

#endif

   recv_ptr= 0;

    

   RCC_Configuration();

   GPIO_Configuration();

   NVIC_Configuration();

   DMA_Configuration();

   USART1_Configuration();

    

   printf("/r/nSystemStart.../r/n");

   printf("InitiallingSendBuff... /r/n");

    for(i=0;i

   {

       SendBuff[i]=i&0xff;

   }

   printf("Initialsuccess!

/r/nWaitingfortransmission.../r/n");

    //发送去数据已经准备好,按下按键即开始传输

    while(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_3));

    

   printf("StartDMAtransmission!

/r/n");

    

    //这里是开始DMA传输前的一些准备工作,将USART1模块设置成DMA方式工作

   USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);

    //开始一次DMA传输!

   DMA_Cmd(DMA1_Channel4,ENABLE);

    

    //等待DMA传输完成,此时我们来做另外一些事,点灯

    //实际应用中,传输数据期间,可以执行另外的任务

    while(DMA_GetFlagStatus(DMA1_FLAG_TC4)==RESET)

   {

       LED_1_REV;      //LED翻转

       Delay();        //浪费时间

   }

    //DMA传输结束后,自动关闭了DMA通道,而无需手动关闭

    //下面的语句被注释

    //DMA_Cmd(DMA1_Channel4,DISABLE);

    

   printf("/r/nDMAtransmissionsuccessful!

/r/n");

    

    /*Infiniteloop*/

    while 

(1)

   {

   }

}

/*******************************************************************************

*FunctionName :

重定义系统putchar函数intfputc(intch,FILE*f)

*Description   :

串口发一个字节

*Input         :

intch,FILE*f

*Output        :

 

*Return        :

intch

*这个是使用printf的关键

*******************************************************************************/

int fputc(int ch, FILE *f)

{

    //USART_SendData(USART1,(u8)ch);

   USART1->DR=(u8)ch;

    

    /*Loopuntiltheendoftransmission*/

    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET)

   {

   }

    return ch;

}

/*******************************************************************************

*FunctionName :

Delay

*Description   :

延时函数

*Input         :

None

*Output        :

None

*Return        :

None

*******************************************************************************/

void Delay(void)

{

   u32i;

    for(i=0;i<0xF0000;i++);

    return;

}

/*******************************************************************************

*FunctionName :

RCC_Configuration

*Description   :

系统时钟设置

*Input         :

None

*Output        :

None

*Return        :

None

*******************************************************************************/

void RCC_Configuration(void)

{

   ErrorStatusHSEStartUpStatus;

    //使能外部晶振

   RCC_HSEConfig(RCC_HSE_ON);

    //等待外部晶振稳定

   HSEStartUpStatus=RCC_WaitForHSEStartUp();

    //如果外部晶振启动成功,则进行下一步操作

    if(HSEStartUpStatus==SUCCESS)

   {

        //设置HCLK(AHB时钟)=SYSCLK

       RCC_HCLKConfig(RCC_SYSCLK_Div1);

        //PCLK1(APB1)=HCLK/2

       RCC_PCLK1Config(RCC_HCLK_Div2);

        //PCLK2(APB2)=HCLK

       RCC_PCLK2Config(RCC_HCLK_Div1);

        //FLASH时序控制

        //推荐值:

SYSCLK=0~24MHz  Latency=0

        //       SYSCLK=24~48MHz Latency=1

        //       SYSCLK=48~72MHz Latency=2

       FLASH_SetLatency(FLASH_Latency_2);

        //开启FLASH预取指功能

       FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

        //PLL设置SYSCLK/1*9=8*1*9=72MHz

       RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);

        //启动PLL

       RCC_PLLCmd(ENABLE);

        //等待PLL稳定

        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);

        //系统时钟SYSCLK来自PLL输出

       RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        //切换时钟后等待系统时钟稳定

        while(RCC_GetSYSCLKSource()!

=0x08);

        /*

       //设置系统SYSCLK时钟为HSE输入

       RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);

       //等待时钟切换成功

       while(RCC_GetSYSCLKSource()!

=0x04);

       */

   }

    //下面是给各模块开启时钟

    //启动GPIO

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|/

                          RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,/

                          ENABLE);

    //启动AFIO

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

    //启动USART1

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

    //启动DMA时钟

   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

    

}

/*******************************************************************************

*FunctionName :

GPIO_Configuration

*Description   :

GPIO设置

*Input         :

None

*Output        :

None

*Return        :

None

*******************************************************************************/

void GPIO_Configuration(void)

{

   GPIO_InitTypeDefGPIO_InitStructure;

    //PC口4567脚设置GPIO输出,推挽2M

   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;

   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;

   GPIO_Init(GPIOC,&GPIO_InitStructure);

    //KEY2KEY3JOYKEY

    //位于PD口的3411-15脚,使能设置为输入

   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_11|GPIO_Pin_12|/

       GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;

   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;

   GPIO_Init(GPIOD,&GPIO_InitStructure);

    //USART1_TX

   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;

   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

   GPIO_Init(GPIOA,&GPIO_InitStructure);

    

    //USART1_RX

   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;

   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;

   GPIO_Init(GPIOA,&GPIO_InitStructure);

}

/*******************************************************************************

*FunctionName :

NVIC_Configuration

*Description   :

NVIC设置

*Input         :

None

*Output        :

None

*Return        :

None

*******************************************************************************/

void NVIC_Configuration(void)

{

   NVIC_InitTypeDefNVIC_InitStructure;

#ifdef VECT_TAB_RAM

    //SettheVectorTablebaselocationat0x20000000

   NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else  /*VECT_TAB_FLASH */

    //SettheVectorTablebaselocationat0x08000000

   NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

    //设置NVIC优先级分组为Group2:

0-3抢占式优先级,0-3的响应式优先级

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    //串口接收中断打开    

   NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQChannel;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;

   NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

   NVIC_Init(&NVIC_InitStructure);

}

/*******************************************************************************

*FunctionName :

USART1_Configuration

*Description   :

NUSART1设置

*Input         :

None

*Output        :

None

*Return        :

None

*******************************************************************************/

void USART1_Configuration(void)

{

   USART_InitTypeDefUSART_InitStructure;

    

   USART_InitStructure.USART_BaudRate= 9600;

   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_Tx|USART_Mode_Rx;

   USART_Init(USART1,&USART_InitStructure);

    

   USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

    

   USART_Cmd(USART1,ENABLE);

}

void DMA_Configuration(void)

{

   DMA_InitTypeDefDMA_InitStructure;

    //DMA设置:

    //设置DMA源:

内存地址&串口数据寄存器地址

    //方向:

内存-->外设

    //每次传输位:

8bit

    //传输大小DMA_BufferSize=SENDBUFF_SIZE

    //地址自增模式:

外设地址不增,内存地址自增1

    //DMA模式:

一次传输,非循环

    //优先级:

   DMA_DeInit(DMA1_Channel4);

   DMA_InitStruc

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

当前位置:首页 > 法律文书 > 辩护词

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

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