关于串口发送数据DMA多次发送的问题求教

只需一步,快速开始
后使用快捷导航没有帐号?
STM32CubeMX系列教程5:串行通信(USART)
查看: 42366|
评论: |原作者: MyMX1213
摘要: 本章以串口为例讲解,HAL 库轮询,中断,DMA 三种编程模型。
本章以串口为例讲解,HAL 库轮询,中断,DMA 三种编程模型。1.前情回顾& & & &在串行通信中,一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束。在进行传输之前,双方一定要使用同一个波特率设置。波特率就是每秒钟传输的数据位数。& & & &常用的两种基本串行通信方式包括同步通信和异步通信。我们通常使用的是异步通信.异步通信规定传输的数据格式由起始位(start&bit)、数据位(data&bit)、奇偶校验位(parity&bit)和停止位(stop&bit)组成。2.重定义printf函数。& & & & 打开STM32CubeMX新建工程,选择STMF746IGT6芯片,选择外部高速晶振(HSE)。USART1选择为异步通信方式。PA10设置RX接收,PA9设置为TX发送。配置时钟系统时钟为216MHz,STMF746可以单独配置USART时钟,默认为108Mhz。串口配置设置波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1.其他参数默认。& & & & 生成报告以及代码,编译程序。在usart.c文件中可看到串口1的初始化函数MX_USART1_UART_Init(void),以及管脚配置函数HAL_UART_MspInit()。& & & & C语言中的标准库中所用的标准输出函数,默认的输出设备是显示器,要实现串口或LCD的输出,必须重新定义标准库函数里与输出函数相关的函数。例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下:只要自己添加一个int&fputc(int&ch,&FILE&*f)函数,能够输出字符就可以了。& & & & 在usart.c文件后面添加如下代码,代码中添加了#ifdef宏定义进行条件编译,如果使用GUNC编译,则PUTCHAR_PROTOTYPE 定义为int&__io_putchar(int&ch)函数,否则定义为int&fputc(int&ch,&FILE&*f)函数。/* USER CODE BEGIN 1 */
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker-&Libraries-&Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
Retargets the C library printf function to the USART.
* @retval None
PUTCHAR_PROTOTYPE
/* Place your implementation of fputc here */
/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
/* USER CODE END 1 */ 其中HAL_UART_Transmit(&huart1,&(uint8_t&*)&ch,&1,&0xFFFF);这个语句表示通过串口1发个一个字符。ch为字符的存储地址,0xFFFF为超时时间。在stm32f7xx_hal_uart.c文件中可以找到HAL_UART_Transmit函数。在main.c文件中添加应用函数。
/* USER CODE BEGIN 2 */
printf("\n\r UART Printf Example: retarget the C library printf function to the UART\n\r");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("\n\r welcome to www.waveshere.com !!!\n\r");
HAL_Delay(1000);
/* USER CODE END 3 */ 编译程序并下载到开发板。用USB线连接开发板到电脑,在电脑上打开串口调试助手。选择对应的串口号,设置波特率为115200。按下复位按键会接收到如图信息。打开stm32f7xx_hal_uart.h头文件,在文件后最后面可以看到有如下操作串口的函数。串口的发送接收函数:HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制。HAL_UART_Receive();串口轮询模式发送,使用超时管理机制。HAL_UART_Transmit_IT();串口中断模式发送,HAL_UART_Receive_IT();串口中断模式发送HAL_UART_Transmit_DMA();串口DMA模式发送HAL_UART_Receive_DMA();串口DMA模式发送串口相关的中断函数:HAL_UART_TxHalfCpltCallback():一半数据(half&transfer)发送完成后,通过中断处理函数调用。HAL_UART_TxCpltCallback():发送完成后,通过中断处理函数调用。HAL_UART_RxHalfCpltCallback():一半数据(half&transfer)接收完成后,通过中断处理函数调用。HAL_UART_RxCpltCallback():接收完成后,通过中断处理函数调用。HAL_UART_ErrorCallback():传输过程中出现错误时,通过中断处理函数调用。可看到串口发送和就是有三种通信模式:& & & &第一种是上面用到的轮询的模式。CPU不断查询IO设备,如设备有请求则加以处理。例如CPU不断查询串口是否传输完成,如传输超过则返回超时错误。轮询方式会占用CPU处理时间,效率较低。& & & &第二种就是中断控制方式。当I/O操作完成时,输入输出设备控制器通过中断请求线向处理器发出中断信号,处理器收到中断信号之后,转到中断处理程序,对数据传送工作进行相应的处理。& & & &第三种就是直接内存存取技术(DMA)方式。所谓直接传送,即在内存与IO设备间传送一个数据块的过程中,不需要CPU的任何中间干涉,只需要CPU在过程开始时向设备发出“传送块数据”的命令,然后通过中断来得知过程是否结束和下次操作是否准备就绪。3.中断模式。& & & & 打开STM32CubeMX重新建工程,配置和前面一样。只是这个工程中,开启了串口中断。生成报告以及代码,编译程序。在main函数前面添加两个数组变量。/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t aTxStartMessage[] = "\r\n****UART-Hyperterminal communication based on IT ****\r\nEnter 10 characters using keyboard :\r\n";
/* Buffer used for reception */
uint8_t aRxBuffer[20];
/* USER CODE END PV */ 在main函数中添加两个语句通过串口中断发送aTxStartMessage数组的数据和接收数据10个字符,保存在数组aRxBuffer中。/* USER CODE BEGIN 2 */
HAL_UART_Transmit_IT(&huart1, (uint8_t *)aTxStartMessage, sizeof(aTxStartMessage));
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);
/* USER CODE END 2 */ 在main.c文件后面添加中断接收完成回调函数。中断回调函数中将接收到的数据又通过串口发送回去。/* USER CODE BEGIN 4 */
* @brief Rx Transfer completed callbacks
* @param huart: uart handle
* @retval None
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_RxCpltCallback can be implemented in the user file
HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF);
/* USER CODE END 4 */ 编译程序并下载到开发板。用USB线连接开发板到电脑,在电脑上打开串口调试助手。选择对应的串口号,设置波特率为115200。按下复位按键会接收到aTxStartMessage数组的数据。通过串口助手发送10个字符,串口助手回显示发送的数据。注意:串口要发够10个字符串,才会触发中断。少于10个字符则不会触发中断,串口不会显示发送的数据。超过10个字符,串口只会发送10个字符回来显示。串口不定长接收程序:
刚表态过的朋友 ()
上一篇:下一篇:
我也是出现了这种情况&&这是个问题啊
CubeMX教程
本章讲解LwIP协议栈实现HTTP服务器
本章讲解USB作为主机使用的例程。
本章讲解USB作为设备使用的例程。
本章教程带领大家移植StmemWin 5.22到STM32的LDTC接口控制的RGB接口屏幕。
本章讲解微雪7inch Capacitive Touch LCD (F)屏幕的触摸控制。
本章讲解LDTC接口控制7寸
LCD屏幕显示。
本章讲解通过FMS接口控制Nand Flash K9F1G08U0E (1G Bit)
本章讲解通过FMS接口控制Nand Flash K9F1G08U0E (1G Bit)
本章介绍Quad-SPI总线,通过Quad-SPI接口控制W25Qxx芯片
上一章我们介绍了SD卡读写操作,本章讲过如何通过FATFS文件系统读写SD卡内部的文件
本章介绍SD/SDIO MMC卡主机接口(SDMMC),通过SDMMC接口读写SD卡。
本章介绍stm32F7系列芯片的随机数发生器(RNG)和循环冗余校验(CRC)。
本章介绍STM32Fxx的两种看门狗:独立看门狗(IWDG)和窗口看门狗(WWDG)
本章介绍STM32Fxx系统低功耗模式。
摘要:本章介绍实时时钟(RTC)。1.RTC简介
实时时钟(RTC)是一个独立的BCD定时器/计
本章介绍CAN总线协议。
本章介绍如何用程序通过SPI控制w25Q125fv。
本章介绍SPI总线。以及介绍串行flash芯片W25Q128FV
本章介绍I2C总线。通过I2C控制AT24Cxx芯片。
本章通过两个例程介绍STM32的数模转换器(DAC),第一个通过软件控制ADC单次转换输出
本章通过两个例程介绍STM32的模数转换器(ADC),第一个通过ADC采集内部温度传感器通
上一章讲解了串口的轮询和中断模式,这一章介绍一下通过DMA模式控制串口传输。
本章以串口为例讲解,HAL 库轮询,中断,DMA 三种编程模型。
上一章我们讲解了定时器的基本应用,以及定时器中断。这一章我们讲解通过定时器控制管
stm32的定时器功能非常强大,包括基本定时器,通用定时器以及高级定时器。 本章介绍定
本章讲解STM32的外部中断已经中断的运行流程。
本章讲解stm32的GPIO使用,通过按键控制LED灯亮灭
本章通过如何点亮一个LED灯讲解STM32CubeMX软件的使用以及STM32最新的HAL固件库
Powered bySTM32中DMA有什么好处_百度知道
STM32中DMA有什么好处
!例如串口发送,没用DMA是也照样可以发送!!
我有更好的答案
用和不用当然都可以发送。不用DMA发送是需要单片机实时参与,由单片机一个一个地发送数据并进行监控。但是如果用DMA,设置了起始地址,数据大小等参数后,就直接由专门的一个DMA模块进行数据发送,发送过程中单片机无需参与。发送完后会产生中断告知单片机。由此可知用DMA可以节省单片机资源,让单片可以在同一时间里干更多事。
采纳率:33%
不占用cpu 提高数据吞吐量
你把AD的采样时间搞常一些,ADC_SampleTime大些;如果还不行估计是AD供电的VDDA和VSSA不够稳定,你测下,在采样的同时,VDDA和VSSA两端的电压是否变化,如果变化比较大,你就需要从新设计下这个电源了
..
1条折叠回答
为您推荐:
其他类似问题
您可能关注的内容
stm32的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。STM32 DMA使用详解
单片机&嵌入式
单片机应用
嵌入式操作系统
学习工具&教程
学习和开发单片机的必备工具
(有问必答)
(带你轻松入门)
电子元件&电路模块
当前位置: >>
>> 浏览文章
STM32 DMA使用详解
DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧。下面用问答的形式表达我的思路。
DMA有什么用?
&&&&&& 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。
有多少个DMA资源?
&&&&&& 有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。
数据从什么地方送到什么地方?
&&&&&& 外设到SRAM(I2C/UART等获取数据并送入SRAM);
&&&&&& SRAM的两个区域之间;
&&&&&& 外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比);
&&&&&& SRAM到外设(SRAM中预先保存的数据送入DAC产生各种波形);
&&&&&& &&还有一些目前还搞不清楚的。
DMA可以传递多少数据?
&&&&&& 传统的DMA的概念是用于大批量数据的传输,但是我理解,在STM32中,它的概念被扩展了,也许更多的时候快速是其应用的重点。数据可以从1~65535个。
直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些电脑内部的硬体子系统(电脑外设),可以独立地直接读写系统存储器,而不需绕道 CPU。在同等程度的CPU负担下,DMA是一种快速的数据传送方式。它允许不同速度的硬件装置来沟通,而不需要依于 CPU的大量中断请求。【摘自Wikipedia】
现在越来越多的单片机采用DMA技术,提供外设和存储器之间或者存储器之间的高速数据传输。当 CPU 初始化这个传输动作,传输动作本身是由&DMA 控制器&来实行和完成。STM32就有一个DMA控制器,它有7个通道,每个通道专门用来管理一个或多个外设对存储器访问的请求,还有一个仲裁器来协调各个DMA请求的优先权。
DMA 控制器和Cortex-M3核共享系统数据总线执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求可能会停止 CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。
在发生一个事件后,外设发送一个请求信号到DMA控制器。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问外设的时候,DMA控制器立即发送给外设一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果发生更多的请求时,外设可以启动下次处理。
总之,每个DMA传送由3个操作组成:
1. 从外设数据寄存器或者从DMA_CMARx寄存器指定地址的存储器单元执行加载操作。
2. 存数据到外设数据寄存器或者存数据到DMA_CMARx寄存器指定地址的存储器单元。
3. 执行一次DMA_CNDTRx寄存器的递减操作。该寄存器包含未完成的操作数目。
仲裁器根据通道请求的优先级来启动外设/存储器的访问。优先级分为两个等级:软件(4个等级:最高、高、中等、低)、硬件(有较低编号的通道比拥有较高编号的通道有较高的优先权)。
可以在DMA传输过半、传输完成和传输错误时产生中断。
STM32中DMA的不同中断(传输完成、半传输、传输完成)通过&线或&方式连接至NVIC,需要在中断例程中进行判断。
进行DMA配置前,不要忘了在RCC设置中使能DMA时钟。STM32的DMA控制器挂在AHB总线上。
DMA总共有7个通道,各个通道的DMA映射关系如下:
外设的事件连接至相应DMA通道,每个通道均可以通过软件触发实现存储器内部的DMA数据传输(M2M模式)
Tips:库2.0中函数RCC_AHBPeriphClockCmd的参数由&RCC_AHBPeriph_DMA&改成&RCC_AHBPeriph_DMA1&(如果是DMA1控制器的话)。
DMA的传输标志位(CHTIFx、CTCIFx、CGIFx)由硬件设置为&1&,但需要软件清零,在中断服务程序中清除。当CGIFx(全局中断标志位)清零后,CHTIFx 和 CTCIFx均清零。
过程:怎样启用DMA?首先,众所周知的是初始化,任何设备启用前都要对其进行初始化,要对模块初始化,还要先了解该模块相应的结构及其函数,以便正确的设置;由于DMA较为复杂,我就只谈谈DMA的基本结构和和常用函数,这些都是ST公司提供在库函数中的。
1、 下面代码是一个标准DMA设置,当然实际应用中可根据实际情况进行裁减:
DMA_DeInit(DMA_Channel1);
上面这句是给DMA配置通道,根据ST提供的资料,STM3210Fx中DMA包含7个通道(CH1~CH7),也就是说可以为外设或memory提供7座&桥梁&(请允许我使用桥梁一词,我觉得更容易理解,哈哈,别&拍砖&呀!);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_A
上面语句中的DMA_InitStructure是一个DMA结构体,在库中有声明了,当然使用时就要先定义 了;DMA_PeripheralBaseAddr是该结构体中一个数据成员,给DMA一个起始地址,好比是一个buffer起始地址,数据流程是:外设 寄存器& DMA_PeripheralBaseAdd&memory中变量空间(或flash中数据空间等),ADC1_DR_Address是我定义的一个地址 变量;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedV
上面这句很显然是DMA要连接在Memory中变量的地址,ADC_ConvertedValue是我自己在memory中定义的一个变量;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
上面的这句是设置DMA的传输方向,就如前面我所说的,DMA可以双向传输,也可以单向传输,这里设置的是单向传输,如果需要双向传输:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。
DMA_InitStructure.DMA_BufferSize = 2;
上面的这句是设置DMA在传输时缓冲区的长度,前面有定义过了buffer的起始地址:ADC1_DR_Address ,为了安全性和可靠性,一般需要给buffer定义一个储存片区,这个参数的单位有三种类型:Byte、HalfWord、word,我设置的2个 half-word(见下面的设置);32位的MCU中1个half-word占16 bits。
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
上面的这句是设置DMA的外设递增模式,如果DMA选用的通道(CHx)有多个外设连接,需要使用外设递增模式:DMA_PeripheralInc_E我的例子里DMA只与ADC1建立了联系,所以选用DMA_PeripheralInc_Disable
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
上面的这句是设置DMA的内存递增模式,DMA访问多个内存参数时,需要使用DMA_MemoryInc_Enable,当DMA只访问一个内存参数时,可设置成:DMA_MemoryInc_Disable。
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW
上面的这句是设置DMA在访问时每次操作的数据长度。有三种数据长度类型,前面已经讲过了,这里不在叙述。
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW
与上面雷同。在此不再说明。
DMA_InitStructure.DMA_Mode = DMA_Mode_C
上面的这句是设置DMA的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_Normal
DMA_InitStructure.DMA_Priority = DMA_Priority_H
上面的这句是设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.
DMA_InitStructure.DMA_M2M = DMA_M2M_D
上面的这句是设置DMA的2个memory中的变量互相访问的
DMA_Init(DMA_Channel1,&DMA_InitStructure);
前面那些都是对DMA结构体成员的设置,在次再统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。
DMA_Cmd(DMA_Channel1,ENABLE);
哈哈哈!这一句我想我就不罗嗦了,大家一看就明白。
至此,整个DMA总算设置好了,但是,DMA通道又是怎样与外设联系在一起的呢?哈哈,这也是我当初最想知道的一个事情,别急!容我想喝口茶~~~~~~哈哈哈!
要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有 一个xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用ADC_DMACmd(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。
一个简单的例子 transfer& a word data buffer from FLASH memory to embedded SRAM memory.
在V3.1.2库的位置
STM32F10x_StdPeriph_Lib_V3.1.2\Project\STM32F10x_StdPeriph_Examples\DMA\FLASH_RAM
DMA_DeInit(DMA1_Channel6);
& //peripheral base address
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_B
& //memory base address&&&
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DST_B
& //数据传输方向&&& Peripheral is source &&& &&& &&& &&
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//缓冲区大小 Number of data to be transferred (0 up to 65535).数据传输数目&&& &
DMA_InitStructure.DMA_BufferSize = BufferS
&& // the Peripheral address register is incremented&&& &&&
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_E
& //the memory address register is incremented
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
//the Peripheral data width&&& &&&
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_W&
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_W
DMA_InitStructure.DMA_Mode = DMA_Mode_N
DMA_InitStructure.DMA_Priority = DMA_Priority_H
//the DMAy Channelx will be used in memory-to-memory transfer
//DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。
DMA_InitStructure.DMA_M2M = DMA_M2M_E&&&
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE);
=======================================================================
外设的DMA请求映像
要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有 一个
xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用 ADC_DMACmd
(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_A
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_V&&&
//u16& AD_Value[2];&& 不加&应该也可以& 数组名 代表地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2;&&& & //############## 改了
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E& //##############&&& &改了
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW
DMA_InitStructure.DMA_Mode = DMA_Mode_C
DMA_InitStructure.DMA_Priority = DMA_Priority_H
DMA_InitStructure.DMA_M2M = DMA_M2M_D
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_InitStructure.ADC_Mode = ADC_Mode_I
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_N
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R
ADC_InitStructure.ADC_NbrOfChannel = 2;&&& & //##############&&& &改了
ADC_Init(ADC1, &ADC_InitStructure);
//内部温度传感器& 添加这一句&
ADC_TempSensorVrefintCmd(ENABLE);
//##############&&& &改了
//################ Channel 10(电位器)
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);
//###### 内部温度传感器& Channel 16 ###################
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_55Cycles5);
& 使能ADC1的DMA请求映像
& ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
&& //使用之前一定要校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
【】【】【】【】
上一篇:下一篇:
CopyRight @
单片机教程网 51hei.com , All Rights Reserved21ic官方微信-->
ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU
关于串口DMA多次发送的问题求教
中级技术员, 积分 189, 距离下一级还需 111 积分
中级技术员, 积分 189, 距离下一级还需 111 积分
中级技术员, 积分 189, 距离下一级还需 111 积分
中级技术员, 积分 189, 距离下一级还需 111 积分
使用STM32串口DMA多次发送数据,当我第一次发送第一组串口数据时,如果发送未完成,又再次开启DMA发送第二组数据,此时会出现什么情况,求助?我测试的结果是第一组的数据发送一半就不在发送了,如果想用串口DMA发送多组不同的数据需要怎么做?必须等待第一次数据发送完成了才能发送第二组数据吗?
高级工程师, 积分 6576, 距离下一级还需 1424 积分
高级工程师, 积分 6576, 距离下一级还需 1424 积分
高级工程师, 积分 6576, 距离下一级还需 1424 积分
高级工程师, 积分 6576, 距离下一级还需 1424 积分
不是排队发送吗,怎么开启了还没发送完,再开。。难道你关闭了?
高级工程师, 积分 5374, 距离下一级还需 2626 积分
高级工程师, 积分 5374, 距离下一级还需 2626 积分
高级工程师, 积分 5374, 距离下一级还需 2626 积分
高级工程师, 积分 5374, 距离下一级还需 2626 积分
你试试会有什么后果,你想让前面的数据丢失?
资深技术员, 积分 495, 距离下一级还需 5 积分
资深技术员, 积分 495, 距离下一级还需 5 积分
资深技术员, 积分 495, 距离下一级还需 5 积分
资深技术员, 积分 495, 距离下一级还需 5 积分
如果可以这么操作,那么第一次的或许会丢失,或许会等第一次发送完才能装填第二次的内容,不过需要试试看
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖21ic官方微信 -->
kinetis的UART串口(DMA模式)
前面的例子中,串口的收发采用中断模式,虽然在一定程度上解放了CPU,但每个字节都要中断一次,在115200波特率下,约8.7uS就要中断一次,CPU仍然很累。直接存储器访问(DMA)方式可以进一步解放CPU,本例采用DAM方式实现每次100字节数据发送与接收。DMA处理发送是最有效的方法,因为程序明确知道有多少数据要发送,直接将数据存放数组的首地址和长度交给DMA即可由DAM连续发完这些数据,如果需要可以设置让DMA发完后产生中断。对于接收,用DMA的问题在于不知道接收多少个数,无法在收到数据后通知CPU。一般采用这样的做法:用DMA收下所有数据放到环形缓冲区里,但不产生中断。这样虽不能通知CPU何时收到了数据,但确可以收下所有数据。每隔一段时间CPU查询该缓冲区,发现有数据就处理。这样虽响应的及时性差些,但一般场合都是可以接受的。
要使用UART的DMA方式,需做下面3件事情:
1、UART5_C2寄存器的发送、接收中断使能,接收使能。
2、UART5_C5寄存器的DMA收和DMA发使能。
3、设置DMAMUX,将相应请求源(中断源)映射到相应DMA通道,并使能相应通道。请求源编号见表3-24。
4、设置DMA控制器,主要是TCD的设置,包括源、目的地址、传输长度、地址递增等。
5、如果需要DMA传输完成产生中断,则要NVICISER寄存器使能DMA对应中断,中断向量表填入中断服务程序入口。
6、想发数据的时候设置UART5_C2的发送使能,会立即因发送数据寄存器空而产生DMA请求。
示例代码用通道0处理发送,完成后产生中断,中断服务程序会再启动发送;通道1处理数据接收,不产生中断。因使用了回环,发送的数据都被自身接收到了,可以看出发送、接收的过程没有CPU的干预,发送完100字节(实际可以很长)才产生一次中断,在此期间MCU可以做各种事情。
下面是完整代码:
* main implementation: use this 'C' sample to create your own application
#define GPIO_PIN_MASK 0x3C000000
#define GPIO_PIN(x) ((1&
#include &derivative.h& /* include peripheral declarations */
struct _uart_buf
char buf[100];
} uart_tx,uart_
void MCG_Init()
SIM_SCGC6 |= 0x; //SIM_SCGC6: RTC=1
if ((RTC_CR & RTC_CR_OSCE_MASK) == 0u)//Only if the OSCILLATOR is not already enabled
RTC_CR &= ~0x3C00; //RTC_CR: SC2P=0,SC4P=0,SC8P=0,SC16P=0
RTC_CR |= 0x0100; //RTC_CR: OSCE=1
RTC_CR &= ~0x0200; //RTC_CR: CLKO=0
/* System clock initialization */
/* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=1,OUTDIV3=1,OUTDIV4=3,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
SIM_CLKDIV1 = (uint32_t)0xUL; /* Update system prescalers */
/* SIM_SOPT2: PLLFLLSEL=0 */
SIM_SOPT2 &= (uint32_t)~0xUL; /* Select FLL as a clock source for various peripherals */
/* SIM_SOPT1: OSC32KSEL=0 */
SIM_SOPT1 &= (uint32_t)~0xUL; /* System oscillator drives 32 kHz clock for various peripherals */
/* Switch to FEE Mode */
SIM_SOPT2 |= (uint32_t)0x01UL;// SIM_SOPT2: MCGCLKSEL=1 0-System oscillator (OSCCLK), 1-32 kHz RTC oscillator
MCG_C2 = (uint8_t)0x00U; // MCG_C2: ??=0,??=0,RANGE=0,HGO=0,EREFS=0,LP=0,IRCS=0
MCG_C1 = (uint8_t)0x02U; // MCG_C1: CLKS=0,FRDIV=0,IREFS=0,IRCLKEN=1,IREFSTEN=0
MCG_C4 |= 0xE0; //MCG_C4: DMX32=1,DRST_DRS=3
MCG_C5 = 0x00; // MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV=0
MCG_C6 = 0x00;// MCG_C6: LOLIE=0,PLLS=0,CME=0,VDIV=0
while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) //Check that the source of the FLL reference clock is the external reference clock.
while((MCG_S & 0x0CU) != 0x00U) // Wait until output of the FLL is selected
void UART_Init()
// SIM_SCGC1: UART5=1
SIM_SCGC1 |= (uint32_t)0x0800UL;
// SIM_SCGC5: PORTE=1
SIM_SCGC5 |= (uint32_t)0x2000UL;
// PORTE_PCR9: ISF=0,MUX=3 做UART
PORTE_PCR9 = (uint32_t)((PORTE_PCR9 & (uint32_t)~0xUL) | (uint32_t)0x0300UL);
// PORTE_PCR8: ISF=0,MUX=3 做UART
PORTE_PCR8 = (uint32_t)((PORTE_PCR8 & (uint32_t)~0xUL) | (uint32_t)0x0300UL);
UART5_C4 = 0x14; //波特率微调
UART5_BDH = (312&&8) & 0x1F;//设波特率9600bps
UART5_BDL = 312&0xFF;
UART5_C2 = (1&&7)|(1&&5)|(1&&2);//允许收、发中断,允许接收
UART5_C5 = (1&&7)|(1&&5);//允许收、发中断产生DMA请求
UART5_C1 |= 1&&7;//使用回环模式
void dma0_init()
SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
DMAMUX_CHCFG0 = (1&&7) | 13;
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;
DMA_CR = 0;
DMA_TCD0_SADDR = (unsigned long)&uart_tx.buf[0];//DMA源地址
DMA_TCD0_DADDR = (unsigned long)&UART5_D;//DMA目的地址
DMA_TCD0_NBYTES_MLNO = 1;
DMA_TCD0_ATTR = 0;//8位传送,关闭模特性
在今年的 MWC 上我们已经领略过天语 Treasure V8 的风采,现在他们又为我们带来了这款 T660。它是天语旗下第一款中国移动版智能手机,支持 TD-SCDMA 网络。硬件方面采用了 4 寸 IPS 屏幕、500 万像素摄像头和一......关键字:
从流传的PPT上可以看出,即便没有全国层面上的关闭,部分省市也会分批关停。......关键字:
虽然中国政府还没有拍卖 FDD-LTE 的时间表,但华为与中兴两家厂商已经陆续在进行有关的研究,为未来做好准备。这次中兴率先拿出同时支援 FDD-LTE、TDD-LTE 及 TD-SCDMA 的 USB 数据卡及行动网络分享器 - MF8......关键字:
&虽然目前3G依旧是我们的工作重点,但是着眼于长远,我们将TD-LTE视为战略重点。&近日,一位地方移动人士向记者表示。据调查,上述观点在地方移动具有一定的代表性,&TD-SCDMA产业链没有完全成熟,......关键字:
上周五,Linux 之父 Linus Torvalds 在内核邮件列表上用很犀利的言辞抨击了 Google Pixel 安全团队的开发者 Kees Cook,引起了大家广泛地讨论。......关键字:
作为电子研发的老兵,面对各种纷繁复杂的问题,加班加点是家常便饭,绞尽脑汁甚至抓狂是常态。经常发现当项目进展到你想砸掉设备的时候,再坚持一步你就成功了。但是有一个项目却因为坚持,到现在每每想起我都心痛郁闷不已。......关键字:
众所周知,一般情况下,学生逃课最严重的后果就是被叫家长或者被学校开除。但是,逃课被枪击的好像还从未听闻过。......关键字:
随着科技史无前例的飞速发展,很难想像二十年后各行各业的工作会变成什么样子。但是加拿大奖学金计划(CST),一个致力于帮助加拿大孩子大专教育的非盈利,想要搞清楚这一点。在富有远见的战略家们的帮助下,CST预测到2030年可能会普遍存在的工作。......关键字:
我 要 评 论
大家都爱看
我们有能力创造一些能保持前代性能并且更好更小的电子设备,例如今天的可穿戴设备、智能手机或平板电脑,这是由于很多因素超过摩尔定律而快速发展,从而能够从底层的嵌入组件发展到今天把它们封…
自适应和智能计算的全球领先企业赛灵思公司(Xilinx, Inc.,(NASDAQ:XLNX)),近日宣布推出一款超越FPGA功能的突破性新型产品,名为ACAP(Adaptive Compute Acceleration Platform,自适应计算加速…
先进嵌入式系统解决方案的领导者赛普拉斯(纳斯达克代码:CY)近日宣布其Wi-Fi®和蓝牙®combo解决方案为全新的树莓派 3 B+(Raspberry Pi 3Model B+)IoT单板计算机提供强大稳定的无线连接…
随着云服务器、云计算的发展,大家对硬件加速的需求越来越多,但是随着设备功耗的上升、性能需求越来越高,常规加速设备以及开始不能满足需求,因此FPGA逐渐在硬件加速中找到了自己的位置,而艾…
白宫周一(3月12日)晚发出声明,川普(特朗普)总统出于“国家安全”考量、禁止新加坡博通公司(Broadcom)收购美国高通公司(Qualcomm)。
业界早知道
04-1004-1004-1004-1004-1004-09
精读涨姿势
03-2309-0810-1602-1706-0806-30

我要回帖

更多关于 c 串口发送数据 的文章

 

随机推荐