OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8144|回复: 22
打印 上一主题 下一主题

GD32F303CCT6+OV7670+NRF24L01P=无线图像传输

[复制链接]

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
跳转到指定楼层
楼主
发表于 2023-4-18 10:17:04 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 LcwSwust 于 2023-4-18 10:41 编辑

接上一帖:“基于GD32F303CCT6的OV7670驱动
  http://www.openedv.com/forum.php?mod=viewthread&tid=342658&extra=

此次调试了接收端,图像传输已初步完成,目前帧率为1帧/秒。
而且由于每次采集1/4帧图像,在有运动物体的情况下,图像会出现“错位”。
(后期再考虑图像压缩及语音的传输)
图像为320*240像素,每像素2字节,每行640字节;
NRF地址宽度为3,CRC为1字节,
NRF打包多出部分:1前导+3地址+1.1控制+1CRC=6.1字节;
PAYLOAD为32字节(x+y+30字节图像数据);空中速度2Mbps。
每行图像:320*2/30=22包;


有效载荷:32/(32+6.1)=84%
利用FIFO:1包150us,空中速率约2.032Mbps。
1行数据约3.2ms;
(32+6.1)*22=838.2字节,838.2*8/3.25=2.063Mbps,符合配置。
60行数据约200ms;
加上等待DMA的时间,传输一幅图像(240行)约需1s。


发送端OV7670配置为RGB565模式,
发送流程:
设置好采集启始行,等待DMA采集完成,通过无线模块发出采集数据。
NRF24L01P模块流程:
初始化为发送模式,CE置高,读取TX_FULL状态位,若为0(表示TX_FIFO未满)就
将数据包写入NRF。

接收端直接将数据发给显示屏(SPI接口,2.8寸TFT,320*240)。
接收流程:
NRF24L01P初始化为接收模式,读取RX_EMPTY状态位,若为0(表示RX_FIFO有数据)
就读取数据包,送往TFT显示屏。


电路.rar (147.26 KB, 下载次数: 34)
程序.rar (9.27 MB, 下载次数: 49)









发送方核心代码:
  1. //发送一行数据,只要TX_FIFO未满就往里写
  2. void nrf_txline(U8 y,U8* buf,U16 len)
  3. {
  4.         U16 x;
  5.         U16 pn,ln;
  6.         U8 buflast[PAYLOAD_SIZE];
  7.         //---------------------------分包有余数的处理
  8.         pn=len/(PAYLOAD_SIZE-2);//完整的包数量
  9.         ln=len%(PAYLOAD_SIZE-2);//有余数(640%30=10)
  10.         for(x=0;x<ln;x++)
  11.         {
  12.                 buflast[x]=buf[pn*(PAYLOAD_SIZE-2)+x];
  13.         }
  14.         //---------------------------
  15.         NRF_CE_H;
  16.         for(x=0;x<len/(PAYLOAD_SIZE-2);x++)//每次发送PAYLOAD_SIZE-2个图像数据(因为有两字节座标)
  17.         {
  18.                 while(NRF_RwReg(CMD_R_REG+STATUS,0) & BIT(0));//TX_FULL               
  19.                 //只要TX_FIFO未满,就存入数据,可维持发送状态
  20.                 NRF_TxPld(x,y,buf+x*(PAYLOAD_SIZE-2));
  21.                 //LED_X;
  22.         }
  23.         //---------------------------分包有余数的处理
  24.         if(ln)
  25.         {
  26.                 while(NRF_RwReg(CMD_R_REG+STATUS,0) & BIT(0));//TX_FULL        
  27.                 //只要TX_FIFO未满,就存入数据,可维持发送状态
  28.                 NRF_TxPld(x,y,buflast);//发送最后一包数据
  29.                 //LED_X;
  30.         }
  31.         //---------------------------
  32.         NRF_CE_L;
  33.         LED_X;
  34. }

  35. //main()
  36.         NRF_TX_INI();//配置为发送模式
  37.         while(1)//NRF发送图像
  38.         {
  39.                 for(OV_linestart=0;OV_linestart<CAMHEIGHT;OV_linestart+=DMAHEIGHT)//每次发送320*240*2/4
  40.                 {
  41.                         OV_capend=0;
  42.                         OV_capen=1;//DMA允许采集
  43.                         while(OV_capend==0);//等待DMA采集完毕
  44.                         LED_ON;
  45.                         p=OV_DMAbuf[0];
  46.                         for(y=0;y<DMAHEIGHT;y++)
  47.                         {
  48.                                 nrf_txline(y+OV_linestart,OV_DMAbuf[y],DMAWIDTH);//发送一行图像               
  49.                         }
  50.                         LED_OFF;                                                        
  51.                 }
  52.         }        
  53.         
复制代码

接收方核心代码:
  1. NRF_RX_INI();//配置为接收模式
  2.         while(n)
  3.         {
  4.                 if((NRF_RwReg(CMD_R_REG+FIFO_STATUS,0)& BIT(0))==0)//RX FIFO非空
  5.                 {
  6.                         LED_ON;
  7.                         NRF_ReadBuf(CMD_R_RX_PAYLOAD,PAYLOAD_SIZE,RF_rxbuf);//读取数据
  8.                         NRF_RwReg(CMD_W_REG+STATUS,0xff);//清TX_DS\MAX_RT标志

  9.                         x=(U16)RF_rxbuf[0]*((PAYLOAD_SIZE-2)/2);//注意16位像素只有15点宽度
  10.                         y=RF_rxbuf[1];                        

  11.                         w=(PAYLOAD_SIZE-2)/2;//图像宽度
  12.                         if((x+w)>LCD_WIDTH)//最后一包有多余数据
  13.                                 w=LCD_WIDTH-x;
  14.                         LCD_DisBmp(x,y,w,1,RF_rxbuf+2);//数据写入显示屏
  15.                         U0TX(0xaa);
  16.                         U0TX(RF_rxbuf[0]);                        
  17.                         U0TX(RF_rxbuf[1]);        
  18.                         LED_OFF;               
  19.                 }        
  20.                
  21.         }
复制代码








专治疑难杂症
回复

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
推荐
 楼主| 发表于 2023-7-27 10:56:21 | 只看该作者
20230727:改进OV7670配置,图像看着更清晰。

程序1.1.rar (8.68 MB, 下载次数: 28)
专治疑难杂症
回复 支持 1 反对 0

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2023-7-1
在线时间
0 小时
2#
发表于 2023-7-1 22:10:31 | 只看该作者
好人一生平安
回复 支持 反对

使用道具 举报

0

主题

455

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4124
金钱
4124
注册时间
2016-3-19
在线时间
956 小时
4#
发表于 2023-7-27 13:53:28 | 只看该作者
Nothing is impossible
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
5#
 楼主| 发表于 2023-8-14 13:00:24 | 只看该作者
本帖最后由 LcwSwust 于 2023-8-14 13:02 编辑

20230814
图像经压缩后传输(非标准JPG压缩)
程序:
图传-TX2.2.rar (4.32 MB, 下载次数: 17)
图传-RX2.2.rar (4.36 MB, 下载次数: 15)
效果:

目前达到的帧率为:4fps。
图像原始数据量为320*240*2=153.6K字节,压缩后数据量约10K~17K字节。
未用于哈夫曼编码。
缺点:由于内存有限,320*240图像分为5份传输,运动画面会出现“错位”现像,
且无线数据若有丢包,则该份画面会被丢弃。
//---------------------------------------------------------
发送端程序流程:320*240像素的图像分为5等份,每份320*48像素.
1.摄像头初始化为QVGA(320*240),YUV模式;(数据为Y1、U、Y2、V)
2.开启DMA采集320*48像素数据到OV_DMAbuf(OV7670.C);
3.NRF24L01P发送JPG_Buf1;(nrf_txjpg1,利用IRQ脚及状态机,降低CPU占用)
4.DMA采集完成后对OV_DMAbuf进行压缩(myjpg1.2.c,ImgComp),压缩后数据存入JPG_Buf;
(压缩期间也在调用nrf_txjpg1)。
5.NRF24L01P发送JPG_Buf1完成后,将JPG_Buf的数据复制到JPG_Buf1;
回到第2步;5次循环为一帧图像。
//---------------------------------------------------------
接收端程序流程:
1.利用NRF_IRQ脚触发中断,读取数据存入JPG_Buf1,接收到完整的JPG文件后,置标志flag_dec;
2.主循环检测到flag_dec标志后,复制JPG_Buf1到JPG_Buf,对JPG_Buf解码,解码后的数据通过DMA发送到显示屏;
//---------------------------------------------------------
图像压缩过程(TX2.2,main.c,ImgComp):
由于摄像头可配置为YUV模式,所以就不需要RGB转YUV的过程了。
1.DMA采集YUV数据;
2.取出8*8的Y1数据,压缩后存入JPG_Buf;
3.取出8*8的U数据,压缩后存入JPG_Buf;
4.取出8*8的Y2数据,压缩后存入JPG_Buf;
5.取出8*8的V数据,压缩后存入JPG_Buf;
//---------------------------------------------------------
压缩算法(myjpg1.2.c):
1.DCT变换(dctconv,二维DCT变为两个方向的一维DCT);
2.DCT变换结果量化并Z形排列(zidctconv,便于更多的0挨在一起);
3.变长编码,存入JPG_Buf(JPG_comp);
//---------------------------------------------------------
变长编码原理(myjpg1.2.c,JPG_comp)
变长编码由2位的码长和3~10位数据构成。
码长(2b)  数据(3b~10b)
0b00        3b,表示块结束或0的个数;
               0b000表示块结束,0b001表示1个0,0b111表示7个0。
0b01        3b,VLI编码,表示数据范围:-1~ 4,1~4;
               0b100=-4,0b111=-1,0b000=1,0b011=4;
0b10        5b,VLI编码,表示范围:-20~ -5,5~20;
               0b1 0000=-20,0b1 1111=-5,0b0 0000=5,0b0 1111=20;
0b11        10b,VLI编码,表示范围:-532~-21,21~532;
               0b10 0000 0000=-532,0b11 1111 1111=-21,
               0b00 0000 0000=21,0b01 1111 1111=532;

注:DC系数固定10位数据,不需要“码长”。
//---------------------------------------------------------
解压过程(RX2.2,main.c,img_decomp):
1.解压8*8的Y1数据;
2.解压8*8的U数据;
3.解压8*8的Y2数据;
4.解压8*8的U数据;
5.YUV转RGB,通过DMA发送至显示屏;
//---------------------------------------------------------
解压算法
1.读取变长编码数据到zdctbuf(JPG_decomp);
2.逆Z形排列、反量化、并进行IDCT变换(zidctconv);
//---------------------------------------------------------
两个程序,采用C++Builder6编写:
串口上位机:串口绘图1.6A
串口绘图1.6A.rar (777.56 KB, 下载次数: 17)

压缩解压算法验证:图像压缩1.3E
图像压缩1.3E.rar (624.79 KB, 下载次数: 10)

//---------------------------------------------------------
参考资料:
参考资料.rar (4.81 MB, 下载次数: 7)
JPEG压缩算法步骤原理
https://blog.csdn.net/yh13572438258/article/details/122346883
JPEG图像编码(详细过程)
https://blog.csdn.net/weixin_44862382/article/details/116541216
经典算法,yuv与rgb互转,查表法,让你的软件飞起来
https://blog.csdn.net/weixin_30731305/article/details/96267624
快速逆离散余弦变换代码实现(FIDCT)
https://www.iteye.com/blog/oraclestudy-1223686
探讨JPEG:IDCT
https://blog.csdn.net/lpr_pro/article/details/4472063






专治疑难杂症
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2019-9-4
在线时间
31 小时
6#
发表于 2023-8-17 00:22:57 | 只看该作者
请问楼主有没有测试这个传输距离最大是多少?
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
7#
 楼主| 发表于 2023-8-17 12:24:48 | 只看该作者
mcuboy 发表于 2023-8-17 00:22
请问楼主有没有测试这个传输距离最大是多少?

由于空中波特率为2Mbps,两米外就有丢包,最大距离估计10米左右吧。
想要距离远,可以降低空中波特率,1Mbps,250kbps(NRF24L01+),后面有空再试试,目前正在调试音频传输。
专治疑难杂症
回复 支持 反对

使用道具 举报

1

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
184
金钱
184
注册时间
2021-10-17
在线时间
64 小时
8#
发表于 2023-9-18 00:55:36 | 只看该作者
楼主,我是需要用两块NRF24L01单向传输100K字节左右的数据,现在遇到的问题是,接收端接收速率(大概只有20K字节1秒)跟不上发送的速率,导致只能收到一半左右的数据,请问你是怎么提高接收的速率的?
回复 支持 反对

使用道具 举报

1

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
184
金钱
184
注册时间
2021-10-17
在线时间
64 小时
9#
发表于 2023-9-18 01:00:15 | 只看该作者
我手上用的是f1c8t6,两端速率也设置的是2Mbs,也有对比过你的配置,没有太大的差别。
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
10#
 楼主| 发表于 2023-9-22 13:59:16 | 只看该作者
本帖最后由 LcwSwust 于 2023-9-22 14:04 编辑
l666l 发表于 2023-9-18 00:55
楼主,我是需要用两块NRF24L01单向传输100K字节左右的数据,现在遇到的问题是,接收端接收速率(大概只有20 ...

报歉未收到通知,刚打开帖子才看到消息,接收端关闭自动应答,开启接收中断,单片机检测到中断就读数据清中断标志就行。

若实在无法解决,建议发个帖子,我们探讨一下。
专治疑难杂症
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
11#
 楼主| 发表于 2023-9-22 14:02:45 | 只看该作者
本帖最后由 LcwSwust 于 2023-9-22 14:18 编辑

20230922更新:1.增加了音频传输功能<gd32_adc.c>
  ADC0.8检测MIC信号,T1.1(20KHz)触发,DMA0.0循环模式采集。
  音频压缩采用"增量调制",音质较差,见主程序 nrf_txwav(void):
    主要流程:数字低通滤波、去直流、AGC、增量调制;
    压缩率:1个采样点压缩为1位;对于NRF24L01P来说,只需11ms左右发一包数据即可。
2.图像方面的改进:
  DMA采集OV7670图像后,每8行压缩为一个小JPG文件进行打包,改善在信号差时的表现。

增加音频传输程序.rar (9.32 MB, 下载次数: 3)








专治疑难杂症
回复 支持 反对

使用道具 举报

1

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
184
金钱
184
注册时间
2021-10-17
在线时间
64 小时
12#
发表于 2023-9-22 15:59:35 | 只看该作者
LcwSwust 发表于 2023-9-22 13:59
报歉未收到通知,刚打开帖子才看到消息,接收端关闭自动应答,开启接收中断,单片机检测到中断就读数据清 ...

已发,求大佬救救
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
13#
 楼主| 发表于 2023-10-24 09:32:37 | 只看该作者
20231024更新
增加信号图标、电量图标、菜单显示、自动清屏、图像变化报警功能。
增加菜单程序.rar (9.45 MB, 下载次数: 9)


专治疑难杂症
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
14#
 楼主| 发表于 2023-11-9 17:12:15 | 只看该作者
本帖最后由 LcwSwust 于 2023-11-9 17:27 编辑

20231109更新
通过超频让无线图像传输帧率达到8帧每秒;
程序的主要改动:
1.MCU超频,改"system_gd32f30x.c",设置频率到240MHz。
2.控制OV7670的0x2A、0x2B寄存器降低帧率,降至8fps左右。
3.修改OV7670图像采集时序,通过双缓冲(每个缓冲为8行数据)不间断DMA采集,
采集的同时进行压缩(ImgComp,存入环形队列)、无线传输(nrf_txjpg_q读取环形队列);
得到的图像就不会像以前那样在转动摄像头时柱子变阶梯,
  现在的图像在转动摄像头时柱子只是会变斜一点。
4.修改音频数据增量调制的时序,在“OV_flagok[id]=0;”之后
   处理音频增量调制dlt_pro(),在nrf_txjpg_q()中发送数据。

注意:
1.超频后单片机的可靠性不能保证。
2.程序中的注释有大部分数据是超频前的数据,有些注释不一定正确,
代码较乱,待有空时慢慢整理。

程序.rar (9.6 MB, 下载次数: 13)


专治疑难杂症
回复 支持 反对

使用道具 举报

1

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
71
金钱
71
注册时间
2022-2-14
在线时间
24 小时
15#
发表于 2024-1-23 10:17:47 | 只看该作者
LcwSwust 发表于 2023-11-9 17:12
20231109更新
通过超频让无线图像传输帧率达到8帧每秒;
程序的主要改动:

学习学习
回复 支持 反对

使用道具 举报

0

主题

34

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1551
金钱
1551
注册时间
2020-3-1
在线时间
315 小时
16#
发表于 2024-2-2 20:14:59 | 只看该作者
楼主厉害呀,还可以这样玩,如果换大内存芯片,速度更高点的芯片,是不是就基本上能满足30帧要求?
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
17#
 楼主| 发表于 2024-2-3 09:06:25 | 只看该作者
本帖最后由 LcwSwust 于 2024-2-3 09:08 编辑
cooleaf 发表于 2024-2-2 20:14
楼主厉害呀,还可以这样玩,如果换大内存芯片,速度更高点的芯片,是不是就基本上能满足30帧要求?

目前的情况是这样:
一帧图像原始数据量为320*240*2=153.6K字节,压缩后数据量约10K~17K字节;
NRF24L01P空中波特率2Mbps,就是每秒250K字节;
250/17=14.7帧每秒;250/10=25帧每秒;
再考虑到打包、音频数据的消耗,单片机性能足够的情况下,估计能做到12~20帧每秒;
也就是说,受限于空中波特率、压缩比,保守估计就是12帧每秒的帧率。
若想要达到30帧,可能需要空中波特率更高的模块或改进压缩算法减小数据量。
专治疑难杂症
回复 支持 反对

使用道具 举报

19

主题

79

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2023-5-13
在线时间
33 小时
18#
发表于 2024-8-27 11:07:08 | 只看该作者
很感谢!!!学习啦!!!!
回复 支持 反对

使用道具 举报

19

主题

79

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2023-5-13
在线时间
33 小时
19#
发表于 2024-8-31 11:39:36 | 只看该作者

楼主 您好 我在阅读您的程序中有两个疑问想咨询您一下:
1,NRF配置的是7个字节的地址,不应该正常来说地址的字节数是5个字节吗?请问为什么配置7个呢?
2,NRF中的频道是做什么用的?为什么要用到频道呢?之前我做的时候是直接设置的收发地址建立的通讯 没有考虑到这一点 所以想咨询您一下

123.png (39.5 KB, 下载次数: 510)

123.png
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
20#
 楼主| 发表于 2024-8-31 11:54:24 | 只看该作者
启林 发表于 2024-8-31 11:39
楼主 您好 我在阅读您的程序中有两个疑问想咨询您一下:
1,NRF配置的是7个字节的地址,不应该正常来说 ...

1. 7个只是定义了一个数组有7字节,并不是全用作地址;
实际还要看SETUP_AW寄存器的设置,虽对TX_ADDR写入5字节,但配置的是3字节地址。
程序是从我做的一个遥控器移植过来,涉及“对码”,刚好单片机有7字节的唯一ID,可以用来当地址,除了5字写入TX_ADDR外,还用了数据包PAYLOAD中的两字节当作地址。
2. 频道当然有用,和电视机频道一样,频道一致才能通信。
当时做遥控器时考虑到某个频道万一有多个设备同时发送就会有干扰,就需要跳频。
这里传图像未作跳频处理。

专治疑难杂症
回复 支持 反对

使用道具 举报

19

主题

79

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2023-5-13
在线时间
33 小时
21#
发表于 2024-8-31 14:17:12 | 只看该作者
LcwSwust 发表于 2024-8-31 11:54
1. 7个只是定义了一个数组有7字节,并不是全用作地址;
实际还要看SETUP_AW寄存器的设置,虽对TX_ADDR ...

收到 谢谢博主解答 我再学习下您的程序 非常感谢
回复 支持 反对

使用道具 举报

1

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2017-8-9
在线时间
61 小时
22#
发表于 2025-8-11 19:50:06 | 只看该作者
楼主,您好,能加个联系方式吗?有偿求助下
回复 支持 反对

使用道具 举报

13

主题

3475

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8980
金钱
8980
注册时间
2020-5-11
在线时间
4550 小时
23#
 楼主| 发表于 2025-8-12 09:09:13 | 只看该作者
zhang313957217 发表于 2025-8-11 19:50
楼主,您好,能加个联系方式吗?有偿求助下

QQ:0x1ACCCF77
建议还是在这里问比较好,比如其它坛友有相同问题的也就比较方便学习。
专治疑难杂症
回复 支持 反对

使用道具 举报

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

本版积分规则


关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-12-13 12:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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