本帖最后由 地瓜patch 于 2025-4-28 21:36 编辑
一、概述
终于解决解决了pack包的问题,见帖子https://bbs.21ic.com/icview-3446880-1-1.html打开STM32Cube_FW_N6_V1.1.0开发包,下入第一个bsp例程,该例程分为5个独立的demo。
二、例程功能分析
对例程进行解读分析,也是一个学习过程。
通过读程序能够学习作者的编程思路和方法。
1.第一个Demo是触屏填充实现这个功能的代码逻辑很简单,首先由 x1 = TS_State.TouchX; y1 = TS_State.TouchY;分别获取当前触点的坐标值。然后判断坐标在蓝、红、黄、绿哪个圆内 if ((y1 > (CIRCLE_YPOS(1) - CIRCLE_RADIUS)) && (y1 < (CIRCLE_YPOS(1) + CIRCLE_RADIUS)))
将其用对应颜色填充 UTIL_LCD_FillCircle(CIRCLE_XPOS(1), CIRCLE_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_BLUE);
[size=13.3333px]
代码如下
if(TS_State.TouchDetected)
{
x1 = TS_State.TouchX;
y1 = TS_State.TouchY;
if ((y1 > (CIRCLE_YPOS(1) - CIRCLE_RADIUS)) &&
(y1 < (CIRCLE_YPOS(1) + CIRCLE_RADIUS)))
{
if ((x1 > (CIRCLE_XPOS(1) - CIRCLE_RADIUS)) &&
(x1 < (CIRCLE_XPOS(1) + CIRCLE_RADIUS)))
{
if ((state & 1) == 0)
{
Touchscreen_DrawBackground_Circles(state);
UTIL_LCD_FillCircle(CIRCLE_XPOS(1), CIRCLE_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_BLUE);
HAL_Delay(1);
state = 1;
}
}
if ((x1 > (CIRCLE_XPOS(2) - CIRCLE_RADIUS)) &&
(x1 < (CIRCLE_XPOS(2) + CIRCLE_RADIUS)))
{
if ((state & 2) == 0)
{
Touchscreen_DrawBackground_Circles(state);
UTIL_LCD_FillCircle(CIRCLE_XPOS(2), CIRCLE_YPOS(2), CIRCLE_RADIUS, UTIL_LCD_COLOR_RED);
HAL_Delay(1);
state = 2;
}
}
if ((x1 > (CIRCLE_XPOS(3) - CIRCLE_RADIUS)) &&
(x1 < (CIRCLE_XPOS(3) + CIRCLE_RADIUS)))
{
if ((state & 4) == 0)
{
Touchscreen_DrawBackground_Circles(state);
UTIL_LCD_FillCircle(CIRCLE_XPOS(3), CIRCLE_YPOS(3), CIRCLE_RADIUS, UTIL_LCD_COLOR_YELLOW);
state = 4;
}
}
if ((x1 > (CIRCLE_XPOS(4) - CIRCLE_RADIUS)) &&
(x1 < (CIRCLE_XPOS(4) + CIRCLE_RADIUS)))
{
if ((state & 8) == 0)
{
Touchscreen_DrawBackground_Circles(state);
UTIL_LCD_FillCircle(CIRCLE_XPOS(4), CIRCLE_YPOS(3), CIRCLE_RADIUS, UTIL_LCD_COLOR_GREEN);
state = 8;
}
}
}
} /* of if(TS_State.TouchDetected) */
2.第二个是跟随触点生成随机颜色的圆点
以下四条语句,画出了上图页眉蓝色区域并填充,限定了文字位白色,填充为蓝色
UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_WHITE); UTIL_LCD_SetFont(&Font24);
以下四条语句,将文字"Touchscreen dual touch polling " "Please press the Touchscreen to activate"
"single and dual touch, then press USER button",指定起始坐标后分三行写在页眉蓝色区域
UTIL_LCD_DisplayStringAt(0, 0, (uint8_t *)"Touchscreen dual touch polling", CENTER_MODE);
UTIL_LCD_SetFont(&Font16);
UTIL_LCD_DisplayStringAt(0, 45, (uint8_t *)"Please press the Touchscreen to activate", CENTER_MODE);
UTIL_LCD_DisplayStringAt(0, 60, (uint8_t *)"single and dual touch, then press USER button", CENTER_MODE);
以下两条语句画出了触屏区域,用两个矩形框加粗了边界的宽度。将线宽从1个像素加粗为2个像素。
UTIL_LCD_DrawRect(10, 90, x_size - 20, y_size - 100, UTIL_LCD_COLOR_BLUE);
UTIL_LCD_DrawRect(11, 91, x_size - 22, y_size - 102, UTIL_LCD_COLOR_BLUE);
以下语句在触摸点x1,y1画出了一个圆点,该点半径为15个像素,颜色是由touchscreen_color_idx累加得来,所以不同时刻触摸同一个像素显示颜色不同。
UTIL_LCD_FillCircle(x1, y1, TS_MULTITOUCH_FOOTPRINT_CIRCLE_RADIUS, colors[(touchscreen_color_idx++ % 24)]);
以下语句将TOUCH INFO显示在页脚
UTIL_LCD_DisplayStringAt(0, y_size - 70, (uint8_t *)"TOUCH INFO : ", CENTER_MODE);
在这个demo中可以同时触摸两个触点,由x2 = TS_MTState.TouchX[1];y2 = TS_MTState.TouchY[1];语句获取第二个触点的坐标
以下语句将两个触点坐标显示在页脚位置,紧随TOUCH INFO :之后
sprintf((char*)lcd_string, "x1 = %u, y1 = %u", x1, y1);
sprintf((char*)lcd_string, "x2 = %u, y2 = %u", x2, y2);
注意:在这个demo中,同时只能最多触摸两个点,大于两个点的触摸,死机。
3.第三个也是跟随触点生成随机颜色的点,不过这个demo是将屏分为240份,随机颜色填充240个方格
用一个嵌套循环将屏幕分为240个方格,hTS.Width=800;hTS.Height=480;因此K的最大值为20,L的最大值为12在这个demo中,只能识别一个触点,无法识别两个及其以上。
for(k = 0; k < hTS.Width/40; k++)
{
for(l = 0; l < hTS.Height/40; l++)
{
UTIL_LCD_DrawRect(40*k, 40*l,40,40, UTIL_LCD_COLOR_BLACK);
}
}
4.第四个Demo是LCD显示
1)显示3行8列 80*80像素的调色板
for (color_index = 0; color_index < 24; color_index++)
{
int x = 80 * ((color_index % 8) + 1);
int y = 80 * (color_index / 8 + 2);
UTIL_LCD_FillRect(x, y, 80, 80, colors[color_index]);
}
2)显示4行6列空心圆
for(color_index = 0; color_index < 4; color_index++)
{
for(i = 0; i < 6; i++)
{
UTIL_LCD_DrawCircle(150 + (100*i), 100*(color_index+1), 40, UTIL_LCD_COLOR_BLACK);
}
}
3)显示一个4行6列的24色圆形配色表
for(color_index = 0; color_index < 4; color_index++)
{
for(i = 0; i < 6; i++)
{
UTIL_LCD_FillCircle(150 + (100*i), 100*(color_index+1), 40, colors[colorIndex]);
colorIndex++;
HAL_Delay(50);
}
}
4)显示3个彩色三角形
for(color_index = 0; color_index < 6; color_index++)
{
for(i = 0; i < 4; i++)
{
triangle[0.X = 40*color_index;
triangle[0.Y = 40 + 50*(i);
triangle[1.X = 40*(color_index+1);
triangle[1.Y = 65 + 50*(i);
triangle[2.X = 40*color_index;
triangle[2.Y = 40 + 50*(1+i);
UTIL_LCD_FillPolygon(triangle, 3, colors[colorIndex]);
if(colors[colorIndex == UTIL_LCD_COLOR_WHITE)
{
UTIL_LCD_DrawPolygon(triangle, 3, UTIL_LCD_COLOR_BLACK);
}
colorIndex++;
}
}
5)在同一行显示4个ST图标
UTIL_LCD_DrawBitmap(80, 130, (uint8_t *)st**);
UTIL_LCD_DrawBitmap(240, 130, (uint8_t *)st**);
UTIL_LCD_DrawBitmap(400, 130, (uint8_t *)st**);
UTIL_LCD_DrawBitmap(560, 130, (uint8_t *)st**);
6)RGB888显示测试
UTIL_LCD_DisplayStringAt(0, 100, (uint8_t *)"LCD RGB888", CENTER_MODE);
for (color_index = 0; color_index < 16; color_index++)
{
x = 40 * ((color_index % 4) + 8) ;
y = (40 * (color_index / 4 + 4));
UTIL_LCD_FillRect(x, y, 40, 40, colors[color_index]);
}
7)ARGB4444显示测试
UTIL_LCD_DisplayStringAt(0, 100, (uint8_t *)"LCD ARGB4444", CENTER_MODE);
for (color_index = 8; color_index < 24; color_index++)
{
x = 40 * ((color_index % 4) + 8) ;
y = (40 * (color_index / 4 + 4));
UTIL_LCD_FillRect(x, y, 40, 40, colors[color_index]);
}
5.第五个demo是读写sd卡
SD卡初始化
UTIL_LCD_DisplayStringAt(20, 100, (uint8_t *)"SD Initialization : OK", LEFT_MODE);
SD卡连接正常 UTIL_LCD_DisplayStringAt(20, 300, (uint8_t *)" SD Connected", RIGHT_MODE); SD卡擦除正常 UTIL_LCD_DisplayStringAt(20, 115, (uint8_t *)"SD ERASE : OK", LEFT_MODE);
SD写入0x22FF
SD_state = BSP_SD_WriteBlocks(0,(uint32_t *)aTxBuffer, SD_START_ADDRESS, NB_BLOCK_BUFFER); SD写入完成
UTIL_LCD_DisplayStringAt(20, 130, (uint8_t *)"SD WRITE : OK", LEFT_MODE);
SD读取完成
UTIL_LCD_DisplayStringAt(20, 145, (uint8_t *)"SD READ : OK", LEFT_MODE);
SD测试结束
UTIL_LCD_DisplayStringAt(20, 160, (uint8_t *)"SD TEST : OK", LEFT_MODE); [size=13.3333px]
6.第六个是摄像头获取图像并显示在LCD屏上,并旋转180度
获取Camera数据 BSP_CAMERA_Start(0, (uint8_t *)CAMERA_FRAME_BUFFER, CAMERA_MODE_CONTINUOUS); [size=13.3333px]
Camera图像在LCD中反转4次,首先是垂直镜像,然后是水平镜像 while(MirrorFlipIndex < 4)
{
Camera_ISP_IdleWait(2000);
BSP_CAMERA_SetMirrorFlip(0, CameraMirrorFlip[MirrorFlipIndex]);
MirrorFlipIndex++;
}
[attach]2398350[/attach[color=var(--darkreader-text-444444, #a19c95)][backcolor=var(--darkreader-background-ffffff, #141617)]]
Camera镜像函数,说实话没看明白,没有对数据进行造作呢 int32_t BSP_CAMERA_SetMirrorFlip(uint32_t Instance, uint32_t MirrorFlip)
{
int32_t ret;
if (Instance >= CAMERA_INSTANCES_NBR)
{
ret = BSP_ERROR_WRONG_PARAM;
}
else if (Camera_Cap.MirrorFlip == 0U)
{
ret = BSP_ERROR_FEATURE_NOT_SUPPORTED;
}
else if (Camera_Drv->MirrorFlipConfig(Camera_CompObj, MirrorFlip) < 0)
{
ret = BSP_ERROR_COMPONENT_FAILURE;
}
else
{
Camera_Ctx[Instance.MirrorFlip = MirrorFlip;
ret = BSP_ERROR_NONE;
}
/* Return BSP status */
return ret;
}
从DCMIPP中获取Camera数据
int32_t BSP_CAMERA_Start(uint32_t Instance, uint8_t *pbuff, uint32_t Mode)
{
int32_t ret = BSP_ERROR_NONE;
if (Instance >= CAMERA_INSTANCES_NBR)
{
ret = BSP_ERROR_WRONG_PARAM;
}
else if (HAL_DCMIPP_CSI_PIPE_Start(&hcamera_dcmipp, DCMIPP_PIPE1, DCMIPP_VIRTUAL_CHANNEL0 , (uint32_t)pbuff, Mode) != HAL_OK)
{
ret = BSP_ERROR_PERIPH_FAILURE;
}
else
{
/* No action */
}
/* Start the Image Signal Processing */
if (ISP_Start(&hcamera_isp) != ISP_OK)
{
ret = BSP_ERROR_COMPONENT_FAILURE;
}
/* Return BSP status */
return ret;
}
三、小结
这个bsp的例程所展示的都是最基本的功能。 这个例程的最大好处来说就是简单,逻辑清晰,流程明了。作为学习用例程极其合适。 通过分析程序,学习了多种图形的绘制,填充。 学习了如何获取触电坐标。 学习了Camera数据的获取和使用。 这个程序的确值得认真学习分析。
开卷有益!!!!
|