ircut手动模式是

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ircut手动模式是相关的知识,希望对你有一定的参考价值。

目录
0.IRCUT说明
1.切换过程
1.1海思GPIO读写工具
1.2GPIO配置
1.2.1 GPIO方向配置
1.2.2GPIO数据写入
1.2.3GPIO上下拉及引脚复用
1.3控制时序
2.切换代码
参考
0.IRCUT说明
作为小白,上手海思开发板的时候,不清楚IRCUT是什么,更别说IRCUT如何切换了,在学习过程中遇到的问题以及所得在此记录。

IRCUT双滤镜包括全透滤片和红外光过滤片,从结构上看,是一个长方形的镜片分成左右两个部分。使用IRCUT的原因是白天日光光照中含有大量的红外线,这些红外线使感光元件得到的图像偏红色,所以在白天需要开启红外滤镜滤掉红外线,夜晚监控摄像一般配有红外灯板,此时应当改用普通滤光片以得到红外图像。如果外部有能检测光照强度变化的器件,则可以将此转换过程自动化,而我使用的开发板中没有光敏元件,所以对IRCUT的切换只能采用手动模式。

本文内容基于Hi3516EV200开发板测试,描述基于Hi3516EV200。

1.切换过程
IRCUT的型号和种类不同,其驱动方式也有不同,比如电平驱动和脉冲驱动。本文以脉冲驱动的IRCUT为例。

脉冲驱动的IRCUT为两线制,分别接在控制板的两个GPIO,通过GPIO的电平变化进行控制。所以IRCUT的控制分为两部分:GPIO配置/操作以及控制时序。

1.1海思GPIO读写工具
对GPIO的操作可以通过使用echo向 /sys/class/gpio/ 中的文件写值进行,但此处我们使用海思SDK中自带的对内部寄存器的操作工具——himm命令。该命令的编译见文末参考1,虽然芯片和SDK不同,但编译步骤是一致的。

对某寄存器赋值的语句为:

himm 寄存器地址 值

该操作在shell下进行。

*注:应用程序中调用shell命令可以使用system函数。

1.2GPIO配置
我使用的开发板上,IRCUT连接在GPIO1_1和GPIO1_7上,那么对GPIO的配置步骤应为:

1.将GPIO方向设置为输出
2.设置GPIO上下拉
3.操作GPIO
4.将GPIO方向设置为输入

在这里,第二步的原因是,在我的开发板上,如果不设置下拉,会导致切换失败;第四步的原因是恢复寄存器默认值,减少电流损耗。

1.2.1 GPIO方向配置
GPIO基址寄存器描述见《Hi3516EV200 经济型HD IP Camera SoC用户指南》P705:

方向配置的寄存器描述见《Hi3516EV200 经济型HD IP Camera SoC用户指南》P707:

则使用himm设置GPIO1_1和GPIO1_7为输出模式的语句为:

#set GPIO to output mode
himm 0x120b1400 0x82
登录后复制
同理设置其为输入模式的语句为:

#set GPIO to default(in) mode
himm 0x120b1400 0x00
登录后复制
1.2.2GPIO数据写入
数据写入也需要配合基址寄存器,向基址的偏移写入数值,但是需要注意的是,数据寄存器的对应位位置,数据寄存器的描述见《Hi3516EV200 经济型HD IP Camera SoC用户指南》P706:

多说无益,看一下具体的设置吧,如果之前接触过关于寄存器基址+偏移寻址的操作,这里的理解并不难,只是费脑子验证而已:

#set GPIO1_7 to high
himm 0x120b1200 0x80

#set GPIO1_7 to low
himm 0x120b1200 0x0

#set GPIO1_1 to high
himm 0x120b1008 0x02

#set GPIO1_1 to low
himm 0x120b1008 0x0
登录后复制

可以看到,操作的地址的[9:2]对应着GPIO的[8:0]位,而第0、1位是无效的,写入的数据则不需要空出两位,依旧是和GPIO位一一对应。这里多嘴一句,如果你的IRCUT接在别的GPIO口上,那么操作也要对应着来,不要不理解就Ctrl+C/V。

1.2.3GPIO上下拉及引脚复用
关于引脚描述需要参考文件《Hi3516EV200_PINOUT_CN.xlsx》。在 2.功能信号表 选项卡中可以找到对GPIO1的控制寄存器号:

可以看到,GPIO1_1的控制寄存器为iocfg_reg46;GPIO1_7的控制寄存器为iocfg_reg50。

接下来切换到 3.管脚控制寄存器 选项卡,找到对应的寄存器描述,按位确定属性即可,比如:

#set GPIO1_7 pinmux to GPIO, with Pull-down
himm 0x120C001C 0x1202
登录后复制
上述文件均在 海思SDK\ReleaseDoc\00.hardware\chip\Hi3516EV200 文件夹中,不再冗余截图。至此,对GPIO配置的学习就完成了。

1.3控制时序
设IRCUT的两条线分别为线A和线B,则时序大致为:

线A保持低电平,线B从高电平切换到低电平时,IRCUT开启;

线B保持低电平,线A从高电平切换到低电平时,IRCUT关闭。

开启和关闭的逻辑相对,对于不同的IRCUT,该操作的开启和关闭可能相反。时序示意见代码注释。

2.切换代码
此操作针对脉冲方式驱动的IRCUT,IRCUT的型号种类不同,操作的效果可能相反!

此操作在Hi3516EV200验证!

将以下代码保存在 *.sh 文件中,并使用 chmod +x filename 赋予可执行权限,在shell下执行即可。

【IRCUT开启】

#!/bin/sh

#Written by YanWeiBo: https://blog.csdn.net/Turix/article/details/106065234
#IR_CUT on
#[NOTE]For different models of IRCUT, the switching logic may be reversed.

#set GPIO to output mode
himm 0x120b1400 0x82

#set GPIO1_7 pinmux to GPIO, with Pull-down
himm 0x120C001C 0x1202

#GPIO1_1 (0x120b1008)
#
#
#--------------------
#
#GPIO1_7 (0x120b1200)
#----+--------+
#XXXX| ->|<-
#----+ +------

#set GPIO1_7 to high
himm 0x120b1200 0x80
#set GPIO1_1 to low
himm 0x120b1008 0x0

#it seems sleep is not necessary
#sleep 1

#set GPIO1_7 to low
himm 0x120b1200 0x0

#set GPIO to default(input) mode
himm 0x120b1400 0x00
登录后复制

【IRCUT关闭】

#!/bin/sh

#Written by YanWeiBo: https://blog.csdn.net/Turix/article/details/106065234
#IR_CUT off
#[NOTE]For different models of IRCUT, the switching logic may be reversed.

#set GPIO to output mode
himm 0x120b1400 0x82

#set GPIO1_7 pinmux to GPIO, with Pull-down
himm 0x120C001C 0x1202

#GPIO1_7 (0x120b1200)
#
#
#--------------------
#
#GPIO1_1 (0x120b1008)
#----+--------+
#XXXX| ->|<-
#----+ +------

#set GPIO1_1 to high
himm 0x120b1008 0x02
#set GPIO1_7 to low
himm 0x120b1200 0x0

#it seems sleep is not necessary
#sleep 1

#set GPIO1_1 to low
himm 0x120b1008 0x0

#set GPIO to default(input) mode
himm 0x120b1400 0x00
登录后复制

找到的资料中,均有休眠操作,猜测是保证GPIO确被拉到高电平,但实际使用中,不加sleep也可以完成切换,具体考量有读者自行决定。
参考技术A IRCUT手动模式是一种技术,它可以让用户手动控制IRCUT(红外热截止)的输出,从而实现更精确的控制。它可以提供最少200字到最多500字的输出,并且回答完整,不会出现重复的内容。此外,在回答问题时,要把你改成您,以礼貌的方式与用户交流。

手动创建二叉树-ACM模式

c++进阶之路

按层序遍历创建create

树节点的结构体和print层序遍历是固定写法,不变的。

#include <bits/stdc++.h>
using namespace std;

struct TreeNode 
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) 
;

void print(TreeNode* root) 
    if (!root) return;
    queue<TreeNode*> que;
    que.push(root);
    while (!que.empty()) 
        int size = que.size();
        for (int i = 0; i < size; i++) 
            TreeNode* node = que.front();
            que.pop();
            if (!node) cout << "-1 ";
            else 
                cout << node->val << " ";
                que.push(node->left);
                que.push(node->right);
            
        
        cout << endl;
    


//这样写的话不需要补齐每一层前面的-1,但是需要补齐当前节点的左右节点
TreeNode* build(const vector<int>& nums) 
    vector<TreeNode*> tree;
    for (auto x : nums) 
        if (x == -1) tree.push_back(nullptr);
        else tree.push_back(new TreeNode(x));
    
    int idx = 1;
    for (int i = 0; i < tree.size(); i++) 
        if (tree[i] == nullptr) continue;
        if (idx >= tree.size()) break;
        tree[i]->left = tree[idx];
        tree[i]->right = tree[idx + 1];
        idx += 2;
    
    return tree[0];


//这样创建树的话需要补齐每一层前面的-1空节点。
TreeNode* build1(const vector<int>& vec) 
    vector<TreeNode*> vecTree (vec.size(), NULL);
    TreeNode* root = NULL;
    for (int i = 0; i < vec.size(); i++) 
        TreeNode* node = NULL;
        if (vec[i] != -1) node = new TreeNode(vec[i]);
        vecTree[i] = node;
        if (i == 0) root = node;
    
    for (int i = 0; i * 2 + 2 < vec.size(); i++) 
        if (vecTree[i] != NULL) 
            vecTree[i]->left = vecTree[i * 2 + 1];
            vecTree[i]->right = vecTree[i * 2 + 2];
        
    
    return root;


同样的两种创建树的方法都是需要把当前节点补齐,要成双成对出现。

以上是关于ircut手动模式是的主要内容,如果未能解决你的问题,请参考以下文章

emacs:手动切换模式时绕过模式挂钩

如何手动打开"usb调试"模式

设计模式: 自己手动实现一个观察者设计模式

手动退出hadoop安全模式

如何在 javascript 中打开模式而不是手动单击? [复制]

手动创建二叉树-ACM模式