本科生进化 2023-07-19 17:55 采纳率: 33.3%
浏览 37

K210读取SD卡里的文件

想要实现K210读取SD卡里的文件,在官网上没有找到解决方案,请帮帮忙,现在没有一点头绪

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-07-19 20:56
    关注
    • 关于该问题,我找了一篇非常好的博客,你可以看看是否有帮助,链接:咸鱼K210体验笔记—环境配置及固件安装
    • 除此之外, 这篇博客: k210 C语言开发-4 从sd卡读取播放烟花视频中的 k210 C语言开发-4 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    • 先上成果图吧,祝大伙新年快乐!
      请添加图片描述
      B站原视频。完整代码在文末。
      前天无意中看到CSDN有个活动,我一看只要是和烟花相关的都可以,然后我就准备用k210播放个烟花视频。结果我哼哧哼哧整完了之后,发现这个活动是要用代码来实现放烟花,文不对题了属于是。。。唉,记录一下过程吧。

      大体思路就是把视频文件转换成二进制文件放到SD卡中,然后单片机读取用LCD播放。
      在之前已经实现了k210使用LCD以及sd卡
      老样子,先把需要的文件整合一下:
      在这里插入图片描述
      发现原先的LCD和SD卡都用的spi0接口.所以要在代码里改下接口。
      K210是具有FPIOA(现场可编程IO阵列),我们可以将 255 个内部功能映射到芯片外围的 48 个自由 IO 上。所以说我们可以把一些引脚的功能改了,比如原本接SD卡的是spi0,现在可以改成spi1。

      void io_mux_init(void) {
        fpioa_set_function(27, FUNC_SPI1_SCLK);
        fpioa_set_function(26, FUNC_SPI1_D1);
        fpioa_set_function(28, FUNC_SPI1_D0);
        fpioa_set_function(29, FUNC_SPI1_SS3);
      }
      

      还有原本这些都调用的spi0也要都改成1.
      在这里插入图片描述
      这些都在一个sdcard.c文件里,把SPI_DEVICE_0全部替换为SPI_DEVICE_1就行了。
      然后测试一下,可以正常输出就行。
      那现在就是先实现一个把一张图片转换成bin文件放到sd卡里,然后读bin文件用LCD显示。
      我测试时用的这个图片,我觉得清晰的颜色可以比较容易看到一些问题
      请添加图片描述
      取模软件用的是Image2Lcd,这个软件功能很全。
      打开图片,输出数据类型选二进制,,输出灰度选择16位真彩色,然后根据屏幕大小选择输出的形状,在软件的下方就显示了输入输出图像的形状。
      扫描的方式很重要,我在这里反复弄了几次。
      首先我先确定了我的屏幕在DIR_XY_LRDU方向下输入扫描方向是这样的:
      在这里插入图片描述
      所以我的图片取模的方向也要是这个顺序,Image2Lcd这个软件在左上方显示了当前设置下的扫描方式
      在这里插入图片描述
      注意不要包含图像头数据,这样方便我们读取。
      用读卡器把转换后的bin文件放到SD卡里。
      用f_read()来读取,十六位真彩色下,每个像素用2个字节来表示,所以总的字节数是3202402=153,600。

      ret = f_read(&file, (void *)v_buf, 320 * 240 * 2, &v_ret_len);
      

      然后我去看了下库里的LCD显示图片函数,发现它居然要我放个uint32_t类型的数组

      void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height,
                            uint32_t *ptr) {
        lcd_set_area(x1, y1, x1 + width - 1, y1 + height - 1);
        tft_write_word(ptr, width * height / 2, lcd_ctl.mode ? 2 : 0);
      }
      

      可是这个小屏幕一个像素点只需要uint16_t就够了啊。
      后来我发现它用一个uint32_t来显示两个像素,我也不明白为啥要这样设计,不过反正我直接读取的是uint8_t都要转换一下,也就无所谓了。
      那么现在就是把4个字节拼成一个uint32_t来显示两个像素。

            for (int n = 0; n < 320 * 240 / 2; n++) {
              img_buf[n] = (v_buf[4 * n] << 24) | (v_buf[4 * n + 1] << 16) |
                           (v_buf[4 * n + 2] << 8) | v_buf[4 * n + 3];
            }
      

      然后

      lcd_draw_picture(0, 0, 240, 320, img_buf);
      

      在这里插入图片描述
      这个图片是错的,因为当时没调整扫描方向。
      现在基本成功一大半了,理论上来说循环播放图片就是视频了。
      把视频从B站上下载下来,up在评论区给了百度网盘的链接,嫌下载速度慢的话,油猴插件和IDM了解一下。
      然后就是视频转换与裁切,这些在线转换工具百度一搜就有。
      整完之后就是这样的:
      在这里插入图片描述
      把这个放到PotPlayer里获得每一帧的图片。
      先设置为无边框尺寸
      在这里插入图片描述
      然后选择连续截图:
      在这里插入图片描述
      选择截图的方式,帧率

      在这里插入图片描述
      注意,由于是用截图的方式获得图片的所以要用无边框以及在点击开始时视频是要处于播放状态的。
      然后就得到了一个有很多帧图像的文件夹了
      在这里插入图片描述
      拿一张图片出来显示显示试试:
      在这里插入图片描述
      不错不错,接着在用Image2Lcd来批量取模,取模后的文件就放在帧图像的文件夹里。
      点开后是很多个bin文件,我们需要将它们合并成一个bin文件。
      方法很多,我用的是linux的cat指令。
      在WSL下,cd到那个bin文件夹
      在这里插入图片描述
      用 cat指令合成就行
      在这里插入图片描述
      现在这个vedio.bin文件就是这个视频的所有数据了。
      前面已经实现了一张图片的显示,现在就是一个for循环的事了

      for (uint32_t i = v_fileinfo.fsize / (320 * 240 * 2); i > 0; i--) {
            ret = f_read(&file, (void *)v_buf, 320 * 240 * 2, &v_ret_len);
            if (ret != FR_OK) {
              printf("Read %s err[%d]\n", path, ret);
            } else {
              // printf("Read :> %d %d bytes lenth\n", v_buf, v_ret_len);
            }
      
            for (int n = 0; n < 320 * 120; n++) {
              img_buf[n] = (v_buf[4 * n] << 24) | (v_buf[4 * n + 1] << 16) |
                           (v_buf[4 * n + 2] << 8) | v_buf[4 * n + 3];
            }
      
            lcd_draw_picture(0, 0, 240, 320, img_buf);
            // 加地址偏移
            img_offset += 320 * 240 * 2;
            ret = f_lseek(&file, img_offset);
      
            if (ret != FR_OK) return -3;
            // printf("%d\n", v_buf[0]);
            // printf("%d\n", v_buf[1]);
            // printf("%d\n", img_buf[0]);
            // printf("%d\n", img_buf[70100]);
          }
      

      大功告成
      最后放上完整代码:代码
      设置的0积分,应该可以直接下载吧。

    评论

报告相同问题?

问题事件

  • 创建了问题 7月19日

悬赏问题

  • ¥60 中金求boss直聘注册起号秒过用那种执照,电子营业执照有没有渠道
  • ¥15 关于#vue.js#的问题:word excel和ppt预览问题语言-javascript)
  • ¥15 Apache显示系统错误3该如何解决?
  • ¥30 uniapp小程序苹果手机加载gif图片不显示动效?
  • ¥20 js怎么实现跨域问题
  • ¥15 C++dll二次开发,C#调用
  • ¥15 请教,如何使用C#加载本地摄像头进行逐帧推流
  • ¥15 Python easyocr无法顺利执行,如何解决?
  • ¥15 为什么会突然npm err!啊
  • ¥15 java服务连接es读取列表数据,服务连接本地es获取数据时的速度很快,但是换成远端的es就会非常慢,这是为什么呢