搜索
bottom↓
回复: 14

32路舵机控制,希望大家指教

[复制链接]

出0入0汤圆

发表于 2009-6-21 04:17:39 | 显示全部楼层 |阅读模式
#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 和管脚值,没有发现问题,等周一用示波器试试就知道这个程序是否能用了。。。。。  
 

出0入0汤圆

 楼主| 发表于 2009-6-21 04:18:15 | 显示全部楼层
第一次没发成功,这次应该可以了吧

出0入0汤圆

 楼主| 发表于 2009-6-22 08:58:47 | 显示全部楼层
啊哈哈哈哈哈 同志们 经过示波器测试,好得很啊!49.8320Hz,看来还要把中间的跳转的时间误差找出来,然后定时的时候减去应该就可以了

出0入0汤圆

 楼主| 发表于 2009-6-22 08:59:48 | 显示全部楼层
把串口通讯程序加进去就可以通过电脑控制了!!

出0入0汤圆

发表于 2009-6-22 09:38:01 | 显示全部楼层
顶~~~~~~~~~~~~~~~~~~~
不错,很好的算法。。。。

出0入0汤圆

发表于 2010-8-3 22:52:33 | 显示全部楼层
好啊

出0入0汤圆

发表于 2010-8-12 10:37:49 | 显示全部楼层
顶 顶顶顶顶

出0入0汤圆

发表于 2010-8-27 11:46:28 | 显示全部楼层
很强大,顶~~~

出0入0汤圆

发表于 2010-10-18 12:09:18 | 显示全部楼层
很强大,顶~~~

出0入0汤圆

发表于 2010-10-18 12:14:43 | 显示全部楼层
很强大,顶~~~

出0入0汤圆

发表于 2012-7-11 18:25:25 | 显示全部楼层
马克西     

出0入54汤圆

发表于 2012-7-19 20:29:58 | 显示全部楼层
需要用到的

出0入0汤圆

发表于 2012-7-20 13:08:25 | 显示全部楼层
认真看看才行

出0入0汤圆

发表于 2013-12-5 12:27:35 | 显示全部楼层
不知道硬件是如何连接的?使用的什么型号的avr,能不能告知

出0入0汤圆

发表于 2014-2-6 18:49:42 | 显示全部楼层
不错!!!顶一个!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 05:01

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表