硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2833|回复: 9
收起左侧

[STM32H7] H750驱动OV7670无法正常显示

[复制链接]
回帖奖励 2 个金币 回复本帖可获得 1 个金币奖励! 每人限 1 次(中奖概率 30%)

2

主题

6

回帖

12

积分

新手上路

积分
12
发表于 2020-4-12 21:34:33 | 显示全部楼层 |阅读模式
板子:自己画的H750VBT6外设:
LCD:st7789(320*240)(FMC模拟8080时序)
摄像头:ov7670(外部12M晶振,已配置寄存器到了48Mhz({0x11, 0x01}))

驱动思路:
程序参考V7的摄像头,使用了DMA1。

定义了一个联合体来存放摄像头数据
typedef union{
struct {
        vu16 buffer_16[320*240];
};
vu32 buffer_32[320*120];
} CAMERA_BUF_t;

CAMERA_BUF_t             g_camera_data;
使用这个结构体是考虑LCD画点的颜色是u16格式
//画点代码
void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)
{       
    LCD_SetCursor(x,y);                //设置光标位置
        LCD->LCD_REG=lcddev.wramcmd;
        LCD->LCD_RAM=color;
}         

//自定义的摄像头刷屏
void LCD_SP(void)
{
        int x =0;
        int y = 0;
        int i = 0;
                for(x=0;x<320;x++)
                {
                        for(y = 0;y<240;y++)
                        {
                          LCD_Fast_DrawPoint(x,y,g_camera_data.buffer_16);
                                i++;
                        }
                }
}


但是移植好后测试发现显示不正确,在开启彩条模式显示如下图。
TIM图片20200412211852.jpg
在论坛里面找,发现有个很类似的问题,看帖子说是LCD的问题
x3 + OV7670+WQVGA 输出彩条有问题
http://www.armbbs.cn/forum.php?m ... 9&fromuid=23224
我就检查了一些我的LCD的方向,调用LCD_FILL填充了一个矩形(LCD_Fill(100,100,130,130,RED);)
TIM图片20200412211858.jpg
左上角为(0,0)从左到右,从上到下。
不开启彩条,实时显示效果如图
TIM图片20200412211902.jpg
图像诡异,个人观察,屏幕中图像被上中下三个段,每个段都相同。

如何解决?

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
发表于 2020-4-13 08:18:21 | 显示全部楼层
如果是参考V7的,注意引脚,时钟和MPU配置。
回复

使用道具 举报

2

主题

6

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2020-4-13 13:07:26 | 显示全部楼层
今天仔细找了一下问题,发现了有个严重硬件问题,估计是这个引起的,DVDD这个引脚按数据手册要接1.8V的,我居然把它悬空了,画板子太不仔细了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
发表于 2020-4-14 10:32:36 | 显示全部楼层
DylanMingan 发表于 2020-4-13 13:07
今天仔细找了一下问题,发现了有个严重硬件问题,估计是这个引起的,DVDD这个引脚按数据手册要接1.8V的,我 ...

好的,后面还有什么问题,我们再交流。
回复

使用道具 举报

2

主题

6

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2020-4-19 15:15:20 | 显示全部楼层
本帖最后由 DylanMingan 于 2020-4-20 11:47 编辑

修复硬件问题还是和原来现象一样,仔细想了想,是我的刷屏函数不对,因为摄像头的数据是从左到右,从上到下。现在把数据存在 u32 的buffer[320*240]数值中,重新刷屏函数
//重写的刷屏函数
void LCD_SP(void)
{
        int x =0;
        int y = 0;
        int i = 0;
        u16 color;
        for(y = 0;y<240; y++)  //先从左到右,所以y坐标循环在外
        {
                        for(x = 0;x<160;x++)
                        {
                                color = (u16)(buffer>>16);
                          LCD_Fast_DrawPoint(2*x,y,color);
                                color = (u16)(buffer);
                                LCD_Fast_DrawPoint(2*x+1,y,color);
                                i++;
                        }
                }
        }


可以显示完整的图像了,但是颜色不对,彩条模式如下
TIM图片20200419150910.jpg
实时显示如图
TIM图片20200419150915.jpg
键盘显示上面蒙了层绿色?整体的画面都是紫色和绿色黄色为主,想问下如何解决?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
发表于 2020-4-20 09:43:23 | 显示全部楼层

回帖奖励 +1 个金币

DylanMingan 发表于 2020-4-19 15:15
修复硬件问题还是和原来现象一样,仔细想了想,是我的刷屏函数不对,因为摄像头的数据是从左到右,从上到下 ...

你的图片太大,刷不出来了,压缩下,几百KB就行。

1、注意RGB,BGR问题。
2、直接复制我的寄存器配置。
回复

使用道具 举报

2

主题

6

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2020-4-20 13:25:48 | 显示全部楼层
eric2013 发表于 2020-4-20 09:43
你的图片太大,刷不出来了,压缩下,几百KB就行。

1、注意RGB,BGR问题。

现在上传会压缩图片大小。
1.直接复制V7的寄存器,一点都没改
2.置换了RGB变为BGR,置换函数如下
//置换再刷屏
void LCD_SP(void)
{
        int x =0;
        int y = 0;
        int i = 0;
        u16 color;
        u16 R,G,B;
        u16 color1;
        for(y = 0;y<240; y++)
        {
                        for(x = 0;x<160;x++)
                        {
                                color = (u16)(buffer>>16);
                                R = color & 0xF800;
                                G = color & 0x07E0;
                                B = color & 0x001F;
                                color1 = (R>>11) + G +(B<<11);    //R和B交换
                                LCD_Fast_DrawPoint(2*x,y,color1);

                                color = (u16)(buffer);
                                R = color & 0xF800;
                                G = color & 0x07E0;
                                B = color & 0x001F;
                                color1 = (R>>11) + G +(B<<11);    //R和B交换
                                LCD_Fast_DrawPoint(2*x+1,y,color1);
                                i++;
                        }
                }
        }

以下是交换BR,也就是BGR的效果图
IMG_20200420_131704.jpg IMG_20200420_131423.jpg
原来绿色还是没有消失,只不过原先的偏紫蓝色的现在偏红色了
RGB下的效果图
IMG_20200420_131939.jpg
我有点搞不明白了,我是直接复制V7的寄存器内容的,理论上讲应该是RGB565,现在互换RB后还是有绿色
我是定义了一个数组存放数据的,应该不用开启MPU把?我MPU里面只有FMC的保护代码

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
发表于 2020-4-21 08:52:03 | 显示全部楼层
DylanMingan 发表于 2020-4-20 13:25
现在上传会压缩图片大小。
1.直接复制V7的寄存器,一点都没改
2.置换了RGB变为BGR,置换函数如下

1. MPU肯定要设置的,可以直接关闭DCMI DMA缓冲区的Cache。
2、另外你的这个代码buffer怎么更新的,看着像是一个32bit变量,这个循环有点没看懂。
回复

使用道具 举报

2

主题

6

回帖

12

积分

新手上路

积分
12
 楼主| 发表于 2020-4-21 12:05:09 | 显示全部楼层
eric2013 发表于 2020-4-21 08:52
1. MPU肯定要设置的,可以直接关闭DCMI DMA缓冲区的Cache。
2、另外你的这个代码buffer怎么更新的,看着 ...

1.我的MPU设置
void LCD_MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_Initure;

    HAL_MPU_Disable();                                                        //&#197;&#228;&#214;&#195;MPU&#214;&#174;&#199;°&#207;è1&#216;±&#213;MPU,&#197;&#228;&#214;&#195;íê3éò&#212;oó&#212;úê1&#196;üMPU
    MPU_Initure.Enable       =MPU_REGION_ENABLE;          
    MPU_Initure.Number       =MPU_REGION_NUMBER0;               
    MPU_Initure.BaseAddress  =LCD_ADDRESS_START;        //(0X60000000)
    MPU_Initure.Size         =LCD_REGION_SIZE;                        //256MB
    MPU_Initure.SubRegionDisable  =0X00;
    MPU_Initure.TypeExtField      =MPU_TEX_LEVEL0;
    MPU_Initure.AccessPermission  =MPU_REGION_FULL_ACCESS;        //′&#203;region&#191;é&#182;áD′
    MPU_Initure.DisableExec       =MPU_INSTRUCTION_ACCESS_ENABLE;        //&#212;êDí&#182;áè&#161;′&#203;&#199;&#248;óò&#214;Dμ&#196;&#214;&#184;á&#238;
    MPU_Initure.IsShareable       =MPU_ACCESS_NOT_SHAREABLE;
    MPU_Initure.IsCacheable       =MPU_ACCESS_NOT_CACHEABLE;
    MPU_Initure.IsBufferable      =MPU_ACCESS_BUFFERABLE;
    HAL_MPU_ConfigRegion(&MPU_Initure);
       
                /* &#197;&#228;&#214;&#195;AXI SRAMμ&#196;MPUê&#244;D&#212;*/
    MPU_Initure.Enable = MPU_REGION_ENABLE;
    MPU_Initure.BaseAddress = 0x24000000;
    MPU_Initure.Size = MPU_REGION_SIZE_512KB;
    MPU_Initure.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_Initure.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    MPU_Initure.IsCacheable = MPU_ACCESS_CACHEABLE;
    MPU_Initure.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    MPU_Initure.Number = MPU_REGION_NUMBER1;
    MPU_Initure.TypeExtField = MPU_TEX_LEVEL0;
    MPU_Initure.SubRegionDisable = 0x00;
    MPU_Initure.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    HAL_MPU_ConfigRegion(&MPU_Initure);

    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);     //&#191;a&#198;&#244;MPU
}


2.buffer是一个全局的u32类型的数组,有关摄像头的主程序流程如下,buffer的数据由主程序循环开启了DMA传输更新的

...
                CAM_Start(buffer);
...
                LCD_Clear(BLUE);
...
        while(1)
        {
                CAM_Start1(buffer);
                rt_thread_mdelay(100);
                LCD_SP();         
        }


//RB交换并刷屏函数
void LCD_SP(void)
{
        int x =0;
        int y = 0;
        int i = 0;
        u16 color;
        u16 R,G,B;
        u16 color1;
        for(y = 0;y<240; y++)
        {
                        for(x = 0;x<160;x++)
                        {
                                //由于DMA传输是32位,而RGB565为16位,需要拆开读取
                                color = (u16)(buffer>>16);   //读取DMA传送的前16位颜色信息
                                R = color & 0xF800;               //取出R通道数据
                                G = color & 0x07E0;               //取出G通道数据
                                B = color & 0x001F;               //取出B通道数据
                                color1 = (R>>11) + G +(B<<11); //交换
                                //color1 = R + G + B; //不交换
                                LCD_Fast_DrawPoint(2*x,y,color1);    //按顺序画偶数点
                                color = (u16)(buffer);          //读取DMA传送的后16位颜色信息
                                R = color & 0xF800;               //取出R通道数据
                                G = color & 0x07E0;               //取出G通道数据
                                B = color & 0x001F;               //取出B通道数据
                                color1 = (R>>11) + G +(B<<11);  // //交换
                                //color1 = R + G + B; //不交换
                                LCD_Fast_DrawPoint(2*x+1,y,color1);  //按顺序画奇数点
                                i++;
                        }
                }
        }



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107077
QQ
发表于 2020-4-22 19:42:03 | 显示全部楼层
DylanMingan 发表于 2020-4-21 12:05
1.我的MPU设置
void LCD_MPU_Config(void)
{

MPU里面的SDRAM和AXI SRAM全部配置成这样:

MPU_Initure.IsShareable  =MPU_ACCESS_NOT_SHAREABLE;
MPU_Initure.IsCacheable  =MPU_ACCESS_NOT_CACHEABLE;
MPU_Initure.IsBufferable   =MPU_ACCESS_BUFFERABLE;
MPU_Initure.TypeExtField   =MPU_TEX_LEVEL1;
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-17 00:21 , Processed in 0.235924 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表