专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

ARM9舵机程序

作者:蓝梦荒   来源:本站原创   点击数:  更新时间:2013年12月09日   【字体:

/*****************************************************************************************************************************
S3C2440A 具有5 个16 位定时器,每个定时器可以按照中断模式或DMA 模式工作。定时器0,1,2,3 具有PWM 功能。定时器4 是一个内部定时器,不具有对外输出口线。定时器0 还具有死区发生器,通常用于大电流设备。
定时器特性总结如下。
● 5 个16 位定时器可以工作在中断模式或DMA 模式。
● 包括2 个8 位预分频器、2 个4 位分割器。
● 输出波形的占空比可用编程控制(即进行脉宽调制)。
● 具有自动重载模式或单次触发模式。
● 具有死区发生器。
 
与定时器相关的寄存器有:TCFG0、TCFG1、TCON、TCMPBn、TCNTBn、TCNTOn
定时器的频率由PCLK分频而来,即Ftimer = PCLK / (prescaler+1) / MUX
prescaler位于TCFG0,MUX位于TCFG1
TCON控制定时器的运行:是否自动装载定时器初值,是否手动装载,开始/停止 定时器。
TCNTBn放定时器n的初值,装载用
TCMPBn放定时器n的匹配值,用于调至PWM
TCNTOn,只读,用于观察定时器n的初值

编程方法如下:
定时器初始化()
{
 设置预分频器prescaler (TCFG0)
 设置MUX    (TCFG1)
 赋初值TCNTB    TCNTB    =   (PCLK / (prescaler+1) / MUX) * 中断时间间隔(单位秒)
 TCON: 手动跟新打开 
 手动跟新关闭
 自动装载(计时器循环计数)
 启动定时器
}

中断初始化()
{
 清除SRCPNF、INTPND中的相应中断标志位(可以调用ClearPending函数)
 填入中断例程地址于中断向量表 pISR_TIMER1
 使能相应中断 rINTMSK
}
 
中断例程()  __irq
{
 ……中断程序……
 清除SRCPND、INTPND中的相应中断标志位
}
 

******************************************************************************************************************************/

//以下驱动对于PCLK=50MHZ的开发板可以直接添加到工程中使用,GPG14引脚对应一路舵机,需要的话可以在添加7路

#include "2440addr.h"
#include "def.h"
typedef unsigned int uint32;
#define ClearPending(bit) {rSRCPND |= bit;rINTPND = rINTPND;}//宏定义清零中断标志位
#define RGB(r,g,b)   (unsigned int)(r << 16) + (g << 8) + b
extern unsigned int  pwm[8];
extern unsigned int  *p;//锁定指针所指的数组,防止跑偏
void __irq timer0_ISR(void);
void sifuTimer0(unsigned int);
void Task1(void);
void Glib_FilledRectangle(int x1,int y1,int x2,int y2,int color);
void BUZZER_PWM_Test( void );
void int_time0_init(void)
{
 //Uart_Printf("Timer0中断实验\n");
 //p=pwm;   //指针初始化
 ClearPending(1<<10);     //清楚中断标志
 pISR_TIMER0=(unsigned)timer0_ISR;  //填入中断例程地址于中断向量表
 rINTMSK&=~(1<<10);       //TIME0开中断
 }
 
void __irq timer0_ISR(void) //定时器中断函数
{
 static char n,biaozhi;
 static unsigned int hhe,good;
 good++;
  n++;
 switch(n)
 {
 case 1:  sifuTimer0(*p-400); rGPGDAT|=1<<14; break;
 case 2:  sifuTimer0(2900-*p); rGPGDAT&=~(1<<14);n=0; break;
 case 3:  sifuTimer0(*(p+1)); break;
 case 4:  sifuTimer0(2500-*(p+1)); break;
 case 5:  sifuTimer0(*(p+2)); break;
 case 6:  sifuTimer0(2500-*(p+2)); break;
 case 7:  sifuTimer0(*(p+3)); break;
 case 8:  sifuTimer0(2500-*(p+3)); break;
 case 9:  sifuTimer0(*(p+4)); break;
 case 10:  sifuTimer0(2500-*(p+4)); break;
 case 11:  sifuTimer0(*(p+5)); break;
 case 12:  sifuTimer0(2500-*(p+5)); break;
 case 13:  sifuTimer0(*(p+6)); break;
 case 14:  sifuTimer0(2500-*(p+6)); break;
 case 15:  sifuTimer0(*(p+7)); break;
 case 16:  sifuTimer0(2500-*(p+7)); n=0; break;
 }
 if(good==100)
 {
// Task1();
 good=0;
 }
/*biaozhi?(*p)++:(*p)--;
if(*p>=2050)
 biaozhi=0;
 else if(*p<=50)
  biaozhi=1;*/
 ClearPending(1<<10);    //清楚中断标志
}


void  time0_init(void)
{
 rTCFG0 = (rTCFG0 &(~0xFF)) | 24; 
 rTCFG1 = (rTCFG1 &(~0xF)) | 0;  
 rTCNTB0 = 1500;    
 rTCON |= 1<<1;       //开启手动更新,将TCNTB0的值载入定时器0
 rTCON &= ~(1<<1);      //关闭手动更新(必须)
 rTCON |=0x1<<0; //开启定时器,关闭自动装载模式
 rGPGCON|=1<<28;        //舵机输出引脚初始化
 rGPGUP=0x00;    //舵机输出引脚初始化
 
//关于中断时间的设定:    TCNTB =(PCLK / (prescaler+1) / MUX) *  中断时间间隔(单位秒)
}
//装载的频率是1MHz 
void sifuTimer0(U32 us)
{
 rTCON |= 1<<1; //开启手动更新,将TCNTB0的值载入定时器0
 rTCNTB0=us;     
    rTCON &= ~(1<<1);      //关闭更新
}

//***********************************************************************************************************
void Task1(void)   
{
  static unsigned int task1Cnt=0;
 //实现流水灯
  if((task1Cnt%5 == 0))
   rGPBDAT = 0x1E0;    //全灭
  else
  rGPBDAT = rGPBDAT - (0x10<<(task1Cnt%5));
  task1Cnt++;
}

关闭窗口

相关文章