当前位置: 首页 > >

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

发布时间:

摘要

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


总体思路是这样的,计算机端通过上位机获取视频信息,并将视频信息转换成显示屏可现实的数据,然后通过串口将数据发送到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,打开视频,将捕获窗口拖到视频上,调节下窗口大小,刚好包含图像即可。


操作小提示:


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



单片机代码

单片机软件在 显示屏代码 【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 ++;
}
}
}

运行效果

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



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



友情链接: