1.初始化

//RCC
RCC->APB1ENR|=1<<20; //使能串口5时钟
RCC->APB1ENR|=1<<19; //使能串口4时钟
RCC->APB1ENR|=1<<18; //使能串口3时钟
RCC->APB1ENR|=1<<17; //使能串口2时钟
RCC->APB2ENR|=1<<4; //使能串口1时钟
RCC->APB2ENR|=1<<5; //使能串口6时钟
RCC->AHB1ENR|=1<<21;//DMA1时钟使能
RCC->AHB1ENR|=1<<22;//DMA2时钟使能 //GPIO
//串口6
GPIO_AF_Set(GPIOG,9,8);
GPIO_AF_Set(GPIOG,14,8);
GPIO_Set(GPIOG,PIN9|PIN14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PD);//复用功能 //UART4
DMA1_Stream2->PAR=(uint32_t)&(UART4->DR); //DMA外设地址 多重ADC->CDR
DMA1_Stream2->CR=0; //先全部复位CR寄存器值
DMA1_Stream2->NDTR=50; //传输数据项个数
DMA1_Stream2->M0AR= (uint32_t)_rece_data1; //DMA 存储器0地址
DMA1_Stream2->CR|=4<<25; //通道选择4
DMA1_Stream2->CR|=0<<23; //存储器单次传输
DMA1_Stream2->CR|=0<<21; //外设单次传输
DMA1_Stream2->CR|=1<<16; //中等优先级 2:高 3:非常高
DMA1_Stream2->CR|=0<<13; //存储器数据大小为8位 0:8位 1:16位 2:32位
DMA1_Stream2->CR|=0<<11; //外设数据大小为8位 0:8位 1:16位 2:32位
DMA1_Stream2->CR|=1<<10; //存储器地址递增
DMA1_Stream2->CR|=0<<9; //外设地址固定
DMA1_Stream2->CR|=0<<8; //普通模式
DMA1_Stream2->CR|=0<<6; //0:外设到存储器 1:存储器到外设 2:存储器到存储器
DMA1_Stream2->CR|=1<<4; //开启传输完成中断
DMA1_Stream2->CR|=1<<0; //开启DMA传输 MY_NVIC_Init(3,0,DMA1_Stream2_IRQn,4); //抢占1,子优先级3,组2
MY_NVIC_Init(2,0,UART4_IRQn,4); //抢占1,子优先级3,组2
//波特率为
temp=(float)(42000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整数部分
fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction; UART4->CR1 = 0;
UART4->CR3 = 0;
//波特率设置
UART4->BRR=mantissa; //波特率设置
UART4->CR1&=~(1<<15); //设置OVER8=0
UART4->CR1|=1<<4; //空闲中断
UART4->CR1|=1<<3; //串口发送使能
UART4->CR1|=1<<2; //串口接收使能
UART4->CR3|=1<<6; //开启DMA输出
//使能
UART4->CR1|=1<<13; //串口使能 //UART5
//接收
DMA1_Stream0->PAR=(uint32_t)&(UART5->DR); //DMA外设地址 多重ADC->CDR
DMA1_Stream0->CR=0; //先全部复位CR寄存器值
DMA1_Stream0->M0AR= (uint32_t)_rece_data2; //DMA 存储器0地址
DMA1_Stream0->NDTR=50; //传输数据项个数
DMA1_Stream0->CR|=4<<25; //通道选择4
DMA1_Stream0->CR|=0<<23; //存储器单次传输
DMA1_Stream0->CR|=0<<21; //外设单次传输
DMA1_Stream0->CR|=1<<16; //中等优先级 2:高 3:非常高
DMA1_Stream0->CR|=0<<13; //存储器数据大小为8位 0:8位 1:16位 2:32位
DMA1_Stream0->CR|=0<<11; //外设数据大小为8位 0:8位 1:16位 2:32位
DMA1_Stream0->CR|=1<<10; //存储器地址递增
DMA1_Stream0->CR|=0<<9; //外设地址固定
DMA1_Stream0->CR|=0<<8; //普通模式
DMA1_Stream0->CR|=0<<6; //0:外设到存储器 1:存储器到外设 2:存储器到存储器
DMA1_Stream0->CR|=1<<4; //开启传输完成中断
DMA1_Stream0->CR|=1<<0; //开启DMA传输
MY_NVIC_Init(4,0,DMA1_Stream0_IRQn,4); //抢占1,子优先级3,组2
MY_NVIC_Init(3,0,UART5_IRQn,4); //抢占1,子优先级3,组2 //发送
DMA1_Stream7->M0AR= (uint32_t)uart5_send; //DMA 存储器0地址
DMA1_Stream7->NDTR=0; //传输数据项个数
DMA1_Stream7->PAR=(uint32_t)&(UART5->DR); //DMA外设地址 多重ADC->CDR
DMA1_Stream7->CR=0; //先全部复位CR寄存器值
DMA1_Stream7->CR|=4<<25; //通道选择4
DMA1_Stream7->CR|=0<<23; //存储器单次传输
DMA1_Stream7->CR|=0<<21; //外设单次传输
DMA1_Stream7->CR|=3<<16; //中等优先级 2:高 3:非常高
DMA1_Stream7->CR|=0<<13; //存储器数据大小为8位 0:8位 1:16位 2:32位
DMA1_Stream7->CR|=0<<11; //外设数据大小为8位 0:8位 1:16位 2:32位
DMA1_Stream7->CR|=1<<10; //存储器地址递增
DMA1_Stream7->CR|=0<<9; //外设地址固定
DMA1_Stream7->CR|=0<<8; //普通模式
DMA1_Stream7->CR|=1<<6; //0:外设到存储器 1:存储器到外设 2:存储器到存储器 //波特率为
temp=(float)(42000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整数部分
fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
UART5->CR1 = 0;
UART5->CR3 = 0;
//波特率设置
UART5->BRR=mantissa; //波特率设置
UART5->CR1&=~(1<<15); //设置OVER8=0
UART5->CR1|=1<<4; //空闲中断
UART5->CR1|=1<<3; //串口发送使能
UART5->CR1|=1<<2; //串口接收使能
UART5->CR3|=1<<6; //开启DMA接收
UART5->CR3|=1<<7; //开启DMA发送
//使能
UART5->CR1|=1<<13; //串口使能 //USART6
DMA2_Stream1->PAR=(uint32_t)&(USART6->DR); //DMA外设地址 多重ADC->CDR
DMA2_Stream1->CR=0; //先全部复位CR寄存器值
DMA2_Stream1->M0AR= (uint32_t)_rece_data3; //DMA 存储器0地址
DMA2_Stream1->NDTR=50; //传输数据项个数
DMA2_Stream1->CR|=5<<25; //通道选择5
DMA2_Stream1->CR|=0<<23; //存储器单次传输
DMA2_Stream1->CR|=0<<21; //外设单次传输
DMA2_Stream1->CR|=1<<16; //中等优先级 2:高 3:非常高
DMA2_Stream1->CR|=0<<13; //存储器数据大小为8位 0:8位 1:16位 2:32位
DMA2_Stream1->CR|=0<<11; //外设数据大小为8位 0:8位 1:16位 2:32位
DMA2_Stream1->CR|=1<<10; //存储器地址递增
DMA2_Stream1->CR|=0<<9; //外设地址固定
DMA2_Stream1->CR|=0<<8; //普通模式
DMA2_Stream1->CR|=0<<6; //0:外设到存储器 1:存储器到外设 2:存储器到存储器
DMA2_Stream1->CR|=1<<4; //开启传输完成中断
DMA2_Stream1->CR|=1<<0; //开启DMA传输
MY_NVIC_Init(5,0,DMA2_Stream1_IRQn,4); //抢占1,子优先级3,组2
MY_NVIC_Init(4,0,USART6_IRQn,4); //抢占1,子优先级3,组2
//波特率为
temp=(float)(84000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整数部分
fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
USART6->CR1 = 0;
USART6->CR3 = 0;
//波特率设置
USART6->BRR=mantissa; //波特率设置
USART6->CR1&=~(1<<15); //设置OVER8=0
USART6->CR1|=1<<4; //空闲中断
USART6->CR1|=1<<3; //串口发送使能
USART6->CR1|=1<<2; //串口接收使能
USART6->CR3|=1<<6; //开启DMA输出
//使能
USART6->CR1|=1<<13; //串口使能 //USART1
DMA2_Stream2->PAR=(uint32_t)&(USART1->DR); //DMA外设地址 多重ADC->CDR
DMA2_Stream2->CR=0; //先全部复位CR寄存器值
DMA2_Stream2->M0AR= (uint32_t)_rece_data4; //DMA 存储器0地址
DMA2_Stream2->NDTR=50; //传输数据项个数
DMA2_Stream2->CR|=4<<25; //通道选择4
DMA2_Stream2->CR|=0<<23; //存储器单次传输
DMA2_Stream2->CR|=0<<21; //外设单次传输
DMA2_Stream2->CR|=1<<16; //中等优先级 2:高 3:非常高
DMA2_Stream2->CR|=0<<13; //存储器数据大小为8位 0:8位 1:16位 2:32位
DMA2_Stream2->CR|=0<<11; //外设数据大小为8位 0:8位 1:16位 2:32位
DMA2_Stream2->CR|=1<<10; //存储器地址递增
DMA2_Stream2->CR|=0<<9; //外设地址固定
DMA2_Stream2->CR|=0<<8; //普通模式
DMA2_Stream2->CR|=0<<6; //0:外设到存储器 1:存储器到外设 2:存储器到存储器
DMA2_Stream2->CR|=1<<4; //开启传输完成中断
DMA2_Stream2->CR|=1<<0; //开启DMA传输
MY_NVIC_Init(6,0,DMA2_Stream2_IRQn,4); //抢占1,子优先级3,组2
MY_NVIC_Init(5,0,USART1_IRQn,4); //抢占1,子优先级3,组2
//波特率为
temp=(float)(84000000)/(_baud*16);//得到USARTDIV@OVER8=0
mantissa=(u16)(temp); //得到整数部分
fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
USART1->CR1 = 0;
USART1->CR3 = 0;
//波特率设置
USART1->BRR=mantissa; //波特率设置
USART1->CR1&=~(1<<15); //设置OVER8=0
USART1->CR1|=1<<4; //空闲中断
USART1->CR1|=1<<3; //串口发送使能
USART1->CR1|=1<<2; //串口接收使能
USART1->CR3|=1<<6; //开启DMA输出
//使能
USART1->CR1|=1<<13; //串口使能

2.串口空闲中断接收

void UART4_IRQHandler(void)
{
if( ( UART4->SR&(1<<4) ) >> 4 == 1 ) //发生空闲中断
{
DMA1_Stream2->CR &= ~(1<<0); //关闭DMA传输 会发生DMA完成中断
UART4->CR1 &= ~(1<<2); //接收关闭
UART4->SR;
UART4->DR;
}
}
void DMA1_Stream2_IRQHandler(void)
{
u8 num = 0;
if( ( DMA1->LISR&(1<<21) ) >> 21 == 1 ) //完成中断
{
DMA1_Stream2->CR &= ~(1<<0); //关闭DMA传输
num = 50 - DMA1_Stream2 ->NDTR; //获取读到的字节数
if( usart1_nux == 0 ) //互斥量,未使用数据,可进行更改
{
for( u8 i =0; i<num; i++ )
{
_rece_temp1[i] = _rece_data1[i];
}
}
usart1_num = num; DMA1_Stream2->NDTR = 50; //重新填充
DMA1->LIFCR |= 1<<21; //清除完成中断标志位
DMA1_Stream2->CR |= 1<<0; //开启DMA传输
UART4->CR1 |= 1<<2; //接收开启
}
} void UART5_IRQHandler(void)
{ if( ( UART5->SR&(1<<4) ) >> 4 == 1 ) //发生空闲中断
{
DMA1_Stream0->CR &= ~(1<<0); //关闭DMA传输
UART5->CR1 &= ~(1<<2); //接收关闭
UART5->SR;
UART5->DR;
}
}
void DMA1_Stream0_IRQHandler(void)
{
u8 num = 0; num = 50 - DMA1_Stream0 ->NDTR; //获取读到的字节数
if( usart2_nux == 0 )
{
for( u8 i =0; i<num; i++ )
{
_rece_temp2[i] = _rece_data2[i];
}
}
usart2_num = num;
DMA1_Stream0->NDTR = 50; //重新填充
DMA1->LIFCR |= 1<<5;
DMA1_Stream0->CR |= 1<<0; //开启DMA传输
UART5->CR1 |= 1<<2; //接收开启
} void USART6_IRQHandler(void)
{
if( ( USART6->SR&(1<<4) ) >> 4 == 1 ) //发生空闲中断
{
DMA2_Stream1->CR &= ~(1<<0); //关闭DMA传输
USART6->CR1 &= ~(1<<2); //接收关闭
USART6->SR;
USART6->DR;
}
}
void DMA2_Stream1_IRQHandler(void)
{
u8 num = 0; num = 50 - DMA2_Stream1 ->NDTR; //获取读到的字节数
if( usart3_nux == 0 )
{
for( u8 i =0; i<num; i++ )
{
_rece_temp3[i] = _rece_data3[i];
}
}
usart3_num = num; DMA2_Stream1->NDTR = 50; //重新填充
DMA2->LIFCR |= 1<<11;
DMA2_Stream1->CR |= 1<<0; //开启DMA传输
USART6->CR1 |= 1<<2; //接收开启
}
} void USART1_IRQHandler(void)
{
if( ( USART1->SR&(1<<4) ) >> 4 == 1 ) //发生空闲中断
{
DMA2_Stream2->CR &= ~(1<<0); //关闭DMA传输,此时会发生DMA完成中断
USART1->CR1 &= ~(1<<2); //接收关闭
USART1->SR;
USART1->DR;
}
}
void DMA2_Stream2_IRQHandler(void)
{
u8 num = 0;
num = 50 - DMA2_Stream2 ->NDTR; //获取读到的字节数
if( usart4_nux == 0 )
{
for( u8 i =0; i<num; i++ )
{
_rece_temp4[i] = _rece_data4[i];
}
}
usart4_num = num;
DMA2_Stream2->NDTR = 50; //重新填充
DMA2->LIFCR |= 1<<21;
DMA2_Stream2->CR |= 1<<0; //开启DMA传输
USART1->CR1 |= 1<<2; //接收开启
} //接收函数
u8 USART_RECE(u8 _sum, u8 *_rece)
{
u8 temp = 0;
if(_sum >50)
{
_sum = 50;
}
if( usart4_num == 0 )
{
return 0;
}
else
{
usart4_nux = 1; //互斥量,占用数据
for( u8 i=0; i<_sum; i++ )
{
*_rece = _rece_temp4[i];
if( i+1 > usart4_num ) //请求读数据量超过接收数据量,后面置0
{
*_rece = 0;
}
_rece++;
}
temp = usart4_num;
usart4_nux = 0; //释放互斥量
usart4_num = 0;
}
return temp; //返回接收到的数据个数
}

3.串口DMA发送

//发送函数
void UART5_SEND(u8 _sum, const u8 *_send){
static uint8_t send_flag = 0;
u8 *pBuf = NULL;
pBuf = uart5_send;
if( _sum > 50 )
{
_sum = 50;
}
for( u8 i=0; i<_sum; i++ )
{
*pBuf++ = *_send++;
}
if( send_flag == 0 ) //未进行过发送,直接发
{
DMA1_Stream7->NDTR=_sum; //数据传输量
DMA1_Stream7->CR|=1<<0; //开启DMA传输
send_flag = 1;
}
else //等待发送完成后,再进行发送
{
if((DMA1->HISR & (1<<27)) >> 27==1) //DMA1_Steam7传输完成标志
{
DMA1_Stream7->CR&=~(1<<0); //关闭DMA
while((DMA1_Stream7->CR & (uint32_t)DMA_SxCR_EN) != 0); //确保DMA可以被设置
DMA1->HIFCR|=1<<27;//清除DMA1_Steam7传输完成标志,不清的话第二次不能发送
DMA1_Stream7->NDTR=_sum; //数据传输量
DMA1_Stream7->CR|=1<<0; //开启DMA传输
}
}
}

STM32F4寄存器串口DMA汇总的更多相关文章

  1. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

  2. STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率

    前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...

  3. STM32CubeMX HAL库串口+DMA数据发送不定长度数据接收

    参考资料:1.ST HAL库官网资料 2.https://blog.csdn.net/u014470361/article/details/79206352#comments 一.STM32CubeM ...

  4. RT-Thread中的串口DMA分析

    这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考. 背景 在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的 ...

  5. 为何串口dma发送数据可能不完整

    串口dma数据发送不完整, 1. 通过打印log说明数据合成,送给dma buff都是正常的. 2. 数据通过硬件串口直接配置,是正常的 3. 数据通过单片机dma转发后数据异常,通过检查发现 dma ...

  6. STM32F4 SPI with DMA

    STM32F4 SPI with DMA A few people have requested code, so I thought I’d post the code showing how I’ ...

  7. cubemx+stm32串口学习汇总资料

    这篇文章是串口中断的文章--STM32基于CubeMX的高速串口收发程序(中断模式)比较有帮助. http://www.stmcu.org.cn/module/forum/thread-616613- ...

  8. STM32串口DMA接收数据错位——暴力解决方法

    背景:两片STM32通过串口通信,为了减小CPU负担,采用DMA进行通信,发送端为STM32F103C8T6,接收端为STM32F407VET6.在调试的过程中发现,一直出现数据错位的问题,接收端尝试 ...

  9. STM32串口DMA超时接收方法,可大大节约CPU时间

    //超时时间定义#define        UART1_TimeoutComp 2  //20ms#define        UART2_TimeoutComp 10  //100ms#defin ...

  10. STM32 串口DMA方式接收(转)

    STM32 是一款基于ARM Cortex-M3内核的32位MCU,主频最高可达72M.最近因为要在车机上集成TPMS功能, 便开始着手STM32的开发工作,STM32F10x系列共有5个串口(USA ...

随机推荐

  1. Seata 1.5.2 源码学习(Client端)

    在上一篇中通过阅读Seata服务端的代码,我们了解到TC是如何处理来自客户端的请求的,今天这一篇一起来了解一下客户端是如何处理TC发过来的请求的.要想搞清楚这一点,还得从GlobalTransacti ...

  2. 8 STL-stack

    ​ 重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦!  生命就像一朵花,要拼尽全力绽放!死磕自个儿,身心愉悦! 写在前面,本篇章主要介绍S ...

  3. Python: 你所不知道的星号 * 用法

    以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://mp.weixin.qq.com/s/FHyosiG_tegF5NRUEs7UdA 本文大概 1193 个 ...

  4. Datawhale组队学习_Task02:详读西瓜书+南瓜书第3章

    第3章 线性模型 家人们又来吃瓜了! 3.1 基本形式 线性模型的本质是通过一个所有属性的线性组合进行预测的函数,即 $\mathcal{f(x)=w_1x_1+w_2x_2+...+w_dx_d+b ...

  5. SpringMVC03:SSM整合

    一.搭建整合环境 1.ssm整合说明 2.搭建环境 二.Spring框架代码的编写 1.编写Spring框架(处理业务层) applicationContext.xml <?xml versio ...

  6. 【每日一题】【DFS&每个点都调用一次前后左右】由1连接的岛屿数量-211031/220216

    给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网格的四条边 ...

  7. 动态SQL遇到的问题

    看图 查不出来任何数据 因为判断有问题 修改方法如下:

  8. linux 删除influxdb的某条数据

    1.进入服务器,输入: influx 进入influxdb 2.继续输入: show databases 显示所有的数据库名称 3.继续输入: use database 使用某一个数据库 ps:此处的 ...

  9. MasaFramework -- i18n (国际化)

    概念 作为一个普通开发者, 我们负责的项目的使用群体大多数是本国的人民, 但不可避免的也有一些做外贸的业务或者给外企做的项目, 这个时候就要求我们的项目有服务全球客户的能力, 而一个支持国际化能力的框 ...

  10. [编程基础] Python列表解析总结

    在本教程中,我们将学习使用Python列表解析(list comprehensions)相关知识 1 使用介绍 列表解析是一种基于现有列表创建列表的句法结构.列表解析提供了创建列表的简洁方法.通常需要 ...