DMA接收串口数据(定长与不定长)
Posted 文某9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DMA接收串口数据(定长与不定长)相关的知识,希望对你有一定的参考价值。
效果如图
串口配置(可以直接拷贝拿去用)
#include "sys.h"
#include "usart.h"
//
//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
int handle;
;
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
x = x;
//重定义fputc函数
int fputc(int ch, FILE *f)
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
#endif
#if EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记
void uart_init(u32 bound)
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
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); //初始化串口1
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能串口1的DMA发送
void USART1_IRQHandler(void) //串口1中断服务程序
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
Res =USART_ReceiveData(USART1); //读取接收到的数据
#endif
DMA配置
#include "dma.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK精英STM32开发板
//DMA 代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/8
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//
DMA_InitTypeDef DMA_InitStructure;
u16 DMA1_MEM_LEN;//保存DMA每次数据传送的长度
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA1_MEM_LEN=cndtr;
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Rx_DMA 所标识的寄存器
USART_Cmd(USART1, ENABLE); //使能串口1
DMA_Cmd(DMA_CHx, ENABLE); //使能USART1 TX DMA1 所指示的通道
MYDMA_Enable(DMA1_Channel5);//开始一次DMA传输!
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
DMA_Cmd(DMA_CHx, DISABLE ); //关闭USART1 TX DMA1 所指示的通道
DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小
DMA_Cmd(DMA_CHx, ENABLE); //使能USART1 TX DMA1 所指示的通道
主函数(定长)
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "dma.h"
#include "string.h"
int main(void)
u8 USART_RX_BUF1[50];
delay_init();
uart_init(115200);
MYDMA_Config(DMA1_Channel5,(u32)&USART1->DR,(u32)USART_RX_BUF1,50);//DMA1通道5,外设为串口1,存储器为SendBuff,长度35,
while(1)
if(DMA_GetFlagStatus(DMA1_FLAG_TC5)!=RESET) //判断通道5传输完成
DMA_ClearFlag(DMA1_FLAG_TC5);//清除通道4传输完成标志
delay_ms(10); //延时10ms,让DMA继续接收后面数据的同时,也能跑跑其它进程
printf("1:%s\\r\\n",USART_RX_BUF1); //打印
memset(USART_RX_BUF1,0,35); //清空数组
MYDMA_Enable(DMA1_Channel5);//开始一次DMA传输!
主函数(不定长)
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "dma.h"
#include "string.h"
int main(void)
u8 USART_RX_BUF1[50];
delay_init();
uart_init(115200);
MYDMA_Config(DMA1_Channel5,(u32)&USART1->DR,(u32)USART_RX_BUF1,50);//DMA1通道5,外设为串口1,存储器为SendBuff,长度35,
while(1)
if(USART_RX_BUF1[0]!=0) //判断通道4传输完成
delay_ms(10); //延时10ms,让DMA继续接收后面数据的同时,也能跑跑其它进程
printf("1:%s\\r\\n",USART_RX_BUF1); //打印
memset(USART_RX_BUF1,0,35); //清空数组
MYDMA_Enable(DMA1_Channel5);//开始一次DMA传输!
标志位说明
以上是关于DMA接收串口数据(定长与不定长)的主要内容,如果未能解决你的问题,请参考以下文章
STM32F4 DMA接收串口定长数据,串口每秒来1000个数据,使用DMA-Normal模式