标题:
ATmega16实现八个电位器分别同时控八个舵机,还可以更多
[打印本页]
作者:
HYH520
时间:
2017-6-12 12:49
标题:
ATmega16实现八个电位器分别同时控八个舵机,还可以更多
上回用了一个定时器控制三个舵机行不通,这次在次按照网上的思路,用了两个定时器,成功实现了atmega16八个电位器分别同时控八个舵机,实际还可以更多,
通过实验发现舵机受控的周期不一定要20ms,八路舵机,每个舵机的控制周期可以延伸,例如40ms给一次脉冲,也是能控制舵机旋转至固定角度,在这里,控制舵机的应该是高电平信号持续时间,由于从20ms延长到40ms,所以单片机可以控制更多的舵机,20ms能控制8个,40ms能控制16个,但是20ms相对于40ms控制周期的舵机来说更稳定,可能是由于原本1s内,以20ms为周期的信号,可以对舵机发送50次控制信号,延长到40ms,只能对舵机发送25次控制信号,这样会导致舵机控制频率降低,从而导致相对的不稳定,这里使用的是普通舵机,数码舵机应该不会出现这种情况。
最后贴上代码,实测可用:
/**************八通道电位器控制八舵机****************
* 编写:HYH
* 日期:2017-6-12
* 晶振:12mhz
* 说明:定时/计数器0固定每2.5ms溢出中断,负责拉高对
* 应端口,定时/计数器1负责在tc1中断产生后将对
* 应端口的电平拉低,依次循环形成八个通道舵机
* 控制pwm波
*****************************************************/
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define OUTPUT PORTD //定义pd口为舵机信号输出口
#define ADCN ADMUX
unsigned char output_high[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数组控制各个io口高电平
unsigned int i=0;
unsigned int j=0;
unsigned char ADCN_[8]={0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; //数组控制ADC通道选择
unsigned int adcn_[8]; //存取八个通道的ADC值
unsigned int adcn_change[8]; //存储adcn_[]经过转换成计数器1初值的值
/************延时函数***********/
void delay(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<1141;j++);
}
}
/*********端口设置函数*********/
void port_init(void)
{
DDRD|=0XFF;
PORTD&=0X00; //设置舵机信号输出端口
DDRA&=0X00;
PORTA|=0Xff; //设置adc通道端口,带上拉输入
SREG=0X80; //开放全局中断
}
void timer0_init()
{
TIMSK|=(1<<TOIE0); //是能溢出中断
TCCR0|=(1<<CS02)|(0<<CS01)|(0<<CS00); //12mhz晶振 256预分频
TCNT0=139;
//计数器初值,(256-139)/(12mhz/256)=2.5ms
}
void timer1_init()
{
TCCR1A|=0X00; //普通模式
TCCR1B|=(0<<CS12)|(0<<CS11)|(1<<CS10); //无预分频
TIMSK|=(1<<TOIE1);
}
/**********ad转换函数**********/
unsigned int ADC_init()
{
unsigned int addata;
ADCN=ADCN_[j]; //AVCC为基准电,设置adc通道选择
ADCSRA=0XD8; //使能ADC,允许中断 11011000
ADCSRA|=BIT(ADSC); //开始A/D转换
while(!(ADCSRA&(BIT(ADIF)))); //等待转换完成
addata=ADCL; //获取ADC结果
addata=addata+ADCH*256;
return addata; //返回ADC值
}
void main()
{
timer0_init();
timer1_init();
ADC_init();
port_init();
}
/*********定时器0中断函数************
* 说明:定时器每溢出一次,舵机通道调
* 至下一个,拉高该舵机通道io口
* 并把对应通道的adcn_change[]值
* 赋给定时/计数器初值
************************************/
#pragma interrupt_handler timer0_ovf:10
void timer0_ovf()
{
OUTPUT|=output_high[i];
TCNT0=139;
TCNT1=adcn_change[i];
i++;
if(i>=8)
i=0;
}
/************定时/计数器1中断函数********
* 说明:将对应端口电平拉高
****************************************/
#pragma interrupt_handler timer1_ovf:9
void timer1_ovf()
{
TCNT1=0;
if(i==0)
OUTPUT&=~BIT(7);
else
OUTPUT&=~BIT(i-1);
}
/************ADC中断函数**************/
#pragma interrupt_handler ADCN_change:15
void ADCN_change()
{
adcn_[j]=ADC_init();
adcn_change[j]=59536-24*adcn_[j]; //将adc值转化为定时/计数器1初值,控制高电平持续时间
j++;
if(j>=8)
j=0;
ADC_init(); //adc转换
}
复制代码
0.png
(56.86 KB, 下载次数: 250)
下载附件
2017-6-12 15:57 上传
全部资料下载地址:
ADC多通道.zip
(537.96 KB, 下载次数: 32)
2017-6-12 12:45 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
admin
时间:
2017-6-12 15:59
好资料,51黑有你更精彩!!!
作者:
erzhu2007
时间:
2017-8-15 15:47
哇,思路清晰啊,舅服你
作者:
erzhu2007
时间:
2017-8-15 19:58
多个数字舵机控制,楼主讲下具体思路吗?我不管小板凳已经拿来了
作者:
成森林
时间:
2018-1-31 16:23
金币不足了,先收藏了。
作者:
成森林
时间:
2018-2-25 16:08
终于可以下载到了,谢谢楼主。
作者:
HYH520
时间:
2018-3-8 12:48
数字舵机区别于传统的模拟舵机,模拟舵机需要给它不停的发送PWM信号,才能让它保持在规定的位置或者让它按照某个速度转动,数字舵机则只需要发送一次PWM信号就能保持在规定的某个位置
作者:
工作狂
时间:
2018-3-10 16:45
好资料,51黑有你更精彩!!!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1