STM32:DMA实例之串口(USART)通信

2020-07-04来源: eefocus关键字:STM32  DMA  串口(USART)通信

硬件平台:stm32f10xZET6

开发环境:keil MDK uVision v4.10

开发语言:C、ST_lib_3.5固件库


/* 代码演示 main.c */

#include "stm32f10x.h"

#include "bsp_usart1.h"

#include "bsp_led.h"

 

extern uint8_t SendBuff[SENDBUFF_SIZE];

static void Delay(__IO u32 nCount); 

 

/**

  * @brief  主函数

  */

int main(void)

{

/* USART1 config 115200 8-N-1 */

USART1_Config();

USART1_DMA_Config();

LED_GPIO_Config();

printf ("rn usart1 DMA TX test... rn");

{

uint16_t i;

/*填充将要发送的数据*/

for(i=0;i

{

SendBuff[i] = 'a'; // 打字母a仅做演示

}

}

/* USART1 向 DMA发出TX请求 */

USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);

 

/* 此时CPU是空闲的,可以干其他的事情 */

//例如同时控制LED

for(;;)

{

LED1(ON);

Delay(0xFFFFF);

LED1(OFF);

Delay(0xFFFFF);

}

}

 

static void Delay(__IO uint32_t nCount) //简单的延时函数

{

for(; nCount != 0; nCount--);

}

/* 中断处理函数 stm32f10x_it.c line:157 */

void DMA1_Channel4_IRQHandler(void)

{

//判断是否为 DMA 发送完成中断

if (DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET)

{

//LED 关闭

LED1(OFF);

 

 

DMA_ClearFlag(DMA1_FLAG_TC4);

}

}

/* 代码演示 bsp_usart1模块 */

#ifndef __USART1_H

#define __USART1_H

 

 

#include "stm32f10x.h"

#include

 

 

#define USART1_DR_Base  0x40013804 // 0x40013800 + 0x04 = 0x40013804

#define SENDBUFF_SIZE   5000

 

 

void USART1_Config(void);

void USART1_DMA_Config(void);

 

 

#endif /* __USART1_H */

// ------------------------------------------------------

#include "bsp_usart1.h"

 

 

uint8_t SendBuff[SENDBUFF_SIZE];

 

 

/**

  * @brief  USART1 GPIO 配置,工作模式配置。115200 8-N-1

  * @param  无

  * @retval 无

  */

void USART1_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

/* config USART1 clock */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

/* USART1 GPIO config */

/* Configure USART1 Tx (PA.09) as alternate function push-pull */

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);    

/* Configure USART1 Rx (PA.10) as input floating */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* USART1 mode config */

USART_InitStructure.USART_BaudRate = 115200;

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_Cmd(USART1, ENABLE);

}

 

 

/**

  * @brief  USART1 TX DMA 配置,内存到外设(USART1->DR)

  * @param  无

  * @retval 无

  */

void USART1_DMA_Config(void)

{

DMA_InitTypeDef DMA_InitStructure;

/*开启DMA时钟*/

RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, ENABLE);

 

 

/*传输大小DMA_BufferSize=SENDBUFF_SIZE*/

DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;  // 此处是发送的buffer的配置

/*方向:从内存到外设*/

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

/*禁止内存到内存的传输 */

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

 

 

/*内存地址(要传输的变量的指针)*/

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;

/*内存数据单位 8bit*/

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

/*内存地址自增*/

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

 

 

/*DMA模式:不断循环*/

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  

 

/* 设置DMA源:串口数据寄存器地址 */

DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;

/* 外设数据单位:字节 */

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    

  /* 外设地址不增 */     

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 

 

 

/*优先级:中*/

DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  

 

 

/*配置DMA1的4通道*/    

DMA_Init(DMA1_Channel4, &DMA_InitStructure);    

/*使能DMA*/

DMA_Cmd (DMA1_Channel4,ENABLE);

//DMA_ITConfig(DMA1_Channel4, DMA_IT_TC,ENABLE);  // 配置DMA发送完成后产生中断

}

 

 

/// 重定向c库函数printf到USART1

int fputc(int ch, FILE *f)

{

/* 发送一个字节数据到USART1 */

USART_SendData(USART1, (uint8_t) ch);

/* 等待发送完毕 */

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

return (ch);

}

 

 

/// 重定向c库函数scanf到USART1

int fgetc(FILE *f)

{

/* 等待串口1输入数据 */

while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

 

 

return (int)USART_ReceiveData(USART1);

}

/* 代码演示 bsp_led模块 */

#ifndef __LED_H

#define __LED_H

 

 

#include "stm32f10x.h"

 

 

/** the macro definition to trigger the led on or off 

  * 1 - off

  *0 - on

  */

#define ON  0

#define OFF 1

 

 

/* 带参宏,可以像内联函数一样使用 */

#define LED1(a) if (a)

GPIO_SetBits(GPIOB,GPIO_Pin_0);

else

GPIO_ResetBits(GPIOB,GPIO_Pin_0)

 

#define LED2(a) if (a)

GPIO_SetBits(GPIOF,GPIO_Pin_7);

else

GPIO_ResetBits(GPIOF,GPIO_Pin_7)

 

#define LED3(a) if (a)

GPIO_SetBits(GPIOF,GPIO_Pin_8);

else

GPIO_ResetBits(GPIOF,GPIO_Pin_8)

 

void LED_GPIO_Config(void);

 

#endif /* __LED_H */

//---------------------------------------------------------

#include "bsp_led.h"   

 

 

 /**

  * @brief  初始化控制LED的IO

  * @param  无

  * @retval 无

  */

void LED_GPIO_Config(void)

{

/*定义一个GPIO_InitTypeDef类型的结构体*/

GPIO_InitTypeDef GPIO_InitStructure;

 

 

/*开启GPIOB和GPIOF的外设时钟*/

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE); 

 

 

/*选择要控制的GPIOB引脚*/    

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

 

 

/*设置引脚模式为通用推挽输出*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

 

 

/*设置引脚速率为50MHz */   

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

 

 

/*调用库函数,初始化GPIOB0*/

GPIO_Init(GPIOB, &GPIO_InitStructure);

/*选择要控制的GPIOF引脚*/    

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

 

 

/*调用库函数,初始化GPIOF7*/

GPIO_Init(GPIOF, &GPIO_InitStructure);

/*选择要控制的GPIOF引脚*/    

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

 

 

/*调用库函数,初始化GPIOF7*/

GPIO_Init(GPIOF, &GPIO_InitStructure);   

 

 

/* 关闭所有led灯 */

GPIO_SetBits(GPIOB, GPIO_Pin_0);

/* 关闭所有led灯 */

GPIO_SetBits(GPIOF, GPIO_Pin_7|GPIO_Pin_8);  

}

*注:LED灯的管脚Pin根据开发板的不同,实际去调整即可。

关键字:STM32  DMA  串口(USART)通信 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic502125.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:串口通讯(DMA模式)
下一篇:通过DMA向串口发送数据

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32F10X ADC原理详解(STM32F103ZET6)
STM32ADC的工作原理模/数转换器STM32F10x  ADC特点12位逐次逼近型的模拟数字转换器。最多带3个ADC控制器最多支持18个通道,可最多测量16个外部和2个内部信号源。支持单次和连续转换模式转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。通道0到通道n的自动扫描模式自动校准采样间隔可以按通道编程规则通道和注入通道均有外部触发选项转换结果支持左对齐或右对齐方式存储在16位数据寄存器ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)ADC供电要求:2.4V-3.6VADC输入范围:VREF- ≤  VIN 
发表于 2020-07-25
<font color='red'>STM32</font>F10X ADC原理详解(<font color='red'>STM32</font>F103ZET6)
STM32控制步进电机程序
、IN3:PC0、IN4:PC13、//步进电机初始化函数void Motor_Init(void){        GPIO_InitTypeDef GPIO_InitStructure;                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启时钟                GPIO_InitStructure.GPIO
发表于 2020-07-25
<font color='red'>STM32</font>控制步进电机程序
基于IAR环境下STM32F103单片机读取BME280程序
自己编写的基于IAR环境下STM32F103单片机读取BME280程序,没有太多的寄存器操作,简单易懂,可以直接调用,上电后只要对IO口初始化,调用函数Bme_ReadDigValue()读取校准寄存器参数并保存,再调用函数Bme_Init()初始化之后就可以用函数Bme_ReadStatus()读取传感器状态判断是否读取数据了,也可不判断传感器状态直接读取数据,读取数据直接调用函数ReadBme280()。单片机源程序:void ReadBme280(){        u32 value_ad;        double var1; 
发表于 2020-07-25
STM32步进伺服电机梯形加速源程序 单轴简易运动控制器
步进电机梯形加速程序单片机源程序如下:/*基于STM32的单轴简易运动控制器/脉冲发生器*//*脉冲+方向控制步进伺服电机*//*优化记录:增加急停GPIOC.0、正向极限GPIOC.1、负向极限GPIOC.2等输入IO接点中断修改TIMx_PSC一个寄存器的值,而不是修改TIMx_ARR预加载寄存器+TIMx_CCRx比较值寄存器两个值,缩短中断处理时间定位指令DRVI/DRVA中,目标频率设定过高、而实际输出脉冲数过少时,则不必加速到目标频率即进入减速区*//*DRVI(A);相对定位,输出A(A取绝对值)个脉冲A不能为0若A为正数,则方向为正、GPIOB.0为高电平若A为负数,则方向为负、GPIOB.0为低电平DRVA
发表于 2020-07-25
STM32实现ADS1256进行数据电压采集程序
通过cubeMX配置STM32RCT6的IO口与ads1256ADC模块的连接IO口工作模式SPI,还有接受中断接受状态引脚,最终ADC采集数据经过卡尔曼滤波器滤波输出单片机源程序如下:#include "ads1256.h"int32_t adcVaule = 0x00;float voltage = 0x00;float filterVoltage = 0.0;float filterVoltage2 = 0.0;void delayXus(uint16_t us) {    uint16_t diff = 0xffff - 5 - us;    //设置定时器的计数
发表于 2020-07-25
基于WiFi的网络授时时钟(带实时天气更新)STM32程序设计
本方案采用的是MCU+AT指令的形式开发,MCU是大家比较熟悉的意法半导体公司STM32F103C8T6,WiFi模块使用的是安信可ESP-12F,本方案是一个Demo设计,比较简单,仅实现了功能,算是一个抛砖引玉吧!先上视频演示:https://v.youku.com/v_show/id_XN ... m=a2hzp.8244740.0.0WiFi模块资料链接:wiki点ai-thinker点com/esp8266STM32F103C8芯片资料链接:https://www.stmicroelectronics.c ... 103c8.html#overview硬件部分,由时钟电路+WiFi模块+MCU最小系统+OLED
发表于 2020-07-25
基于WiFi的网络授时时钟(带实时天气更新)<font color='red'>STM32</font>程序设计
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved