|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2014-3-30 13:51:03
|
显示全部楼层
#include<iccioavr.h>
#include<AVRdef.h>
#include"AVR_SPI.h"
unsigned char m=0,a=0;
unsigned int Dispersion[32];//存放各个延时值之间的时间差
//第1组舵机数据
unsigned char Length_Temp[32];//从小到大存放各路高电平延时值
unsigned char Length[32]={50,60,60,80,90,100,130,130,
50,60,60,80,90,100,130,30,
50,60,60,80,90,100,130,130,
50,60,60,80,90,100,130,130};//高电平时间 单位10us
unsigned long Serial_Num[32]={0xfffffffe,0xfffffffd,0xfffffffb,0xfffffff7,0xffffffef,0xffffffdf,0xffffffbf,0xffffff7f,
0xfffffeff,0xfffffdff,0xfffffbff,0xfffff7ff,0xffffefff,0xffffdfff,0xffffbfff,0xffff7fff,
0xfffeffff,0xfffdffff,0xfffbffff,0xfff7ffff,0xffefffff,0xffdfffff,0xffbfffff,0xff7fffff,
0xfeffffff,0xfdffffff,0xfbffffff,0xf7ffffff,0xefffffff,0xdfffffff,0xbfffffff,0x7fffffff};
unsigned long Serial_Temp[32];//临时存放Serial_Num[[8]
void Timer1_Init(void);//定时器3初始化
void Int0_Init(void);//外部中断0初始化,下降沿触发
void Sorting(void);//冒泡法排序函数 主要对Length_Temp0[8]排序
void main(void)
{
SPI_MasterInit();//SPI总线初始化
DDRD|=0x08;//设置PD0为输出
PORTD|=0x08;//置PD0为高电平
Timer1_Init();//初始化定时器3 8分频
Int0_Init();//初始化外部中断0 1分频
Sorting();//对初始值进行排序,确定dispersion数组的值
//因为vlaue的值是0—255,外部晶振为16M,定时器的计数频率设为8分频。这样每计一个值
//耗费的时间是0.5us.舵机要求的高电平时间是500us到2500us之间,对定时器赋初值
//就以应该是65536-500*2=64536到65536-2500*2=60536之间。对应的value的值就是50-250
//所以,给定时器赋初值就是vlaue*20 value的单位是10us
TCNT1H=(0xffff-Length_Temp[0]*20)/256;//经过排序后,vlaue[0]是最小的数
TCNT1L=(0xffff-Length_Temp[0]*20)%256;//给定时器3赋初值
HC595_OUT_BANK0(0xff);
HC595_OUT_BANK1(0xff);
HC595_OUT_BANK2(0xff);
HC595_OUT_BANK3(0xff);
//定时器开始计时,对外部16M晶振进行8分频,定时器计数为0.5us一个增量,
//单片机的指令执行速度仍然是1/16m=62.5ns一个指令周期
TCCR1B=0x02; //T1定时器8分频
SREG|=BIT(7);//总中断使能
while(1)
;
}
#pragma interrupt_handler Int0:2//中断0处理程序
void Int0(void)
{
TCCR1B=0x00;
PORTD|=0x08;//恢复PD3口为高电平,开始响应中断0
Sorting();
m=0;
TCNT1H=(0xffff-Length_Temp[0]*20)/256; //给定时器3赋初值
TCNT1L=(0xffff-Length_Temp[0]*20)%256;
HC595_OUT_BANK0(0xff);//PORTB=0xff;//置所有位为高
HC595_OUT_BANK1(0xff);
HC595_OUT_BANK2(0xff);
HC595_OUT_BANK3(0xff);
TCCR1B=0x02;//打开定时器1,8分频,每计一位为0.5us
}
#pragma interrupt_handler Timer1_Time:9//定时器1的溢出中断处理程序
void Timer1_Time(void)
{
TCCR1B=0x00;
if(m==32)
{
TCCR1B=0x00;//一个周期结束,关闭定时器1
PORTD&=0xf7; //PD0置低位,引发外部中断0
}
else
{
spot0:HC595Output(Serial_Temp[m]);
//第一次中断溢出时,m=0,Dispersion[0]为value[1]-value[0]
if(Dispersion[m]==0)
{
m=m+1;
goto spot0;
}
else
{
TCNT1H=(0xffff-Dispersion[m]+40)/256;//+40为补偿值
TCNT1L=(0xffff-Dispersion[m]+40)%256;
}
//当m=7的时候,dispersion[7]为所有管脚置低后低电平维持的时间
m=m+1;
}
TCCR1B=0x02;
}
void Timer1_Init(void)
{
TCCR1A=0x00;//
TCCR1B=0x02;//8 frequency division
TIMSK|=(1<<TOIE1);//TOIE1=1
}
void Int0_Init(void)
{
GICR|=0X40;//ENABLE INT0
MCUCR|=0X02;//drop edge trigger
}
//冒泡法将Length_Temp和Serial_Num从小到大排序
void Sorting(void)
{
unsigned char i,j,k;
unsigned long t;
for(i=0;i<32;i++)
Length_Temp=Length;//将时常数据传送给临时数组Length_Temp
for(i=0;i<32;i++)
Serial_Temp=Serial_Num;//将时常数据传送给临时数组Serial_Temp
for(j=0;j<31;j++)//冒泡算法,Length_Temp[8]被从小到大排序
{
for(i=0;i<31-j;i++)
{
if(Length_Temp>Length_Temp[i+1])
{
k=Length_Temp[i+1];
Length_Temp[i+1]=Length_Temp;
Length_Temp=k;
t=Serial_Temp[i+1];
Serial_Temp[i+1]=Serial_Temp;
Serial_Temp=t;//相应要置低的管脚也排序
}
}
}
for(j=0;j<31;j++)//相邻的数之间做差值,总共得到差值7个
{
//if(Length_Temp[j+1]==Length_Temp[j])
//Dispersion[j]=6;
//else
Dispersion[j]=(Length_Temp[j+1]-Length_Temp[j])*20;
}
//最后一个值是低电平延时,65536-40000是20ms的定时初值
Dispersion[31]=40000-Length_Temp[31]*20;
for(i=0;i<32;i++)
{
if(i>0)
Serial_Temp=Serial_Temp&Serial_Temp[i-1];
}
}
将函数改了一下在 Sorting中将Serial_Temp和TCNT1计算 在T1中断中用:HC595Output(Serial_Temp[m]);调用发现误差依然很大 误差依然很大,是不是说明HC595Output()会的调用会占用很多时间?另外周期也不准确了,周期倒是比较修正 |
|