外部中断的按键,软件滤波实现方法

按键分为机械按键和触摸按键,每种按键都有不同程度的抖动。
这里我们来说下机械按键吧,新手都会接触到。我用的板子是MSP430G2553 的那块红色的板子做的。
上面的独立按键有一个,接在P13口上,我自己制作了一个LCD5110的转接板,渣手工。
下面讨论我们的重点,按键。
对于机械按键,抖动的原因是因为刚性接触时候会发生碰撞之类的,所以并不是可靠地接触,所以会产生抖动,那么我们的软件就要进行滤波。
那么我们要怎么做呢?
一般的方法是进行延时,就是等待,Delay(...)大家估计不陌生。但是这样做的结果是CPU的可耻浪费,那么我们要如何去做呢?
不用等待,又能精确定时,那么就是定时器了。使用定时器进行扫描,中断进行触发,就是我们对付按键的方法。
具体步骤如下:
1、中断服务程序,检测按键是否被触发。
2、定时器运行,扫描按键状态,完成消抖动作。
对于MSP430来说,P13是一个外部中断的中断源,所以我们可以直接将P13设置为外部中断输入就可以进行检测,代码如下:


void P1_inter_Init(void)
{


  P1IES|=BIT3;                          //选择下降沿触发     
  P1REN |=BIT3;                      //上啦电阻
  P1IFG &=~BIT3;                     //P1IES的切换可能使P1IFG置位,需清除 
  P1IE|=BIT3;                           //打开中断允许   
}


然后就可以完成第一步了,第二步,定时器,那么首先要配置定时器的周期,这里我用了CCR1的中断来扫描,CCR0来设置扫描周期,(不会的去看看MSP430的定时器A部分)
void Time0_A0_Init(void)
{
  TACCR0 = 327;  //10ms


  TACCTL0 = CCIE;  //允许中断
  TACCR1 = 32;
      // TACCTL1= CCIE;       
  TA0CTL = TASSEL_1+TACLR+MC_1; //模式设置
}


需要特别注意的是,我并没有直接开启CCR1的中断任务,因为一直处于扫描状态是会给CPU带来极大的压力。我们只在按键被触发了的时候,才进行扫描(精髓所在)。
所以在外部中断里面,我们才打开定时器的CCR1中断,进行扫描。
#pragma vector=PORT1_VECTOR 
__interrupt void P1_In(void)
{
  if(P1IFG&BIT3)
{
                     //处理P1IN.3中断
    P1IFG &= ~BIT3;  //清除中断标志
    P1OUT ^= BIT0;
      //以下填充用户代码
    TACCTL1= CCIE;  //开CCR1中断来扫描状态
    P1IE&=~BIT3;      //关闭外部中断
}


LPM3_EXIT;   //不喜欢低功耗的小伙伴不要这句
}




然后,再在定时器中断中添加我们的扫描代码
#pragma vector=TIMER0_A1_VECTOR
__interrupt void T0_A1_Inter()
{
switch(TA0IV)
{
  case 2:                           //CCR1
      //ii++;
      if(Switch_scan(&steep))       //键盘状态机
        ii++;


      break;
  case 4:                          //CCR2


      break;
case 10:                          //OVER 


      break;
}
}




其中扫描的函数我们采用状态机来编写,这对于一些新手来说可能比较少见
char Switch_scan(char *steep)
{
  switch(*steep)
  {
  case 0:
     if(P1IN&BIT3)       //表示如果下降后直接上升,表示为抖动
     {
       TACCTL1 &= ~CCIE; //把定时器扫描关掉
       P1IE|=BIT3;       //把中断打开
       (*steep) = 0;
     }
     else                //表示电平为低
     { 
       (*steep)++;
     }
     break;
  case 1:
    if(P1IN&BIT3)       //表示为抖动
      (*steep) = 0;


    else                  //这句保证2次认证按键的电平无误
      (*steep)++;       
    break;
  case 2:               //这里是检测松手
       if(P1IN&BIT3)
         (*steep) =3;   //松手了往下走
       else             //不然就在这里等松手
          ;
       break;
  case 3:
     if(P1IN&BIT3)     //的确松手了
       {
       (*steep)=0;     //重置状态机状态
       return 1;       //返回键值有效信号      
       }  
     else
       ;
       break;
  default : break;
  }
return 0;
}




我们将按键的状态分解成 按下→ 保持→ 松开  分别检测状态,制作条件语句和跳转逻辑,当第一次扫描发现按键只是抖动的时候,果断的关闭定时器的CCR1中断,并且重新打开外部的按键触发中断,这样一来,既节省了系统的开支,又可以可靠地进行按键的滤波。程序写进去发现效果很好,希望可以帮到大家。
<think>好的,用户想知道如何在海思SS928芯片上部署自己训练的模型。首先,我需要回忆之前提供的引用内容。根据引用[1],用户提到需要将.pt模型转换为.om模型,分两步:pt转ONNX,再转OM。引用[2]详细说明了转换需要ATC工具的环境安装,而引用[3]给出了ATC命令的示例。 接下来,我需要整理步骤。首先,用户需要将自训练的模型,比如YOLO的.pt文件,转换成ONNX格式。这可能需要使用导出工具,比如PyTorch的export函数。然后,用ATC工具将ONNX转成OM。这里要确保安装好ATC的依赖环境,可能包括CANN包。另外,如果模型需要量化,可能涉及AMCT工具进行校准,如引用[2]提到的量化步骤。 用户可能需要具体的操作命令,比如使用torch.onnx.export函数,调整输入输出的名称和形状。转换ONNX时要注意版本兼容性,可能指定opset版本。然后,ATC命令的参数需要正确设置,比如输入形状、输出节点、soc_version等,如引用[3]中的例子。 另外,部署SS928可能还需要编写推理代码,调用HiAI的Runtime API加载OM模型,处理输入输出数据。这部分可能需要参考海思的文档,确保内存管理和数据预处理正确。 可能的问题包括转换过程中的错误,比如不支持的算子,需要调整模型结构或使用自定义算子。或者性能优化,如调整ATC的编译选项。用户可能还会遇到量化精度损失的问题,需要校准数据集和调整量化参数。 最后,需要检查回答是否覆盖所有步骤,并生成相关问题,帮助用户深入理解后续可能遇到的问题,比如性能优化、模型量化或具体部署中的调试方法。</think>在海思SS928芯片上部署自训练模型的核心流程分为模型转换和部署适配两个阶段,具体步骤如下: ### 一、模型转换流程 1. **原始模型导出为ONNX格式** - 使用PyTorch的`torch.onnx.export`函数转换.pt模型 - 示例代码: ```python torch.onnx.export(model, dummy_input, "model.onnx", input_names=["input"], output_names=["output"], opset_version=11) ``` - 需注意输入/输出节点命名与模型结构一致性[^2] 2. **ONNX转OM模型** - 使用华为ATC工具完成格式转换 - 转换命令示例: ```bash atc --model=model.onnx \ --output=model \ --framework=5 \ --input_format=NCHW \ --input_shape="input:1,3,640,640" \ --log=debug \ --soc_version=SS928V100 ``` - 必须指定`soc_version`参数匹配目标芯片型号[^3] ### 二、部署适配要点 1. **环境准备** - 安装CANN工具包(版本需≥5.0.4) - 配置Ascend Runtime环境变量 ```bash source /usr/local/Ascend/ascend-toolkit/set_env.sh ``` 2. **推理代码开发** - 使用HiAI Runtime API加载OM模型 ```cpp aclmdlDesc* modelDesc; aclmdlLoadFromFile("model.om", &modelDesc); void* inputBuffer = aclmdlGetInputBuffer(modelDesc, 0); ``` 3. **性能优化** - 使用`msame`工具进行基准测试 - 调整ATC参数开启优化选项: ```bash --fusion_switch_file=fusion_switch.cfg ``` ### 三、常见问题处理 1. **算子不支持**:通过ATC的`--op_select_implmode`参数调整实现方式 2. **精度损失**:使用AMCT工具进行量化校准 3. **输入不匹配**:检查`input_shape`参数与模型实际输入维度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值