文章目录[隐藏]
第一章:简介
1.1 开发环境
USB摄像头型号:100w前置摄像头
主机型号:野火霸天虎开发版
外设:USB-HOST接口:连接USB摄像头设备
外部Sram:存放USB摄像头数据
LCD屏幕:显示图像数据
- 第二章、UVC获得摄像头数据的过程
2.1 UVC枚举过程
当USB设备连接的时候,主机采用总线枚举过程来识别和管理接入的设备。并安装下面顺序进行行动:
- 设备上电
用户把USB设备插入USB端口,此时USB设备除于加点状态,他所连接的端口是无效的。
(2)Hub检测电压变化,报告主机hub会实时监测端口的电平变化,一旦HUB检测到端口有电压变化,hub将利用自己的中断端点将信息反馈给主控制器,告诉主机有设备连接。
(3)主机了解连接设备
如果有连接/断开事件发生,那么主机会发送一个 Get_Port_Status请求给hub以了解此次状态改变的确切含义。Get_Port_Status等请求属于所有hub都要求支持的hub类标准请求。
4.主机检测所插入的设备是全速还是低速
hub通过检测USB总线空闲时的差分线的高低电压来判断所连接设备的速度类型,当host发来Get_Port_Status请求时,hub就可以将此设备的速度类型信息回复给host。USB 2.0规范要求速度检测要先于复位(Reset)操作。
根据是D+还是D-被拉高来判断到底是什么设备(全速/低速)插入端口。如下图。
(5)主机通过hub复位设备
主机一旦得知新设备已连上以后,它至少等待100ms以使得插入操作的完成以及设备电源稳定工作。然后主机控制器就向hub发出一个 Set_Port_Feature请求让hub复位刚才设备插上的端口。hub通过驱动数据线到复位状态(D+和D-全为低电平 ),并持续至少10ms。当然,hub不会把这样的复位信号发送给其他已有设备连接的端口,所以其他连在该hub上的设备自然看不到复位信号,不会受影响。
(6) 主机进一步检测全速设备是否是支持高速模式
因为根据USB 2.0协议,高速(High Speed)设备在初始时是默认全速(Full Speed )状态运行,所以对于一个支持USB 2.0的高速hub,当它发现它的端口连接的是一个全速设备时,会进行高速检测,看看目前这个设备是否还支持高速传输,如果是,那就切到高速信号模式,否则就一直在全速状态下工作。同样的,从设备的角度来看,如果是一个高速设备,在刚连接到hub时或上电只能用全速模式运行。随后hub会进行高速检测,之后这个设备才会切换到高速模式下工作。假如所连接的hub不支持USB 2.0,即不是高速hub,不能进行高速检测,设备将一直以全速工作。
(7)通过Hub建立主机和设备之间的信息通道
主机不停地向hub发送Get_Port_Status请求,以查询设备是否复位成功。Hub返回的报告信息中有专门的一位用来标志设备的复位状态。当hub撤销了复位信号,设备就处于默认/空闲状态(Default state),准备接收主机发来的请求。设备和主机之间的通信通过控制传输管道,默认管道为地址0、端点0。此时,设备能从总线上得到的最大电流是100mA。此后主机就可以通过默认控制管道和设备进行控制传输。
(8)主机获取默认控制管道的最大数据包长度
默认管道其实连接到设备一端其实就是端点0。主机此时发送的请求是默认地址0,端点0,虽然所有未分配地址的设备都是通过地址0来获取主机发来的请求,但由于枚举过程不是多个设备并行处理,而是一次枚举一个设备的方式进行,所以不会发生多个设备同时响应主机发来的请求。
主机会发送Get_Descriptor获取设备描述符,设备描述符的第8字节代表设备端点0的最大包大小,只有知道端点0 的最大包长度,才知道一次控制传输要从设备请求多少字节数据。
(9)主机收到设备描述符后,返回一个0长度的数据确认包。
(10)主机对设备再次复位,复位后主机对地址为0的设备端点0发送一个设置地址SetAddress请求(新的设备地址在数据包中)。
(11)主机发送请求状态返回,设备返回0长度的状态数据包。
(12)主机收到状态数据 包后,发送应答包ACK给设备,设备收到ACK后,启用新的设备地址。
(13)主机再次使新的地址获取设备描述符GetDescriptor,设备返回地址描述符。上图描述此步动作
(14)主机获取第一次配置描述符有前18个字节,设备返回配置描述符的前18个字节,其数据包中含有配置描述符的总长度。
(15)主机根据配置描述符的总长度再次获取配置描述符,设备返回全总的配置描述符,此时就可以根据获得的设备描述符进行分析判断。《USB设备描述符》有对各类描述符的描述。
(16)如果还有字符串描述符,系统还会获取字符串描述符。像HID设备还有报告描述符,它也需要单独获取。
2.2 获取数据过程
该过程主要是进行摄像头数据帧格式进行选择,以及选择分辨率和设置FPS,同时进行数据最大获取值(由分辨率决定)和数据的一帧可以最多获得多少。需要注意,UVC1.0的描述有26个字节,UVC1.1的描述符有34个字节,UVC1.5的描述符有48个字节。
(1)先进行SET_CUR设置分辨率,帧格式,FPS和数据最大获取值以及一帧的最大值。
21:表示设置接口数据
01:表示SET_CUR
00 01:高位为01,低为为00,表示视频流控制接口选择子CS的VS_PROBE_CONTROL请求。
01 00:表示接口01,表示发向的是视频流接口(通过上节可知,视频控制接口VC为0,视频流接口VS为01)。
1a 00 :表示接收数据长度为26个字节。
设置的值中
01 00:参照视频流控制接口,dwFrameInterval=1,指定在视频流传输过程中帧速率不变。
01:bFormatIndex=1,表示视频流格式为1,为YUY2.
03:bFrameIndex=2,表示分辩率为 176*144。
15 16 05 00:0x051615=333333百纳秒,即33.3333ms,即帧间隔为33ms.
00 00:即wKeyFrameRate=0x0000,即只有第一帧是关键帧。
00 00:wPFrameRate=0x0000
00 00:wCompQuality=00
00 00 :wCompQuality=00
00 00:wDelay=00,内部视频流接口延迟(毫秒).
00 00 00 00:dwMaxVideoFrameSize
00 00 00 00 :dwMaxPayloadTransferSize
(2)GET_CUR 获得一系列的配置。
a1:表示获取接口数据
81:表示GET_CUR
00 01:高位为01,低为为00,表示视频流控制接口选择子CS的VS_PROBE_CONTROL请求。
01 00:表示接口01,表示发向的是视频流接口(视频控制接口VC为0,视频流接口VS为01)。
1a 00 :表示接收数据长度为26个字节。
00 00:参照视频流控制接口,dwFrameInterval=0未进行任何设置
01:bFormatIndex=1,表示视频流格式为1,为YUY2.
00:bFrameIndex=2,表示分辩率为 176*144。
0F 42 40 00:0x0f4240=1000000百纳秒,即100ms,即帧间隔为100ms.
00 00:即wKeyFrameRate=0x0000,即只有第一帧是关键帧。
00 00:wPFrameRate=0x0000
00 00:wCompQuality=00
00 00 :wCompQuality=00
00 00:wDelay=00,内部视频流接口延迟(毫秒).
00 00 C6 00:dwMaxVideoFrameSize 177*144*2
00 00 03 BC :dwMaxPayloadTransferSize 一帧最大的传输数据大小
(3)SET_CUR这里改变了选择子,使用了VS_COMMIT_CONTROL选择子,提交上面的参数,以激活视频流接口,表示开始传递数据。
21:表示获取接口数据
01:表示SET_CUR
00 02:高位为02,低为为00,表示视频流控制接口选择子CS的VS_COMMIT_CONTROL请求。
01 00:表示接口01,表示发向的是视频流接口(视频控制接口VC为0,视频流接口VS为01)。
(4)SET INTERFACE
视频流接口需要使用端点0X81来读取数据,但此接口处于视频流接口1的转换接口1中
完成上述的操作以后就可以进行摄像头的数据传输了,但是判断一帧的方式可以通过判断负载描述符中第二个字节中的第二位进行判断,同时也可以通过接收的字符数据的长度和一张图片的数据长度进行对比从而得出是否接收完一张图片的数据。
在此特别感谢USB中文网的站长,给了我很多指引,如果要搞UVC或者USB的设备类,可以去http://www.usbzh.com/article/forum-12.html这个网站上,先把上面的概念知识搞懂,会对你完成驱动有很大的帮助的!
代码是在这个https://github.com/iliasam/STM32_HOST_UVC_Camera下面进行更改的,移植到霸天虎上调试完成的,需要注意的就是分辨率是否支持,要看USB摄像头上支持哪几个分辨率进行选择。
版权声明:本文为CSDN博主「MTPPZ」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MTPPZ/article/details/119568672
暂无评论