zoukankan      html  css  js  c++  java
  • 明确目标以及不要过早优化

      上周的嵌入式实验课做了一个关于ADC的实验,即用从5V中用变阻器分出一部分电压,用ADC采样量化作为输入信号,要求是使LED闪烁频率随这个信号限值(包括上限A和下限A)的幅度的增大而变快。

      设输入信号幅度是A,一个思路是用延时,A-A  越大,两次亮灯之间的延时越小,这样也就是闪得越快了。低于下限的时候同理。不过这篇随笔主要不是讲这个思路有多好(一般都能想到这个思路),而是要说它的实现。

      

      先说说当时是怎么做的吧。。由于已经给了例程,一般情况下为了图方便省事是直接修改,或者调用里面的函数(而且是只看接口不看内部)。一般情况下都有这么一个Delay的函数

    <main.c>中

    extern __IO uint32_t TimingDelay;

    void
    Delay(__IO uint32_t nTime) { TimingDelay = nTime; while(TimingDelay != 0); }

    在写中断源文件<stm32f10x_it.c>中

    __IO uint32_t TimingDelay = 0;

    void
    SysTick_Handler(void) { TimingDelay--; }

    当然还要配置SysTick,打开定时器,这样才能进入SysTick_Handler中断

    可是上面这些都配置好了以后,这个Delay函数只能在main.c 中调用,但问题是 LED亮灭(闪烁)本身就是在中断里面完成的

    void ADC1_2_IRQHandler(void)
    {
      /* Toggle LED1 */
      STM_EVAL_LEDOn(LED1);
      printf("interrupt occur
    ");
      STM_EVAL_LEDOff(LED1);
      printf("               
    ");
    /* Clear ADC1 AWD pending interrupt bit */ ADC_ClearITPendingBit(ADC1, ADC_IT_AWD); }

    如果在stm32f10x_it.c中调用Delay,即

    void ADC1_2_IRQHandler(void)
    {
      /* Toggle LED1 */
      STM_EVAL_LEDOn(LED1);
      Delay(500);
      printf("interrupt occur
    ");
      STM_EVAL_LEDOff(LED1);
      Delay(500);
      printf("               
    ");
    /* Clear ADC1 AWD pending interrupt bit */ ADC_ClearITPendingBit(ADC1, ADC_IT_AWD); }

    显示结果就是灯一直亮,也就是说进入 Delay(包括SysTick)以后就出不来了。。再转电位器也无济于事。这其中可能有很多原因,比如中断嵌套,优先级,标志位或者什么地方没有设置好,反正就是得不到想要的结果。由于机房的环境以及时间捉急(还有没法上网百度谷歌),越搞越搞不出来。

    (下面才是本文重点要说的)

      这时候朱哥提醒了我,要不用for循环来做延时得了。一试如梦初醒茅塞顿开!然后一下子有了很多想法(主要是反思)思维又被限制了好吗!

    来整理一下:

    1.

    //说明:ADC给过来的值的范围A是0~4096,A是2816,A是768
    //   系统晶振是25M
    //    3000是放大因子

    void ADC1_2_IRQHandler(void) { /* Toggle LED1 */ int i=0; STM_EVAL_LEDOn(LED1); if(ADC_GetConversionValue(ADC1)>2000){ for(i=ADC_GetConversionValue(ADC1)*3000;i<12500000;i++); }else{ for(i=(2000-ADC_GetConversionValue(ADC1))*6000;i<12500000;i++); } printf("interrupt occur "); STM_EVAL_LEDOff(LED1); if(ADC_GetConversionValue(ADC1)>2000){ for(i=ADC_GetConversionValue(ADC1)*3000;i<12500000;i++); }else{ for(i=(2000-ADC_GetConversionValue(ADC1))*6000;i<12500000;i++); } printf(" "); /* Clear ADC1 AWD pending interrupt bit */ ADC_ClearITPendingBit(ADC1, ADC_IT_AWD); }

    试验效果OK,达到要求。

    2.

      刚学51的时候,郭天祥老师的书上教了两种延时的方法:可以直接在其中用for循环来耗掉时间,这种方法中间不能做其他事,而且不是很精确;

    //<新概念51单片机C语言教程>中用来延时n毫秒的方法
    //当然也可以只用一个for
    void delay_ms(uint n)
    {
        uint x,y;
        for(x=0;x<n;x++)
            for(y=0;y<120;y++);
    }

    也可以用中断来实现,这样可以在期间做其他事情,既保证了效率又可以更精确计时。

      但是,并非所有场合都必须要用中断!在要求不高(时间精度或者功耗要求等)的场合,for延时够用了!简单方便,测试看延时的效果够用了。

    要把学过的东西融汇贯通,思维不要被约束和限制,明确目的!这里的目的首先是要达到要求,其次才是看你会不会正确用中断什么的

    3.

    3.1

      《黑客与画家》的译者总结,原著作者Paul Graham有一套完整的创业哲学,他的创业公式是:

      (1)搭建原型

      (2)上线运营(别管bug)

      (3)收集反馈

      (4)调整产品

      (5)成长壮大

      Paul Graham还指出,不要过早优化你的产品,在这次实验中也有异曲同工之妙。先完成作业要求,而不要一开始就想着出一个完美的作品,然后再进一步优化,至少在完成要求后心态更好头脑清晰不会有焦虑之急,有利于优化工作的进行。

    3.2

      看上去更近的路不一定是捷径(比如直接从另一个工程里面把与Delay函数有关的的抄过来,在这里就是用不了),绕远路可能更快,这样的例子在生活中很常见。

      至少需要先思考一下再行动,大脑这个智能CPU不是白给的。

      

  • 相关阅读:
    数据分析优化之惩罚性线性回归算法
    数据分析之贝叶斯算法案例
    SSM-CRUD练习
    使用 Code First 迁移以设定数据库种子
    .Net Web Api相关学习内容
    ASP.NET MVC5的学习知识点
    Entity Framework的学习(ASP.NET MVC5的学习中的一部分)
    EFCore框架的学习
    jsp中的<%%>用法
    nginx出现404和403错误
  • 原文地址:https://www.cnblogs.com/Cmfvacks-IsLjj/p/3745926.html
Copyright © 2011-2022 走看看