|
#include<avr/io.h>
//#include<util/delay.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define uint unsigned int
uint c=0,a=0;
uchar b=0,m=0,i,begin_cycle=2;
//存放7个pwm数值之间的差和一个周期与最大数值的差,作为定时器的输入值
uint dispersion[8];
//用于8个pwm数值排序
uchar value[8];
//储存8个PWM数值的初始值
uchar storage[8]={210,180,106,150,120,101,80,60};
//要关闭的管脚,与值
uchar serial_num[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void uart0init(void);//串口中断初始化
void time3init(void);//定时器3初始化
void time0init(void);//定时器0初始化
void int0init(void);//外部中断0初始化,下降沿触发
SIGNAL(SIG_OVERFLOW3);//定时器3中断处理函数
SIGNAL(SIG_OVERFLOW0);//定时器0中断处理函数
SIGNAL(SIG_INTERRUPT0);//外部中断0处理函数
void uart0SendChar(unsigned char data);//串口发送函数
SIGNAL(SIG_USART0_RECV);//串口接收中断函数
void sorting();//排序函数
int main(void)
{
DDRC=0xff;//设置c端口为输出
PORTC=0xff;//置所有的管脚为高
DDRD|=0x01;//设置PD0为输出
PORTD|=0x01;//置PD0为高电平
time3init();//初始化定时器3
int0init();//初始化外部中断0
sorting();//对初始值进行排序,确定dispersion数组的值
//因为vlaue的值是0—255,外部晶振为16M,定时器的计数频率设为8分频。这样每计一个值
//耗费的时间是0.5us.舵机要求的高电平时间是500us到2500us之间,对定时器赋初值
//就以应该是65536-500*2=64536到65536-2500*2=60536之间。对应的value的值就是50-250
//所以,给定时器赋初值就是vlaue*20
TCNT3H=(0xffff-value[0]*20)/256;//经过排序后,vlaue[0]是最小的数
TCNT3L=(0xffff-value[0]*20)%256;//给定时器3赋初值
PORTC=0xff;//置输出口为高
//定时器开始计时,对外部16M晶振进行8分频,定时器计数为0.5us一个增量,
//单片机的指令执行速度仍然是1/16m=62.5ns一个指令周期
TCCR3B=0x02;
begin_cycle=0;//置下一个周期开始标志位为0
sei();//开总中断
for(;;)
{
}
}
//主程序结束了
//interrupt program
void uart0SendChar(unsigned char data)//串口发送程序
{
while(!(UCSR0A&_BV(UDRE1)));
UDR0 = data;
}
SIGNAL(SIG_USART0_RECV)//串口接收程序
{
b=UDR0;
uart0SendChar(b);
}
SIGNAL(SIG_INTERRUPT0)//中断0处理程序
{
PORTD|=0x01;//恢复PD0口为高电平,开始响应中断0
if(begin_cycle==0)//对数组进行排序,对dispersion数组进行赋值
{
sorting();
}
else if(begin_cycle==1)
{
TCNT3H=(0xffff-value[0]*20)/256; //给定时器3赋初值
TCNT3L=(0xffff-value[0]*20)%256;
PORTC=0xff;//置所有位为高
TCCR3B=0x02;//打开定时器3,8分频,每计一位为0.5us
begin_cycle=0;
}
}
SIGNAL(SIG_OVERFLOW0)
{
}
SIGNAL(SIG_OVERFLOW3)//定时器3的溢出中断处理程序
{
if(m==9)
{ m=0;
begin_cycle=1;//等赋值dispersion[7]的计时完成后,准备开始下一个周期
TCCR3B=0x00;//一个周期结束,关闭定时器3
PORTD&=0xfe;//引发EINT0
}
else
{
PORTC&=serial_num[m];//将相应的管脚置低
//第一次中断溢出时,m=0,dispersion[0]为value[1]-value[0]
TCNT3H=(0xffff-dispersion[m])/256; TCNT3L=(0xffff-dispersion[m])%256;
//当m=7的时候,dispersion[7]为所有管脚置低后低电平维持的时间
m++;
//给定时器赋完值后,定时器开始进入延时最长的时间段,引发外部中断0
//在这个时间段里面,在外部中断0里面完成排序,计算等工作
if(m==8)
{
m++;
begin_cycle=0;
PORTD&=0xfe; //PD0置低位,引发外部中断0
}
}
}
//interrupt initial
void uart0init(void)
{
UBRR0H = 0x00;
UBRR0L = 103;//9600
UCSR0B =0x98 ;//RXCIEn=1,RXENn=1,TXENn=1
UCSR0C = 0x06;//UCSZn1=1,UCSZn0=1,8bit,1 stop,
}
void time3init(void)
{
TCCR3A=0x00;//
TCCR3B=0x02;//8 frequency division
ETIMSK|=0x04;//TOIE1=1
}
void time0init(void)
{
TCNT0=0x50;
TCCR0=0x02;//prescaler=1
TIMSK|=0x01;
}
void int0init(void)
{
EIMSK|=0X01;//ENABLE INT0
EICRA|=0X02;//drop edge trigger
}
//data process
void sorting()
{ uchar i,j,t;
serial_num[0]=0xfe;serial_num[1]=0xfd;serial_num[2]=0xfb;serial_num[3]=0xf7;
serial_num[4]=0xef;serial_num[5]=0xdf;serial_num[6]=0xbf;serial_num[7]=0x7f;
for(i=0;i<8;i++)
{value=storage;}
// sort program
for(j=0;j<7;j++)//冒泡算法,value[0]是最小的数
for(i=0;i<7-j;i++)
if(value>value[i+1])
{
t=value;value=value[i+1];value[i+1]=t;
t=serial_num;serial_num=serial_num[i+1];serial_num[i+1]=t;
//相应要置低的管脚也排序
}
for(j=0;j<7;j++)//相邻的数之间做差值,总共得到差值7个
dispersion[j]=(value[j+1]-value[j])*20;
//最后一个值是低电平延时,65536-40000是20ms的定时初值
dispersion[7]=40000-value[7]*20;
}
这是我做测试的一个8位的数组,增加数组数的个数就能实现32路以上的处理。而且,只用中断,这样在主程序中就可以处理传感器了。希望大家斧正!
经过模拟调试,通过观察定时器的TCNT3 和管脚值,没有发现问题,等周一用示波器试试就知道这个程序是否能用了。。。。。
|
|