当前位置:主页 > 查看内容

【国信长天蓝桥杯】CT117E-M4 嵌入式开发板 显示屏播放Bad Apple

发布时间:2021-07-22 00:00| 位朋友查看

简介:摘要 最近在指导学生参见 蓝桥杯 嵌入式比赛比赛完成后开发板就闲置了于是准备拿过来做一个好玩的东东。 总体思路是这样的计算机端通过上位机获取视频信息并将视频信息转换成显示屏可现实的数据然后通过串口将数据发送到M4开发板开发板在串口中断中处理数据……

摘要

最近在指导学生参见 蓝桥杯 嵌入式比赛,比赛完成后开发板就闲置了,于是准备拿过来做一个好玩的东东。

总体思路是这样的,计算机端通过上位机获取视频信息,并将视频信息转换成显示屏可现实的数据,然后通过串口将数据发送到M4开发板,开发板在串口中断中处理数据,最后将数据显示到屏幕上。

Bad Apple

上位机软件

上位机软件采用的是开源软件 OLED_ToolBox,软件下载地址:
https://shyboy.oss-cn-shenzhen.aliyuncs.com/readonly/OLED_ToolBox.exe

这个软件是开源的,如果有兴趣的话可以研究下源码,源码地址:
https://github.com/AnChangNice/oled_display_gui



软件配置如下:

在这里插入图片描述
波特率建议采用100000,分辨率采用240*160,横向扫描,字节横向排列。

右边选择 Screen模式,在B站搜索 Bad Apple,打开视频,将捕获窗口拖到视频上,调节下窗口大小,刚好包含图像即可。

操作小提示:

  1. 点击 Scan Port 扫描到串口后,一定要在下拉框再次点选对应的串口号才行!
  2. 捕获窗口是一个红色的框框,点击框框上部可进行拖拽移动,移动到合适位置后,一定要再次点击鼠标才能将窗口固定。

单片机代码

单片机软件在 显示屏代码 【HAL_06_LCD】的基础上添加了串口接收功能,波特率1000000,并开启了接收中断,操作步骤如下:

① 添加 stm32g4xx_hal_uart.c , stm32g4xx_hal_uart_ex.c

双击Drivers/STM32G4xx_HAL_Driver,打开添加文件对话框,在向上一级 -> Drivers -> STM32G4xx_HAL_Driver -> Src中,找到stm32g4xx_hal_uart.c , stm32g4xx_hal_uart_ex.c 并添加。添加后如下图所示:
在这里插入图片描述

② 修改 stm32g4xx_hal_conf.h 文件

在如下位置找到该文件,并打开:
在这里插入图片描述
取消注释 #define HAL_UART_MODULE_ENABLED 这一行,取下注释后如下图所示:
在这里插入图片描述

main.c 添加#include "stm32g4xx_hal_uart.h"

main.c 适当位置添加#include "stm32g4xx_hal_uart.h",添加后如下图所示:
在这里插入图片描述

④ 复制如下 TIM 初始化的代码

注意:下列代码包含了UART1的初始化接收中断,同学们可参考自行使用!

UART_HandleTypeDef huart1;
uint8_t uart_rx_buf1[1024 * 6]; //串口接收数据缓冲区1
uint8_t uart_rx_buf2[1024 * 6]; //串口接收数据缓冲区2


// UART1 初始化
static void MX_UART1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
	
	PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
	PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); //配置USART1外设的时钟
	
	__HAL_RCC_USART1_CLK_ENABLE(); //打开USART1的时钟
	__HAL_RCC_GPIOA_CLK_ENABLE();
	
	huart1.Instance = USART1;
	huart1.Init.BaudRate = 1000000; //设置波特率
	huart1.Init.WordLength = UART_WORDLENGTH_8B; //设置数据位
	huart1.Init.StopBits = UART_STOPBITS_1; //设置停止位
	huart1.Init.Parity = UART_PARITY_NONE;
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
	huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
	huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
	
	HAL_MultiProcessor_Init(&huart1, 0, UART_WAKEUPMETHOD_IDLELINE);
	HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8);
	
	HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8);
	HAL_UARTEx_DisableFifoMode(&huart1);
	
	GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; //复用开漏输出
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.Alternate = GPIO_AF7_USART1;//复用功能
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //初始化串口引脚PA9 PA10
	
	HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); //设置串口中断优先级
	HAL_NVIC_EnableIRQ(USART1_IRQn); //打开串口中断
	
	HAL_UART_Receive_IT(&huart1, uart_rx_buf1, 4800); //设置串口中断缓冲区及中断阈值(当前为1)
}

//串口中断
void USART1_IRQHandler(void) //串口中断
{
	HAL_UART_IRQHandler(&huart1);
}
int buf = 1; //记录当前使用的是buf1 还是 buf2
int disp = 0; //告诉main该显示什么内容,0不显示,1显示buf1,2显示buf2

//串口中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{
	if(buf == 1) //若果当前是使用的是buf1
	{
		buf = 2; //下次使用buf2
		disp = 1;//告诉main显示buf1的内容到屏幕
		HAL_UART_Receive_IT(&huart1, uart_rx_buf2, 4800);  //切换为buf2
	}
	else
	{
		buf = 1; //下次使用buf1
		disp = 2;//告诉main显示buf2的内容到屏幕
		HAL_UART_Receive_IT(&huart1, uart_rx_buf1, 4800);  //切换为buf2
	}
}

⑤ 主函数main()内容

int main(void)
{
	HAL_Init();
	
	SystemClock_Config();
	
	MX_GPIO_Init();
	
	MX_UART1_Init();
	
	LCD_Init();
	
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	

  while (1)
  {
		if(disp == 1) 
		{
			disp = 0;
			LCD_UartPic(uart_rx_buf1);
		}
		else if(disp == 2)
		{
			disp = 0;
			LCD_UartPic(uart_rx_buf2);
		}
  }
}

LCD_UartPic()函数内容如下,次函数应放在lcd.c

void LCD_UartPic(uc8 *c)
{
	u32 index = 1, i = 0;
	
	u8 x = 40;
	u16 y = 0;
	
	for(; x < 200; x++)
	{
		LCD_SetCursor(x, 280);
		LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
		for(y = 0; y < 30; y++)
		{
			for(i = 0; i < 8; i ++)
			{
				if((c[index] & (1 << i)) == 0x00)
				{
					LCD_WriteRAM(BackColor);
				}
				else
				{
					LCD_WriteRAM(TextColor);
				}
			}
			index ++;
		}
	}
}

运行效果

虽然是彩屏,但是当成黑白屏使用了

在这里插入图片描述

如果你喜欢此文章,欢迎点赞 关注 收藏 转发.

;原文链接:https://blog.csdn.net/weixin_48033504/article/details/115763284
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐