硬汉嵌入式论坛

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

[JPEG] h750硬解jpeg数据出错了

[复制链接]

3

主题

38

回帖

47

积分

新手上路

积分
47
发表于 2025-5-12 19:00:52 | 显示全部楼层 |阅读模式
本帖最后由 spi-sd 于 2025-5-12 19:26 编辑

新人自学stm32h750,在网上找了一些教程学习硬解jpg图片,然后发现硬解jpg以后的数据和我预期的不一样,所以想请教一下下面这种解码错误的图一般是哪里出现的问题


下面图片的数据是我dump解码以后的yuv图片的数据,是还没有转换成rgb的数据,上面那张是正常的照片,下面是解码出错的照片(看起来都是在解码为8x8小块的时候就出错了)

27.png



解码的流程是首先各种初始化以后,设置好jpg寄存器,然后读取jpg图片到内存,设置好MDMA_Channel7直接将图片的内存地址传递过去开启MDMA中断,然后就不管了,接着等jpg的文件头解析完毕,然后就开始监视JPEG->SR的OFNEF寄存器如果有数据就接收,但是最后接收的数据好像对不怎么对,数据量也少了一半,请问是我哪里的逻辑没对吗?


[C] 纯文本查看 复制代码
 if (JPEG->SR & JPEG_SR_OFNEF) {
            uint32_t r3 = JPEG->DOR;     // 读取32位数据(2个像素)
            *argb_dest++ = (r3 >> 16) & 0xFFFF;  // 高16位像素
            *argb_dest++ = r3 & 0xFFFF;          // 低16位像素
           output_pixel_count += 2; // 每次读取2个像素                                
        }


[C] 纯文本查看 复制代码
void JPEG_Init_0(void) {

        RCC->AHB3ENR |= 1 << 5; 
                
    JPEG->CR = 0;                       /* 先清零 */
    JPEG->CR |= 1 << 0;                 /* 使能硬件JPEG 启用JPEG编解码器核心*/
    JPEG->CONFR0 &= ~(1 << 0);          /* 停止JPEG编解码进程 */
    JPEG->CR |= 1 << 13;                /* 清空输入fifo */
    JPEG->CR |= 1 << 14;                /* 清空输出fifo */
    JPEG->CFR = 3 << 5;                 /* 清空标志 */                
    JPEG->CONFR1 |= 1 << 8;             /* 使能header处理 */                
     NVIC_SetPriority(JPEG_IRQn, 1);    // 设置JPEG中断优先级 (抢占优先级: 1, 子优先级: 0)        
    // 使能JPEG中断
    NVIC_EnableIRQ(JPEG_IRQn);
        
/////////////////////////////////////////////////
    JPEG->CONFR1 |= 1 << 3;         /* 硬件JPEG解码模式 */
  //  JPEG->CR &= ~(0X3F << 1);       /* 关闭所有中断 */
    JPEG->CR |= 1 << 6;             /* 使能Jpeg Header解码完成中断 */
    JPEG->CR |= 1 << 5;             /* 使能解码完成中断 */
    JPEG->CONFR0 |= 1 << 0;         /* 使能JPEG编解码进程 启动解码*/        
        
////////////////////////////////////////////////////////        
    MDMA_Channel7->CCR = 0;         /* MDMA通道7禁止 */
    MDMA_Channel7->CIFCR = 0X1F;    /* 中断标志清零 */

    JPEG->CONFR1 |= 1 << 3;         /* 硬件JPEG解码模式 */
    JPEG->CONFR0 &= ~(1 << 0);      /* 停止JPEG编解码进程 */
    JPEG->CR &= ~(0X3F << 1);       /* 关闭所有中断 */
    JPEG->CR |= 1 << 13;            /* 清空输入fifo */
    JPEG->CR |= 1 << 14;            /* 清空输出fifo */
    JPEG->CR |= 1 << 6;             /* 使能Jpeg Header解码完成中断 */
    JPEG->CR |= 1 << 5;             /* 使能解码完成中断 */
    JPEG->CFR = 3 << 5;             /* 清空标志 */
    JPEG->CONFR0 |= 1 << 0;         /* 使能JPEG编解码进程 */
}


[C] 纯文本查看 复制代码
void jpeg_in_dma_init(uint32_t meminaddr, uint32_t meminsize)
{

   uint32_t regval = 0;
    uint32_t addrmask = 0;
    RCC->AHB3ENR |= 1 << 0;             /* 使能MDMA时钟 */
    MDMA_Channel7->CCR = 0;             /* 输入MDMA清零 */

    while (MDMA_Channel7->CCR & 0X01);  /* 等待MDMA_Channel7关闭完成 */

    MDMA_Channel7->CIFCR = 0X1F;        /* 中断标志清零 */
    MDMA_Channel7->CCR |= 1 << 2;       /* CTCIE=1,使能通道传输完成中断 */
    MDMA_Channel7->CCR |= 2 << 6;       /* PL[1:0]=2,高优先级 */
    MDMA_Channel7->CBNDTR = meminsize;  /* 传输长度为meminsize */
    MDMA_Channel7->CDAR = (uint32_t)&JPEG->DIR; /* 目标地址为:JPEG->DIR */
    MDMA_Channel7->CSAR = meminaddr;    /* meminaddr作为源地址 */
    regval = 0 << 28;                   /* TRGM[1:0]=0,每个MDMA请求触发一次buffer传输 */
    regval |= 1 << 25;                  /* PKE=1,打包使能 */
    regval |= (32 - 1) << 18;           /* TLEN[6:0]=31,buffer传输长度为32字节 */
    regval |= 4 << 15;                  /* DBURST[2:0]=4,目标突发传输长度为16 */
    regval |= 4 << 12;                  /* SBURST[2:0]=4,源突发传输长度为16 */
    regval |= 0 << 8;                   /* SINCOS[1:0]=0,源地址变化单位为8位(字节) */
    regval |= 2 << 6;                   /* DSIZE[1:0]=2,目标位宽为32位 */
    regval |= 0 << 4;                   /* SSIZE[1:0]=0,源位宽为8位 */
    regval |= 0 << 2;                   /* DINC[1:0]=0,目标地址固定 */
    regval |= 2 << 0;                   /* SINC[1:0]=2,源地址自增 */
    MDMA_Channel7->CTCR = regval;       /* 设置CTCR寄存器 */
    MDMA_Channel7->CTBR = 17 << 0;      /* MDMA的硬件触发通道17触发inmdma,通道17=JPEG input FIFO threshold
                                         * 详见<STM32H7xx参考手册>577页,table 95
                                         */
    addrmask = meminaddr & 0XFF000000;  /* 获取掩码 */

    if (addrmask == 0X20000000 || addrmask == 0)MDMA_Channel7->CTBR |= 1 << 16; /* 使用AHBS总线访问DTCM/ITCM */
    // 配置NVIC
    // 设置MDMA中断优先级 (抢占优先级: 2, 子优先级: 0)
    NVIC_SetPriority(MDMA_IRQn, 2);
   
    // 使能MDMA中断
    NVIC_EnableIRQ(MDMA_IRQn);
}






回复

使用道具 举报

3

主题

38

回帖

47

积分

新手上路

积分
47
 楼主| 发表于 2025-5-12 23:09:05 | 显示全部楼层
看起来是搞定了,原来是我在接收解码的yuv数据的时候,顺序搞反了,接收的4个字节应该是先写入低16bit,在写入高16bit
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-5-13 09:20:19 | 显示全部楼层
好的,解决了就好
回复

使用道具 举报

3

主题

38

回帖

47

积分

新手上路

积分
47
 楼主| 发表于 2025-5-13 15:11:19 | 显示全部楼层
不过很奇怪,看你们都是用mdma接收数据的,都没出现这种问题,难道mdma会自动交换字节吗?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-5-14 09:01:39 | 显示全部楼层
spi-sd 发表于 2025-5-13 15:11
不过很奇怪,看你们都是用mdma接收数据的,都没出现这种问题,难道mdma会自动交换字节吗?

没细看你的代码,估计配置不同吧
回复

使用道具 举报

3

主题

38

回帖

47

积分

新手上路

积分
47
 楼主| 发表于 2025-5-14 22:19:27 | 显示全部楼层
eric2013 发表于 2025-5-14 09:01
没细看你的代码,估计配置不同吧

接收的代码我没贴上来,其实就是检测输出寄存器是否有数据可以接收,如果有的话就接收4个字节,但是接收的这4个字节,写入的时候必须先写低2字节
昨天试过用mdma,数据接收是正常的,不需要转换数据。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-13 05:03 , Processed in 0.043447 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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