舵机程序之一个定时器带32路

发布者:WhisperingLight最新更新时间:2015-05-19 来源: 51hei关键字:舵机程序  定时器  32路 手机看文章 扫描二维码
随时随地手机看文章
关于本程序的几个问答先写出来

问:->这个符号是引用结构体成员吗?为什么不是点“.”呢?

答:指针式结构体的寻址方式。。是个结构体指针的一种用法

问:c51里面还没用过结构体。。

答:恩 不常用 因为比较耗费资源 占用的ram rom都比变量和数组多 不过可以让程序条理清晰 呵呵

每四路一组,从占空比从小到大排序,合并相同占空比。从第0组到第7组分时控制。第一次定时为每一组最短的占空比时间,然后中断处理第2至4路,如果到第2路以及之后路数已大于每组不同占空比路数则结束这一组,拉低4路PWM输出,进入下一组;否则进行判断,前一路占空比在pwm[31]数组(保存了每个占空比对应的物理引脚)中的哪个位置,并拉低相应引脚,设置下一次定时时间为排序后相邻两占空比之差。短小精干!学习了。

程序中用到的12c5a.h这个头文件可从 http://www.51hei.com/f/12c5a.rar 这里下载

//采用了分时和复控混合的控制方法,把20ms分成8个时期(分时控制的思路),

//每个时期同时拉高4路电平对应时间在分别拉低电平(复控的思想),

//最大程度利用定时器

 

#include"12c5a.h"     //STC12C5A
#include"intrins.h"
/***********************************************************************************************/
#define Bijiao_7 31    //为了方便所以在这定义了一个宏,需要控制n路则把#define Bijiao_7   n-1
#define IoPH    P0=0;P1=0;P2=0;P3=0
/***********************************************************************************************/
struct HH
{
 unsigned char geshu[8],Cs;     //重复数值的个数
 unsigned int pwm[8][4];
}xdata Hhpwm={0,{0}},*hpwm;    //创建HH结构体和这样的一个指针 
unsigned int xdata pwm[Bijiao_7+1]=
         {
          500,1000,1500,2500,
          500,1500,2000,2500,
          500,1500,2000,2500,
          500,1500,2000,2500,
          500,1500,2000,2500,
          500,1500,2000,2500,
          500,1500,2000,2500,
          1000,1500,1500,1500
         };
/************************************************全局数据***************************************/
void init_io(void);
void Timer_init(void);
void Timer0(unsigned int us);
void mpf(struct HH *MP,unsigned int *p,unsigned char ong);
void sjcl(struct HH *MP,unsigned char ong);
void Shgx(unsigned int *p);
void daley(unsigned int us);
unsigned int Zt_fh(unsigned char cs,unsigned char);
/************************************************函数声明****************************************/
void main(void)
{
 hpwm=&Hhpwm;     //初始化结构体指针
 hpwm->Cs=0;
 init_io();
 Timer_init();
 Shgx(pwm);
 Timer0(100);
 while(1)
 {
 ;
 }
}
/************************************************************************************************** 
函数名:init_io(void)
功能: io口设置成为推挽工作模式
作者: the sea
时间: ~~~
备注:  io初始化
***************************************************************************************************/
void init_io(void)
{
 P0M1=0;          //设置io口为强推挽
 P0M0=0XFF;

 P1M1=0;
 P1M0=0XFF;

 P2M1=0;
 P2M0=0XFF;

 P3M1=0;
 P3M0=0XFF;
 daley(100);
}
/************************************************************************************************** 
函数名: Timer_init(void)
功能: 定时器0初始化
作者: the sea
时间: ~~~
备注: 1T,方式1,16位
***************************************************************************************************/
void Timer_init(void)
{
 EA=1;          //开总中断
 AUXR|=0xC0;      //T0,T1工作在1T
    TMOD|= 0x11;     //T0工作在方式1,16位
 ET0 = 1;      //开定时器0中断
}
/************************************************************************************************** 
函数名:timer0(unsigned int us)
功能: 定时器0定时函数
参数: us,毫秒。  精确定时。
作者: the sea
时间: ~~~
备注:  晶振11.0592M,工作模式1T
/***************************************************************************************************/
void Timer0(unsigned int us)    

 unsigned int valu;
 us>=90? (valu=(us-80)*11) : (valu=us*11) ;      //在分时和复控当中没有-80,这是误差矫正,不减的话舵机走位误差会很大
 TR0=0;
 valu=0xffff-valu;     

    TH0=valu>>8;         //高8位放入th0
    TL0=valu;    //低8位放入tl0
    TR0= 1;       //T0开始工作
}
/************************************************************************************************** 
函数名:mpf(unsigned int *p,unsigned char ong)
功能: 把结构体数组内的数据按照从小到大的顺序排列之后重新存储到数组当中
作者: the sea
时间: ~~~
备注:  冒泡法
***************************************************************************************************/[page]
void mpf(struct HH *MP,unsigned int *p,unsigned char ong)  //冒泡法
{
 char i,j;
 unsigned int num;
 for(i=0;i  {
  *((*MP->pwm)+i)=*(p+i);   //把*p的数据存储至MP->pwm【】
 }
 for(i=ong;i>0;i--)
  for(j=0;j<(i%4);j++)
  {
   if(MP->pwm[i/4][j]>MP->pwm[i/4][j+1])
   {
    num=MP->pwm[i/4][j];
    MP->pwm[i/4][j]=MP->pwm[i/4][j+1];
    MP->pwm[i/4][j+1]=num;
   }
  }       //冒泡法对大小进行排序,顺序是从小到大
}
/************************************************************************************************** 
函数名:sjcl(struct HH *MP,unsigned char ong)
功能: 经过冒泡法处理之后再把重复的数据进行处理使得每个数值只保留一个
作者: the sea
时间: ~~~
备注:  大概可以总结为除同存异(前提必须经过冒泡法处理过的数据本函数才有效)
***************************************************************************************************/
void sjcl(struct HH *MP,unsigned char ong)   //数据处理,pwm数组当中大小相同的数值处理存储到结构体Hpwm
{
 char i,j,num;
 for(i=(ong/4);i>=0;i--)
  {
   num=0;
   for(j=0;j<3;j++)
   {
    if(MP->pwm[i][j]==MP->pwm[i][j+1])
     {
      num++;      
     }
    else
     {
      MP->pwm[i][j-num]=MP->pwm[i][j];
     }
   }
   MP->pwm[i][3-num]=MP->pwm[i][3];
   MP->geshu[i]=4-num;      //排除相同的数据之后数据的数目
  }
}
/************************************************************************************************** 
函数名:Shgx(unsigned int *p)  
功能: 更新舵机位置
作者: the sea
时间: ~~~
备注: 刷新
***************************************************************************************************/
void Shgx(unsigned int *p)    //pwm数据更新
{
 char i;
 for(i=Bijiao_7;i>=0;i--)
  pwm[i]=*(p+i);     //数组数据更新
 mpf(hpwm,p,Bijiao_7);
 sjcl(hpwm,Bijiao_7);     //数据更新之后再次刷新处理
}
/************************************************************************************************** 
函数名:ZT_fh(unsigned char cs)
功能: 定时器中断调用,用于返还io口电平状态数据
作者: the sea
时间: ~~~
备注: 
***************************************************************************************************/
unsigned int Zt_fh(unsigned char cs,unsigned char ong)
{
 char i;
  static unsigned int num;
 if(cs==2)
 num=0xf;         //一个周期把num复位至0xf
 for(i=ong;i>=0;i--)
  {
   if(hpwm->pwm[hpwm->Cs][cs-2]==pwm[i+(hpwm->Cs*4)])
   {
    num&=~(1<    }
  }
  return num;
}
/************************************************************************************************** 
函数名:daley(unsigned int us)
功能: 延时
作者: the sea
时间: ~~~
备注:  延时函数
***************************************************************************************************/
void daley(unsigned int us)
{
 unsigned int i,j;
 for(i=100;i>0;i--)
  for(j=us;j>0;j--)
  {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
}
/************************************************************************************************** 
函数名:T0_zd(void) interrupt 1
功能: 定时器0中断函数
作者: the sea
时间: ~~~
备注:  制造控制舵机所需的pwm
/***************************************************************************************************/
void T0_zd(void) interrupt 1
{
 static unsigned char num=0;
 num++;
 if(num==1)
 {
  switch(hpwm->Cs)
  {
  case 0: P0=0xf;break;
  case 1: P0=0xf<<4;break;
  case 2: P1=0xf;break;
  case 3: P1=0xf<<4;break;
  case 4: P2=0xf;break;
  case 5: P2=0xf<<4;break;
  case 6: P3=0xf;break;
  case 7: P3=0xf<<4;break;
  }  
  Timer0(hpwm->pwm[hpwm->Cs][0]);
 }
 else if(hpwm->geshu[hpwm->Cs]>=num)
 { 
  switch(hpwm->Cs)
  {
  case 0: P0=Zt_fh(num,3);break;
  case 1: P0=Zt_fh(num,3)<<4;break;
  case 2: P1=Zt_fh(num,3);break;
  case 3: P1=Zt_fh(num,3)<<4;break;
  case 4: P2=Zt_fh(num,3);break;
  case 5: P2=Zt_fh(num,3)<<4;break;
  case 6: P3=Zt_fh(num,3);break;
  case 7: P3=Zt_fh(num,3)<<4;break;
  }                   //把舵机所需的电平状态传给p口
  Timer0(hpwm->pwm[hpwm->Cs][num-1]-hpwm->pwm[hpwm->Cs][num-2]);  //hpwm->geshu需要送人定时器hpwm->pwm【】数据个数
 }
 else
 {
  IoPH;                   //io口电平拉低
  Timer0(2500-hpwm->pwm[hpwm->Cs][hpwm->geshu[hpwm->Cs]-1]);   //将舵机pwm所需低电平时间供出
  num=0;
  hpwm->Cs>=7? hpwm->Cs=0 : ++hpwm->Cs; 
 }
}   

关键字:舵机程序  定时器  32路 引用地址:舵机程序之一个定时器带32路

上一篇:malloc函数及用法
下一篇:外置式PID程序模板

推荐阅读最新更新时间:2024-03-16 14:02

51单片机(二十)—— 定时器产生方波信号
在本文中,我们用定时器0来产生方波信号,包含两个实验,实验1产生一个频率为10kHz的方波信号,实验2产生一个频率为100Hz的方波信号。 实验1 实验1 中定时器0的初始化代码如下所示。 void init_T0(void) { TMOD|= 0x02; //使用方式2,8位自动重装载定时器 TH0=256-50; //给TH0和TL0赋初值,计数周期为50个机器周期 TL0=256-50; //采用12MHz的晶振,计时时长为50us EA=1; //总中断打开 ET0=1; //定时器中断打开 TR0=1; //定时器开关打开 } 代码中将定时器0设置
[单片机]
C51定时器计数器
C51定时器计数器 电路图 定时/计数器的结构和工作原理 1,定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器TH1,TH2组成 TH1+TL0的模是65536,可表达范围0~65535,65535+1时就会溢出产生相关中断 2,TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能; 3,TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志 定时计数器相关寄存器 TCON寄存器(中断的请求与外部中断的选择) IT0和IT1是设置外部中断的触发方式 当其为0时,为低电平触发方式 当其为1时,为负跳变触发方式 IE0和IE1是外部中断标志位 下面是定时/计数器的控制 TF0和
[单片机]
C51<font color='red'>定时器</font>计数器
STM8S003定时器1中断服务程序(PWM)中开启定时器2定时计数
STM8S003定时器1中断服务程序(PWM)中开启定时器2定时定时功能,那么在定时器1中断服务程序退出时,立即就产生了定时器2更新中断,但是轴定时器2中断服务程序中(PWM),开启定时器2定时功能,却工作正常,何故? 这是定时器1中断服务程序的开启定时器2的代码: //TIM2_Cmd(DISABLE); TIM2- CR1 &= (uint8_t)(~TIM2_CR1_CEN); //TIM1_Cmd(DISABLE); TIM1- CR1 &= (uint8_t)(~TIM1_CR1_CEN); gsMOTOR.ucPulseCnt = 0;
[单片机]
PIC单片机定时器1的实际应用
#define uint unsigned int __CONFIG(0x3B31); void init(); uint intnum; void main() { init(); while(1) { /*if(intnum==20) { intnum=0; RD0=!RD0; }*/ } #include #define uchar unsigned char #define uint unsigned int __CONFIG(0x3B31); void init(); uint intnum; void main() { init(); while(1) { /*if(intnum==20) { intnum=0;
[单片机]
PIC单片机<font color='red'>定时器</font>1的实际应用
基于STM32单片机的DLP1700显示电路、光系统改进设计
DLP投影技术是应用美国德州仪器公司开发的数字微镜元件--DMD(Digital Micromirror Device)作为主要关键处理元件以实现数字光学处理过程的技术。DLP显示的色彩清晰度高、艳丽、细腻、逼真,且为全数字显示即可靠性极高,能在各类产品(如大屏幕数字电视、公司/家庭/专业会议投影机和数码相机(DLP Cinema))中提供最佳图像效果。目前,大部分的家用或商用DLP投影机都采用了单片结构,使得其便于移动携带,因而得到越来越广泛的应用。在目前应用发展的基础上,又对其结构的精简性、携带的方便性提出了更高的要求。传统的DLP投影仪是通过DVI接口接收外部信号,并且经过信号转换传送给DLP控制器来控制DLP的显示,占用的
[单片机]
基于STM<font color='red'>32</font>单片机的DLP1700显示电路、光<font color='red'>路</font>系统改进设计
单片机中定时器与计数器的区别
定时器实际上也是计数器,只是计数的是固定周期的脉冲 定时/计数器很容易理解的啊 定时器实际上也是工作在计数方式下,只是计数的是固定周期的脉冲,由于脉冲周期固定,由计数值可以计算时间,有定时功能 定时和计数只是触发来源不同(时钟信号和外部脉冲)其他方面是一样的。 单片机里的寄存器可以看成一个个电子开关,用来切换不同的功能、信号。 51里通过TMOD里的T/C 位切换计数信号的来源 当T/C工作在定时器时,对振荡源12分频的脉冲计数,即每个机器周期计数值加1,计数频率为1/12fosc,当晶振频率 6MHZ 时,计数频率为500KHz,每2us计数值加1;晶振 12MHZ 就是每1us加1 了。 当T/C工作在计数器是,计数脉冲来
[单片机]
STM32F429 >> 14. TIM_(二)_高级定时器 (Code)
基本定时器输出PWM 信号 在该例程中,我将PWM 信号输出管脚连接至LED 管脚,以此观察PWM 信号输出是否正常。 注意:若要对LED 管脚进行初始化配置,对应LED 不能设置为熄灭,否则PWM 信号不能点亮LED bsp_tim_advanced.h /** ****************************************************************************** * @file bsp_tim_advanced.h * @author Waao * @version V1.0.0 * @date 30-Jan-2019 * @brief Thi
[单片机]
基于51单片机的方波发生程序
这是一个最简单的程序,在定时器的控制下由p1.0脚发出500赫兹的方波 要求:6MHz的晶振,P1.0引脚产生500Hz的方波 代码如下: #include reg52.h sbit P1_0=P1^0; void int_X_T() { IE=0x82; TMOD=0x01; TH0=(65536-500)/256; TL0=(65536-500)%256; TR0=1;?? ?? } void int_x() interrupt 1 { TH0=(65536-500)/256; TL0=(65536-500)??%256; P1_0=!P1_0; } void main()?
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved