记一次和摄像头的摩擦经历
因為時間的原因,這次點亮攝像頭的時間特別短,昨天下午模組到公司,今天下午點亮。
幾個人一起調試,發現的問題也很多,今天下午發現有一個懷疑的問題,我馬上驅車幾十公里去模組廠調試,回來的時候,同事已經把攝像頭點亮了。時間雖然很短,但是我覺得應該把排查的問題點總結一下,避免下次調試攝像頭的時候遇到同樣的問題。
也希望大家看了我的文章后,如果遇到調試攝像頭相關的工作,可以迎刃而解。
#模組供電電壓
模擬供電電源可以理解為里面有ADC轉換相關的電路,需要一個基準電壓,這個就是模擬電源電壓。
IOVDD ,這個是I2C通信的GPIO口電壓,有的GPIO口電壓是3.3V,而攝像頭芯片的IOVDD是1.8V,就需要轉換電路把電壓轉換成1.8V。
DVDD 是數字電壓這個需要按照模組規格書提供正確供電。
這三路電壓是供電要求,一定要按照攝像頭模組設計要求。
3.3V轉1.8V的電路復位腳和PWDN腳電平轉換電路
#時鐘MCLK
攝像頭模組里面是有芯片的,有芯片就需要有時鐘,沒有時鐘的芯片是不能工作的。就好像一個人,沒了心跳的話也是不能正常工作的。
時鐘這個問題非常關鍵,我們剛開始有點忽略時鐘的問題。實話說,我也很長時間沒有調試攝像頭了。我2013年在ZTE調過攝像頭,到現在也已經很長時間了,經驗這個東西還是很有必要的。但是排除經驗的話,就是基礎的問題了。沒有基礎的話,根本就不知道其中的原因,只知道需要這個,卻不知道為什么需要這個,知所以,但不知所以然。
但是這個時鐘是什么時候產生也是很有必要說明的,我跟硬件溝通,這個時鐘硬件是直接從CPU連接出來的,中間就加了一個電阻。但是我們開機后還是量不到MCLK。所以這部分應該是軟件問題。
從軟件流程上可以看出,在開機的時候,我們會打開MCLK,然后去讀CHIP ID,如果讀到ID,就保持MCLK打開狀態,如果讀不到,就退出關閉MCLK。所以在開機后去測量MCLK是有可能量不到的。
MCLK在dts里面設置如下
gc5025: gc5025@37 {status = "okay";compatible = "galaxycore,gc5025";reg = <0x37>;clock-frequency = <400000>;pinctrl-names = "default";pinctrl-0 = <&cif_clkout_m0>;clocks = <&cru SCLK_CIF_OUT>;clock-names = "xvclk";avdd-supply = <&vcc2v8_dvp>;dovdd-supply = <&vcc1v8_dvp>;dvdd-supply = <&vdd1v2_dvp>;reset-gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>;pwdn-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;rockchip,camera-module-index = <0>;rockchip,camera-module-facing = "front";rockchip,camera-module-name = "CMK-CW4191-FG1";rockchip,camera-module-lens-name = "CK5502";port {ucam_out: endpoint {remote-endpoint = <&mipi_in_ucam>;data-lanes = <1 2>;};};};對應的dts位置
cif_clkout_m0: cif-clkout-m0 {rockchip,pins = <2 RK_PB3 RK_FUNC_1 &pcfg_pull_none_12ma>;/* cif_clkout */};這個GPIO口對應原理圖我們開機后會打開MCLK,然后讀取CHIP ID。如果讀不到呢?就會關閉MCLK。看看代碼 獲取DTS里面的配置設置MCLK
gc5025->xvclk = devm_clk_get(dev, "xvclk");if (IS_ERR(gc5025->xvclk)) {dev_err(dev, "Failed to get xvclk\n");return -EINVAL;}ret = clk_set_rate(gc5025->xvclk, GC5025_XVCLK_FREQ);if (ret < 0) {dev_err(dev, "Failed to set xvclk rate (24MHz)\n");return ret;}if (clk_get_rate(gc5025->xvclk) != GC5025_XVCLK_FREQ)dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");如果沒有讀到CHIP ID 會進入這里
static void __gc5025_power_off(struct gc5025 *gc5025) {int ret;if (!IS_ERR(gc5025->pwdn_gpio))gpiod_set_value_cansleep(gc5025->pwdn_gpio, 1);clk_disable_unprepare(gc5025->xvclk);if (!IS_ERR(gc5025->reset_gpio))gpiod_set_value_cansleep(gc5025->reset_gpio, 1);if (!IS_ERR_OR_NULL(gc5025->pins_sleep)) {ret = pinctrl_select_state(gc5025->pinctrl,gc5025->pins_sleep);if (ret < 0)dev_dbg(&gc5025->client->dev, "could not set pins\n");}regulator_bulk_disable(GC5025_NUM_SUPPLIES, gc5025->supplies); }里面有一句
clk_disable_unprepare(gc5025->xvclk);就是用來關閉時鐘的。
如果時鐘不是問題,那就是其他的問題了,我們開機后,打開時鐘,讀取CHIP ID,讀不到后,就關閉時鐘。讀不到的原因就應該從其他地方排查了。
#上電時序
上電時序是很重要的,做單片機的同學應該都有調時序的經驗。每個芯片都有自己的脾氣,有的芯片對時序嚴格,有的對時序不夠嚴格。但是如果通信不成功。就需要排查這方面的問題。
GC5025要求的上電時序是。三路電開啟后,MCLK開啟后,需要先拉高PWDN,再拉高reset腳。我們正好在這個問題上做錯了。修改后的代碼如下
#異常問題
還沒調通前,我們攝像頭在開機后,我使用命令「如下圖」讀寫I2C寄存器0x37 是手冊上寫的 GC5025 的器件地址。但是用這個地址是讀不出內容的。但是我把器件地址修改成0x24,卻能看到應答信號,而且讀寄存器都能正常成功。
你們可能想知道我是如何找到這個0x24的,因為我寫了一個腳本。
@echo off setlocal ENABLEDELAYEDEXPANSION set /a ii=3 for /l %%i in (1,1,116) do ( echo "adb shell i2cget -y -f 2 !ii! 0xf0 w" adb shell "i2cget -y -f 2 !ii! 0xf0 w" set /a ii+=1 ) pause還有i2c-tools的鏈接 https://github.com/weiqifa0/i2c-tool
今天去模組廠的一個原因就是因為這個問題,為什么我寫0x37的器件地址,芯片沒有應答。但是我寫0x24的器件地址,芯片有應答信號。這真的是百思不得姐啊。
正常I2C有應答的波形
調通后,我想了下,這個現象剛好說明了。因為沒有正常的上電時序,芯片里面也沒有正常工作了。而且這個不正常工作還讓我懷疑這個芯片是不是壞掉了。
#總結
看看深圳的夜景
? 回復「?籃球的大肚子」進入技術群聊
回復「1024」獲取1000G學習資料
總結
以上是生活随笔為你收集整理的记一次和摄像头的摩擦经历的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给你准备的Linux启动流程
- 下一篇: 实现华为多屏协同--非华为电脑下载12.