5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)

标题: 求 模拟转 开关 AVR 的C语言程序,哪位高人能给提供一个。 [打印本页]

作者: 老郑    时间: 2013-3-5 18:54
标题: 求 模拟转 开关 AVR 的C语言程序,哪位高人能给提供一个。
有点小要求:

此单片机要接在 接收机的一个通道上。

发射机 一个3位开关通道 向上拨  AVR 一个 IO 口 为 0,回中位IO 口信号不变,再次向上拨 IO 口 为1。 3位开关向下 拨 : 另一个 IO 口 输出脉冲 1次/秒,3位开关回中位脉冲停止。   

先行万分感谢! 造福模友。

此装置可用在 相机拍照上用。


作者: keyzheng    时间: 2013-3-5 19:16
实现这个用不了几句话,可是你得从基础学起这就难了。哈哈哈,帮不了你。你还是从跑马灯开始学AVR吧,给你个比较有名的论坛,学吧http://www.amobbs.com/forum.php

作者: flywind    时间: 2013-3-5 19:43
很简单。。不过想一下子学会可能很难。。。主要由以下几个关键点构成
时钟 和 Interrupt 概念:
Interrupt Capture -- 用来补捉接收机的信号
Timer interrupt Output -- 用来做输出脉冲 1次/秒 。
然后就是简单的 For / while loop
应该还有就是电路的问题了。。
慢慢说还是蛮多的。。。。我记得我这些都是一学期的课教的。。。但都是在一个星期学会的。。



作者: 3dbuild    时间: 2013-3-5 23:05
本帖最后由 3dbuild 于 2013-3-5 23:06 编辑

给你写了一个,开关通道输出的也是标准的舵机控制信号,如下图

(, 下载次数: 38)

只要检测脉冲宽度,就可以知道开关的位置,这个程序使用ATTINY13,8个脚的AVR单片机,使用内部9.6M的振荡源,外部不需要任何元件,接线图如下

(, 下载次数: 29)
用WINAVR编译,可以下 载的HEX文件: (, 下载次数: 5)





作者: 3dbuild    时间: 2013-3-5 23:11
#include "stdio.h"
#include "avr/io.h"

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )

// 测量高电平脉冲长度,单位是微秒(uS),接收机输出脉冲宽度是1000uS - 2000uS,中点是1500uS
unsigned long pulseIn()
{
  unsigned long width = 0;
       
  unsigned long numloops = 0;
  unsigned long timeout = 20000; // 超时设置为20ms

  // 把超时转换为循环次数
  unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
       
  // 如果上一个脉冲没结束,则等待其结束
  while( (PINB & _BV(PB0)) == _BV(PB0) )
    if (numloops++ == maxloops)
      return 0;
       
  // 等待脉冲开始
  while( (PINB & _BV(PB0)) == 0 )
    if (numloops++ == maxloops)
      return 0;
       
  // 等待脉冲结束
  while( (PINB & _BV(PB0)) == _BV(PB0) )
  {
    if (numloops++ == maxloops)
      return 0;
    width++;
  }

  // 把width转换成微秒
  return clockCyclesToMicroseconds(width * 21 + 16);
}

// 脉冲宽度小于1200,认为是位置1
// 脉冲宽度小于1700,认为是位置2
// 其他情况认为是位置3

#define POSITION1 1200
#define POSITION2 1700

int main()
{
  uint8_t pos;
  uint8_t do_switch = 0;
  uint8_t pin1_state = 0;
  uint8_t pin2_state = 0;

  // 启动时把PB1 PB2设置为低电平
  cbi(PORTB, PB1);
  cbi(PORTB, PB2);

  // 配置PB0为输入 PB1,PB2为输出
  DDRB = 6;

  uint16_t delay_count = 30000; // 主频9.6M时,大约0.5秒延时的计数值

  for(;;)
  {
    // 检测 3位开关通道 状态
    unsigned long len = pulseIn();
    if(len!=0)
    {
      if(len < POSITION1) pos = 1; // 3位开关通道 向上拨
      else if(len < POSITION2) pos = 2; // 3位开关通道 回中位
      else pos = 3; // 3位开关通道 向下拨
    }

    if(pos==3)
    {
      // 3位开关通道 向下拨 的状态,在PB2口输出脉冲 1次/秒

      delay_count--;
      if(delay_count==0)
      {
        if(pin2_state==0) cbi(PORTB, PB2);
        else sbi(PORTB, PB2);

        pin2_state = !pin2_state;
        delay_count = 30000;
      }
    }
    else{
               
      // 其他状态一律把PB2口输出低电平
      cbi(PORTB, PB2);

      if(pos==1)
      {
        // 3位开关通道 回中后再向上拨一次 PB1口切换输出状态一次
        if( do_switch==1 )
        {
          if(pin1_state==0) cbi(PORTB, PB1);
          else sbi(PORTB, PB1);

          pin1_state = !pin1_state;
          do_switch = 0;
        }
      }
      else do_switch = 1; // 3位开关通道 回中,设置标记,使下一次向上拨时可以切换状态
    }
  }

  return 0;
}




作者: 老郑    时间: 2013-3-6 15:26
感谢 几位 的指点,看样还要多多努力。

作者: 老郑    时间: 2013-3-6 15:48
读了一下程序,看 AVR 有点晕,51和AVR 差别太大了 ,半年以后再研究吧,先按指导,做一个再说。(ATTINY13已有)

感谢 4楼的耐心讲解,造福广大模友。


奢侈的要求 谁有51的程序,能否发发上来学习一下,正如3楼所说学会是很难的。 准备再用 STC 做一个,STC  下 载线简单,这样可能会有更多人仿制了。





作者: 3dbuild    时间: 2013-3-6 19:36
本帖最后由 3dbuild 于 2013-3-6 19:43 编辑

51和AVR差别大吗?我觉得没什么差别啊?只是端口输出0和1的语法有点区别,其实是一样的。AVR的编译器支持C++语法,看起来程序清楚一些

AVR的下 载线比51的更方便,也很便宜

这么小的8脚芯片,51不好找吧?航模的东西越轻越好

设置端口输出0和1的语法:

51:设置P1的7端口

sbit pin =P1^7 ;

pin = 0;
pin = 1;

AVR: 设置PORTB的PB2端口

sbi(PORTB, PB2); // 1
cbi(PORTB, PB2); // 0


作者: 3dbuild    时间: 2013-3-6 19:38
AVR下 载线

(, 下载次数: 20)

作者: 3dbuild    时间: 2013-3-6 20:08
(, 下载次数: 20) (, 下载次数: 40)


作者: 老郑    时间: 2013-3-7 13:43
感谢 3dbuild  的指点 ,对于初学者来说尤其 没有学过C的人, 51还是简单容易理解,尤其是 位操作。

如上 sbit pin =P1^7 ;  意思是 : P1口 的7管脚      就叫  pin 。 初学人这关也是不好过的。

对于 下 载线, 刚接触单片机 学习的是51 ( AT 89S52)   感觉 上述的下 载线很方便、快捷,  这些天看到 STC 的下 载线 似乎更方便 只需要4条,51 是5条,但STC下 载是需要技巧的。

但单片机 AVR  是现公认较稳定的产品,抗干扰非常好。  (出自网上,自己还没试验过)

51 适合刚接触单片机 且从未学习过计算机语言的人,个人愚见。

再次感谢 3dbuild  的指点 。



作者: 铜河    时间: 2013-3-8 13:50
单片机高手如云~~~~~~





欢迎光临 5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年) (http://5imx.com./) Powered by Discuz! X3.3