双缓冲

利用DMA双缓冲或半完成中断实现串口不定长数据的接收

最后都变了- 提交于 2020-02-26 18:44:30
在《 HAL版本DMA循环模式串口数据收发 》中介绍了利用DMA循环模式进行串口数据的收发,STM32F4xx的DMA还提供了双缓冲的功能,采用双缓冲模式,可以在一个DMA完成接收后,对其缓冲区内数据进行处理的过程中,将此时接收到的数据放入第二个DMA缓冲区。双缓冲模式尤其对高速数据接收有着明显的优势,本文以上述循环接收方案为基础,提供实现双缓冲接收数据的实现方式。 首先,从寄存器的角度讲,要实现双缓冲,需要将CR寄存器的DBM位置1,将该位置1后,硬件会强制使用循环模式,当一个缓冲满后,会自动交换缓冲区的地址。但我们采用HAL库版本的程序时,不太需要关注这些,但是值得注意的是,HAL库的stm32f4xx_hal_uart.c中并没有提供实现双缓冲的接口,因此需要我们对HAL库的程序进行一些改写: HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { /*省略库中起始部分的程序*/ /* Set the DMA abort callback */ huart->hdmarx->XferAbortCallback = NULL; /* Enable the DMA stream */ //HAL_DMA_Start_IT(huart-

双缓冲绘图练习(20200217)

早过忘川 提交于 2020-02-16 16:50:58
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { m_canvasPix = QPixmap(this->width(),this->height()); m_canvasPix.fill(Qt::white); m_bIsDrawing = false; } Widget::~Widget() { } void Widget::paintEvent(QPaintEvent *event) { int x,y,w,h; x = m_lastPt.x(); y = m_lastPt.y(); w = m_endPt.x() - x; h = m_endPt.y() - y; QPainter painter(this); //! 如果正在绘图,就在辅助画布上绘制 if(m_bIsDrawing) { //! 将以前pix中的内容复制到tempPix中,保证以前的内容不消失 m_tmpCanvasPix = m_canvasPix; QPainter pp(&m_tmpCanvasPix); pp.drawRect(x,y,w,h); painter.drawPixmap(0, 0, m_tmpCanvasPix); } else { QPainter pp(&m_canvasPix); pp

双缓冲 图像显示

时光总嘲笑我的痴心妄想 提交于 2020-02-01 00:32:04
原文出自: http://blog.csdn.net/xiaohui_hubei/article/details/16319249 一、双缓冲作用 双缓冲甚至是多缓冲,在许多情况下都很有用。一般需要使用双缓冲区的地方都是由于“生产者”和“消费者”供需不一致所造成的。这样的情况在很多地方后可能会发生,使用多缓冲可以很好的解决。我举几个常见的例子: 例 1 . 在网络传输过程中数据的接收,有时可能数据来的太快来不及接收导致数据丢失。这是由于“发送者”和“接收者”速度不一致所致,在他们之间安排一个或多个缓冲区来存放来不及接收的数据,让速度较慢的“接收者”可以慢慢地取完数据不至于丢失。 例2. 再如,计算机中的三级缓存结构:外存(硬盘)、内存、高速缓存(介于CPU和内存之间,可能由多级)。从左到右他们的存储容量不断减小,但速度不断提升,当然价格也是越来越贵。作为“生产者”的 CPU 处理速度很快,而内存存取速度相对CPU较慢,如果直接在内存中存取数据,他们的速度不一致会导致 CPU 能力下降。因此在他们之间又增加的高速缓存来作为缓冲区平衡二者速度上的差异。 例3 . 在图形图像显示过程中,计算机从显示缓冲区取数据然后显示,很多图形的操作都很复杂需要大量的计算,很难访问一次显示缓冲区就能写入待显示的完整图形数据,通常需要多次访问显示缓冲区,每次访问时写入最新计算的图形数据

C# GDI+双缓冲技术

不羁的心 提交于 2020-01-25 01:22:56
GDI+的双缓冲问题 我想有很多搞图形方面的朋友都会用到双缓冲技术的时候,而且有的时候她的确是个头疼的问题。最近我也要用双缓冲技术,程序怎么调试都不合适,当要对图形进行移动时,总是会出现闪烁抖动。在网上找了些资料,说得都不清不楚的,折腾了一晚上也没弄出来。第二天觉定自己研究一下。现在把自己的一些想法拿出来跟大家分享一下。 双缓冲的基本原理:(转) 一直以来的误区:.net1.1 和 .net 2.0 在处理控件双缓冲上是有区别的。 .net 1.1中,使用:this.SetStyle(ControlStyles.DoubleBuffer, true); .net 2.0中,使用:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 怪不说老是提示参数无效,一直也不知道是这个问题,呵呵 要知道,图元无闪烁的实现和图元的绘制方法没有多少关系,只是绘制方法可以控制图元的刷新区域,使双缓冲性能更优! 导致画面闪烁的关键原因分析: 一、绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面重新刷新一次以维持窗口正常显示。刷新过程中会导致所有图元重新绘制,而各个图元的重绘操作并不会导致Paint事件发生,因此窗口的每一次刷新只会调用Paint事件一次

双缓冲技术绘图原理及简单的VC实现

老子叫甜甜 提交于 2020-01-24 04:13:23
为了增加自己对双缓冲绘图技术的理解,简要做个笔记(以Windows为例): 1、Windows 绘图原理 我们在 Windows 环境下看到各种元素,如菜单、按钮、窗口、图像,从根本上说,都是“画”出来的。这时的屏幕,就相当于一块黑板,而 Windows 下的各种 GDI 要素,如画笔、画刷等,就相当于彩色粉笔了。我们在黑板上手工画图时,是一笔一划的,电脑亦然。只不过电脑的速度比手工快的太多,所以在我们看起来好像所有的图形文字都是同时出现的。 2、普通绘图方式的局限 上述绘图方式我们暂且称之为普通绘图方式吧。虽然这种方式能满足相当一部分的绘图需要,但是当要绘制的对象太复杂,尤其是含有位图时,电脑便力不从心了。这时的画面会显示的很慢,对于运动的画面,会给人“卡”住了的感觉,总之一个字:不爽。 3、解决之道:双缓冲 双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板。首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。采取这种方法可以提高绘图速度,极大的改善绘图效果。下面是原理图: 实现过程如下: 1、在内存中创建与画布一致的缓冲区 2、在缓冲区画图 3、将缓冲区位图拷贝到当前画布上 4、释放内存缓冲区 相关的VC函数: 1)、为屏幕 DC 创建兼容的内存DC

Android 绘图时实现双缓冲

我与影子孤独终老i 提交于 2020-01-19 07:51:00
一、双缓冲技术原理:   在内存中创建一片内存区域,把将要绘制的图片预先绘制到内存中,在绘制显示的时候直接获取缓冲区的图片进行绘制。更具体一点来说: 先通过setBitmap方法将要绘制的所有的图形绘制到一个Bitmap上也就是先在内存空间完成,然后再来调用drawBitmap方法绘制出这个Bitmap,显示在屏幕上。 二、双缓冲技术出现的缘由   当一个动画争先显示时,程序又在改变它,前面的画面还没显示完,程序又要求重新绘制,这样屏幕就会不停闪烁。为了避免闪烁,使绘制的内容有一个平滑的过度,所以就出现了双缓冲技术——》将要处理的图片都放在内存中处理好后,再将其一次性显示到屏幕上。这样出来的就是完整的图像,不会出现闪烁现象。 二、双缓冲技术的优缺点   优点:     1.绘制过程中一般不会出现闪烁现象,能使动画平滑过度。     2.高效,将图像一次性绘制到屏幕上比一次一次的绘制要高效的多。   缺点:     当图片过大时会严重的消耗内存 三、实现双缓冲的步骤   1.创建一片内存区域用于存放目标Bitmap        // 创建一个200*200的缓冲区 bitmapBuffer = Bitmap.createBitmap(200, 200, Config.ARGB_8888);   2.设置目标内容绘制到缓冲区     // 设置将目标内容绘制在“缓冲区” canvas

win32下的双缓冲绘图技术

穿精又带淫゛_ 提交于 2020-01-16 10:14:59
一:双缓冲原理   为了解决窗口刷新频率过快所带来的闪烁问题,利用双缓冲技术进行绘图。所谓双缓冲技术,就是将资源加载到内存,然后复制内存数据到设备DC(这个比较快),避免了直接在设备DC上绘图(这个比较慢)。打个简单的比方:有个画家在街边办了一个即时画展,在同一块画布上根据观众的要求画不同的图像,每当有一位观众制定要看什么画时,画家先把之前画布上的东西全部擦干净,再重新绘画。显然有一些经典的画像是大家都想看的,按照以前的老办法,画家每次都要重新画这幅图像,但这种擦了画,画了擦的方式很费时。所以画家想了一个办法,把这些经典画像预先用一块或几块画布画下来,等有人需要看时,把这些预备好的画布贴在现有画布的前面,这样就能满足观众的实时性要求。那么这些事先预备好的画布就相当于内存DC,把资源放在内存DC里,等到要刷新显示时,将内存DC上的东西“贴”到当前窗口DC上,就可以减少延时带来的闪烁问题,这就是双缓冲的原理。 详细介绍见后面的几片博文。下面举两个例子: 二: 例子 例子一:加载位图 代码: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case

Java中用双缓冲技术消除闪烁

蓝咒 提交于 2020-01-15 06:32:29
在 Java 编写具有连贯变化的窗口程序时,通常的办法是在子类中覆盖父类的 paint(Graphics) 方法,在方法中使用 GUI 函数实现窗口重绘的过程。连贯变换的窗口会不断地调用 update(Graphics) 函数,该函数自动的调用 paint(Graphics) 函数。这样就会出现闪烁的情况。 为了解决这一问题,可以应用双缓冲技术。可以通过截取上述过程,覆盖 update(Graphics) 函数,在内存中创建一个与窗口大小相同的图形,并获得该图形的图形上下文 (Graphics) ,再将图片的图形上下文作为参数调用 paint(Graphics) 函数( paint(Graphics) 中的 GUI 函数会在图片上画图),再在 update(Graphics) 函数调用 drawImage 函数将创建的图形直接画在窗口上。 Image ImageBuffer = null; Graphics GraImage = null; public void update(Graphics g){ //覆盖update方法,截取默认的调用过程 ImageBuffer = createImage(this.getWidth(), this.getHeight()); //创建图形缓冲区 GraImage = ImageBuffer.getGraphics(); /

C#双缓冲绘图

自作多情 提交于 2020-01-15 04:25:28
一、 画面闪烁 问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1 绘制窗口由于大小位置状态改变进行重绘操作时   绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面重新刷新一次以维持窗口正常显示。刷新过程中会导致所有图元重新绘制, 而各个图元的重绘操作并不会导致Paint事件发生,因此窗口的每一次刷新只会调用Paint事件一次。 窗口刷新一次的过程中,每一个图元的重绘都会立即显示到窗口, 因此整个窗口中,只要是图元所在的位置,都在刷新,而刷新的时间是有差别的,闪烁现象自然会出现 。   所以说,此时导致窗口闪烁现象的关键因素并不在于Paint事件调用的次数多少,而在于各个图元的重绘。   根据以上分析可知,当图数目不多时,窗口刷新的位置也不多,窗口闪烁效果并不严重;当图元数目较多时,绘图窗口进行重绘的图元数量增加,绘图窗口每一次刷新 都会导致较多的图元重新绘制,窗口的较多位置都在刷新,闪烁现象自然就会越来越严重。特别是 图元比较大绘制时间比较长时 ,闪烁问题会更加严重,因为时间延迟会更长。 解决上述问题的关键在于 : 窗口刷新一次的过程中,让所有图元同时显示到窗口 。 2、 进行鼠标跟踪绘制操作或者对图元进行变形操作时    当进行鼠标跟踪绘制操作或者对图元进行变形操作时,Paint事件会频繁发生,这会使窗口的刷新次数大大增加

MFC双缓冲解决闪烁问题

时光毁灭记忆、已成空白 提交于 2020-01-15 03:27:10
  最近在写一个图像编辑软件,环境是MFC,但是MFC的视图刷新机制使得图像闪烁得非常厉害(图像缩放时尤其明显),在网上查了一些资料,最好的方法是用双缓冲的方式显示,这里总结一下。   双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板。首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。采取这种方法可以提高绘图速度,极大的改善绘图效果。 主要实现代码如下: 1 CDC MemDC; // 首先定义一个内存显示设备对象 2 CBitmap MemBitmap; // 定义一个位图对象 3 MemDC.CreateCompatibleDC(NULL); // 创建兼容设备dc 4 MemBitmap.CreateCompatibleBitmap(pDC,W,H); 5 CBitmap * pOldBit = MemDC.SelectObject( & MemBitmap); 6 MemDC.FillSolidRect( 0 , 0 ,W,H,RGB( 255 , 255 , 255 )); // 填充初始颜色 7 cimg.DrawToHDC(MemDC.GetSafeHdc(),CRect( 0 , 0 ,W,H)); // 绘图到内存显示设备 8 9 pDC ->