stm32串口UART接收图片tft-lcd显示

stm32串口UART接收图片tft-lcd显示
介绍

使用STM32F103开发板。
屏幕为tft-lcd2.4寸:240×320。
软件:
图片二进制生成软件:Image2Lcd.exe
串口工具

一、视频展示

stm32串口UART接收图片tft-lcd显示

二、简要分析
  • 使用Image2Lcd.exe软件生成的图片格式如下:
    在这里插入图片描述

在这里插入图片描述

  • 可以看到数据的前8个字节为图像头数据。

  • 第三和第四个字节组合起来为图像宽低位在前0x00F0 = 240

  • 第五和第六个字节组合起来为图像低位在前0x0140 = 320

  • 所以在代码中我们只需要先获取到图片的头数据,获取传输图片的关键信息,就可以很容易的判断传输的数据了。

三、实现过程
  • 在串口中断中使用环形缓冲区接收数据。
void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
    {
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		ringBufferWrite(&Res,1);  		 
    } 										 
} 
  • 接下来便在主程序中处理接收到的数据。(这里默认所有图片都是从(0,0)开始绘制)
int main(void)
{	 		    	 
	uint8_t buf[8];						//缓冲数组接收串口数据
	uint16_t j,w,h;						//图片参数
	uint16_t getPictureDataFlag = 0;	//是否获取到图片参数标志
	uint16_t sx = 0;					//光标位置
	 
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
    ringBufferInit();
	...
    ... //一些参数化函数
	... 
	 while(1)
	 {
		 if(getPictureDataFlag == 0)
		{
			while(ringBufferGetValidLen() < 8);	//只有在串口接收到超过8个字节数据后执行
			ringBufferRead(buf,8);				//读取8个字节图片头数据
			w = ((uint16_t)buf[3]<<8) |buf[2];
			h = ((uint16_t)buf[5]<<8) |buf[4];
			getPictureDataFlag = 1;				//将标志设置为真
		}
		else
		{
										//s\设置光标位置
			LCD_SetCursor(0,0+sx);
			LCD_WriteRAM_Prepare();     //开始写入GRAM
			for(j=0;j<w;j++)
			{
				while(ringBufferGetValidLen() < 2);
				ringBufferRead(buf,2);
				LCD->LCD_RAM = (uint16_t)buf[1]<<8 | buf[0];	//写入数据
			}
			if(sx == h - 1)		//最后一行写完表示整张图片写入完成
			{
				//初始化数据
				getPictureDataFlag = 0;
				sx = 0;
			}	
			else
				sx++;		//写入下一行
		}	 	 
	 }
}
结尾

代码中使用到的LCD相关函数为正点原子官方例程中的函数原型。

在需求使用flash存储大容量图片数据时,此方法也可以用在将图片数据写入stm32外部flash中,避免在程序中重复烧录。

补充
  • 环形缓冲区代码ring_buffer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "ring_buffer.h"
#define BUFF_SIZE               (200)
static volatile uint32_t valid_len = 0;
static volatile uint8_t *pHead = (volatile uint8_t*)0x68000000;
static volatile uint8_t *pEnd = NULL;
static volatile uint8_t *pValid = NULL;
static volatile uint8_t *pValidEnd = NULL;
void ringBufferInit(void)
{
	pHead = (uint8_t*)malloc(BUFF_SIZE);
	if(pHead==NULL)
    {
        printf("malloc buffer fail\r\n");
	}
	pValid = pValidEnd = pHead;
	pEnd = pHead + BUFF_SIZE;
	valid_len = 0;
}
int ringBufferWrite(uint8_t *buffer,uint32_t len)
{
	int len1 = 0, len2 = 0;
    int move_len = 0;
	if(len > BUFF_SIZE)
    {
        return -2;
    }
    if(pHead==NULL)
    {
		return -1;
    }
	assert(buffer);
	
	if((pValidEnd + len) > pEnd)
	{
		len1 = pEnd - pValidEnd;
		len2 = len - len1;
		memcpy((uint8_t *)pValidEnd,buffer,len1);
		memcpy((uint8_t *)pHead,buffer + len1,len2);
		pValidEnd = pHead + len2;
	}
	else
	{
		memcpy((uint8_t *)pValidEnd,buffer,len);
		pValidEnd = pValidEnd + len;
	}
	
	if((valid_len + len)>BUFF_SIZE)
	{
		//超出数据长度,舍弃move_len
		move_len = valid_len + len - BUFF_SIZE;
		if((move_len + pValid) > pEnd)	//返回数组头
		{
			len1 = pEnd - pValid;
			len2 = move_len - len1;
			pValid = pHead + len2;
		}
		else
		{
			pValid = pValid + move_len;
		}
		valid_len = BUFF_SIZE;	
	}
	else
	{
		valid_len = valid_len + len;
	}
	return 0;
}
int ringBufferRead(uint8_t *buffer,uint32_t len)
{
	int len1 = 0, len2 = 0;
    if(pHead==NULL)
    {
        return -1;
    }
    assert(buffer);
    
    if(valid_len==0)
    {
        return 0;
    }
	if(len > valid_len)
    {
        len = valid_len;
    }
	
	if((pValid + len) >pEnd)
	{
		len1 = pEnd - pValid;
		len2 = len - len1;
		memcpy(buffer,(uint8_t *)pValid,len1);
		memcpy(buffer+len1,(uint8_t *)pHead,len2);
		pValid = pHead + len2;
	}
	else
	{
		memcpy(buffer,(uint8_t *)pValid,len);
		pValid = pValid + len;
	}
	valid_len = valid_len - len;
	return len;
	
}
uint32_t ringBufferGetValidLen(void)
{

	return valid_len;
}
void ringBufferRelease(void)
{
	if(pHead != NULL)
	{
		free((uint8_t *) pHead);
	}
	pHead = NULL;

}
lid_len = valid_len - len;
	return len;
	
}
uint32_t ringBufferGetValidLen(void)
{

	return valid_len;
}
void ringBufferRelease(void)
{
	if(pHead != NULL)
	{
		free((uint8_t *) pHead);
	}
	pHead = NULL;

}

  • 12
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 好的,下面是关于STM32 USART发送和接收使用DMA的回答: DMA (Direct Memory Access)是一种在不占用CPU的情况下直接进行数据传输的技术。对于STM32的USART模块,使用DMA可以大大减轻CPU的负担,提高数据传输效率。 首先,需要配置USART和DMA。可以使用STM32的CubeMX工具来快速生成初始化代码。在配置USART时,需要设置USART的波特率、数据位、停止位和校验位等参数。在配置DMA时,需要设置DMA的传输方向、数据长度、传输模式、优先级和中断等参数。 接下来,可以使用HAL库提供的函数来启动DMA传输。在发送数据时,可以使用函数HAL_UART_Transmit_DMA()启动DMA传输,该函数会将数据存储在指定的缓冲区中,并将缓冲区的地址传递给DMA进行传输。在接收数据时,可以使用函数HAL_UART_Receive_DMA()启动DMA传输,该函数会将接收到的数据存储在指定的缓冲区中,并将缓冲区的地址传递给DMA进行传输。 在DMA传输完成后,可以使用HAL库提供的回调函数来进行处理。对于发送完成,可以使用函数HAL_UART_TxCpltCallback();对于接收完成,可以使用函数HAL_UART_RxCpltCallback()。 需要注意的是,在使用DMA进行数据传输时,需要确保缓冲区的大小足够大,以便存储需要传输的数据。 希望这个回答能够帮助你了解STM32 USART发送和接收使用DMA的相关知识。如果你有任何其他问题,可以随时提出。 ### 回答2: STM32是一种基于ARM Cortex-M内核的微控制器。在STM32中,USART是其中一种通信接口,它可以用于串口通讯,支持同步和异步模式,而DMA是指直接存储器访问,是一种通过硬件优化(减少中央处理器的干预)直接访问外设(如USART)数据的技术。 在STM32中,USART发送和接收都可以使用DMA技术来实现。DMA可以减少CPU的干预,提高数据传输效率。使用DMA时,USART的数据传输不再需要中断和CPU参与,而是通过DMA控制器直接完成。 在USART发送中,使用DMA可以提高发送速率和可靠性,并减轻CPU的 burden。具体实现步骤包括:初始化USART和DMA,选择传输方向并设置数据长度和地址,启动DMA传输,并检查传输是否完成。 在USART接收中,同样使用DMA可以提高接收速度和减轻CPU压力,具体操作步骤和发送时类似,首先初始化USART和DMA,设置数据长度和地址,选择传输方向并启动DMA传输,然后等待数据接收完成,在回调函数中处理接收到的数据。 总之,使用DMA技术可以极大地提高USART的数据传输效率和可靠性。但也要注意在配置和使用时遵循相关规范,避免发生错误。 ### 回答3: STM32是一类广泛应用于微控制器中的芯片,其中USART是一种通信协议,可以实现串行通信。在STM32上,USART不仅支持单字节发送和接收,还可以使用DMA实现数据的快速传输。在本文中,我们将探讨STM32USART发送和接收时如何使用DMA。 首先,让我们来了解一下DMA(直接存储器访问)的概念。DMA是一种高效的数据传输方式,允许数据在外设和内存之间直接传输,而不需要CPU的干预。在使用DMA进行数据传输时,我们需要设置源地址、目的地址和传输长度,然后启动DMA传输,再次目标数据传输完成,DMA会自动发出传输完成的中断信号。 在STM32中,我们可以通过代码来配置DMA。首先,我们需要定义源地址、目的地址和传输长度,然后将它们写入DMA控制器的相关寄存器。为了使用USART与DMA进行数据传输,我们还需要将DMA与USART相关的寄存器连接起来。在最后一步,我们需要启动DMA传输,等待传输完成中断信号。 使用DMA进行USART发送和接收操作,需要针对每个操作分别进行配置。在发送方面,我们需要设置USART的数据寄存器作为源地址,DMA的数据寄存器作为目的地址,并将传输长度设置为待发送的字节数。在接收方面,我们需要设置USART的数据寄存器作为目的地址,DMA的数据寄存器作为源地址,并将传输长度设置为接收缓冲区的大小。 总之,使用DMA进行USART发送和接收操作可以大大提高数据传输效率和操作速度。但是,需要注意的是,在进行DMA配置时需要仔细处理相关寄存器和缓冲区,否则可能会导致数据传输错误。因此,在使用DMA进行通信之前,我们应该对USART和DMA的相关概念有一定的理解,并根据具体的需求进行合理的配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值