最近在指导学生参见 蓝桥杯 嵌入式比赛,比赛完成后开发板就闲置了,于是准备拿过来做一个好玩的东东。
总体思路是这样的,计算机端通过上位机获取视频信息,并将视频信息转换成显示屏可现实的数据,然后通过串口将数据发送到M4开发板,开发板在串口中断中处理数据,最后将数据显示到屏幕上。
上位机软件采用的是开源软件 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 ++;
}
}
}
虽然是彩屏,但是当成黑白屏使用了
如果你喜欢此文章,欢迎点赞
关注
收藏
转发
.