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