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;
}