utils.c
来自「一个机器人开发的相关嵌入式开发源码」· C语言 代码 · 共 585 行 · 第 1/2 页
C
585 行
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* utils.c - utility library for SRV-1 robot
* Copyright (C) 2005-2006 Surveyor Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details (www.gnu.org/licenses)
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "utils.h"
/*****************************************************************************
*
* Description:
* Routine for printing integer numbers in various formats. The number is
* printed in the specified 'base' using exactly 'noDigits', using +/- if
* signed flag 'sign' is TRUE, and using the character specified in 'pad'
* to pad extra characters.
*
* Params:
* [in] base - Base to print number in (2-16)
* [in] noDigits - Number of digits to print (max 32)
* [in] sign - Flag if sign is to be used (TRUE), or not (FALSE)
* [in] pad - Character to pad any unused positions
* [in] number - Signed number to print
*
****************************************************************************/
void
printNumber(unsigned char base,
unsigned char noDigits,
unsigned char sign,
unsigned char pad,
unsigned int number)
{
static unsigned char hexChars[16] = "0123456789ABCDEF";
unsigned char *pBuf;
unsigned char buf[32];
unsigned int numberAbs;
unsigned int count;
// prepare negative number
if(sign && (number < 0))
numberAbs = -number;
else
numberAbs = number;
// setup little string buffer
count = (noDigits - 1) - (sign ? 1 : 0);
pBuf = buf + sizeof(buf);
*--pBuf = '\0';
// force calculation of first digit
// (to prevent zero from not printing at all!!!)
*--pBuf = hexChars[(numberAbs % base)];
numberAbs /= base;
// calculate remaining digits
while(count--)
{
if(numberAbs != 0)
{
//calculate next digit
*--pBuf = hexChars[(numberAbs % base)];
numberAbs /= base;
}
else
// no more digits left, pad out to desired length
*--pBuf = pad;
}
// apply signed notation if requested
if(sign)
{
if(number < 0)
*--pBuf = '-';
else if(number > 0)
*--pBuf = '+';
else
*--pBuf = ' ';
}
// print the string right-justified
uart0SendString(pBuf);
}
/*****************************************************************************
*
* Description:
* Delay execution by a specified number of microseconds by using
* timer #1. A polled implementation.
*
* Params:
* [in] delayInUs - the number of microseconds to delay.
*
****************************************************************************/
void
delayUs(unsigned int delayInUs)
{
/*
* setup timer #1 for delay
*/
TIMER1_TCR = 0x02; //stop and reset timer
TIMER1_PR = 0x00; //set prescaler to zero
TIMER1_MR0 = delayInUs * ((CRYSTAL_FREQUENCY * PLL_FACTOR)/ (1000000 * VPBDIV_FACTOR));
TIMER1_IR = 0xff; //reset all interrrupt flags
TIMER1_MCR = 0x04; //stop timer on match
TIMER1_TCR = 0x01; //start timer
//wait until delay time has elapsed
while (TIMER1_TCR & 0x01)
;
}
/*****************************************************************************
*
* Description:
* Initialize timer #0 as real time clock (in milliseconds)
* read TIMER0_TC to get current time
*
* NOTE - timer will cycle to zero every 49.71 days
*
****************************************************************************/
void
initRTC(void)
{
TIMER0_TCR = 0x02; //stop and reset timer
TIMER0_IR = 0xff; //reset all interrrupt flags
TIMER0_PR = ((CRYSTAL_FREQUENCY * PLL_FACTOR)/ (1000 * VPBDIV_FACTOR)); // prescale for 1ms tics
TIMER0_TCR = 0x01; //start timer
}
/*****************************************************************************
*
* Description:
* Initialize the PWM unit to generate a variable duty cycle signal on
* PWM2 and PWM5.
* The function sets initial frequency. Initial duty cucle is set to 0%.
*
* Params:
* [in] initialFreqValue - the initial frequency value. Value calculated as:
*
* (crystal frequency * PLL multiplication factor)
* -----------------------------------------------
* (VPBDIV factor * desired frequency)
*
****************************************************************************/
void
initPwm(unsigned int initialFreqValue)
{
/*
* initialize PWM
*/
PWM_PR = 0x00000000; //set prescale to 0
PWM_MCR = 0x0002; //counter resets on MR0 match (period time)
PWM_MR0 = initialFreqValue; //MR0 = period cycle time
PWM_MR2 = 0; //MR2 = duty cycle control, initial = 0%
PWM_MR5 = 0; //MR5 = duty cycle control, initial = 0%
PWM_LER = 0x25; //latch new values for MR0 and MR2 and MR5
PWM_PCR = 0x2400; //enable PWM2 and PWM5 in single edge control mode
PWM_TCR = 0x09; //enable PWM and Counter
/*
* connect signal PWM2 to pin P0.7
*/
PINSEL0 &= ~0x0000c000; //clear bits related to P0.7
PINSEL0 |= 0x00008000; //connect signal PWM2 to P0.7 (second alternative function)
/*
* connect signal PWM5 to pin P0.21
*/
PINSEL1 &= ~0x00000c00; //clear bits related to P0.21
PINSEL1 |= 0x00000400; //connect signal PWM5 to P0.21 (second alternative function)
/*
* connect motor direction signals to pins p0.22 p0.23
*/
PINSEL1 &=0xffff0fff;
IODIR0 |= 0x00c00000;
IOSET0 |= 0x00c00000;
}
/*****************************************************************************
*
* Description:
* Initialize the PWM unit to generate a servo control signals on
* PWM2 and PWM5.
*
* pulse width ranges from 1.0ms to 2.0ms, and pulse is updated 50 times/sec
*
* initial pulse is set to 1.5ms
*
****************************************************************************/
void
initServos()
{
/*
* initialize dual edge PWM
*/
PWM_PR = 0x00000000; //set prescale to 0
PWM_MCR = 0x0002; //counter resets on MR0 match (period time)
PWM_MR0 = (CRYSTAL_FREQUENCY * PLL_FACTOR)/ (VPBDIV_FACTOR * 50); // 50H update rate
PWM_MR1 = 0; //MR2 initial = 1.6ms pulse
PWM_MR2 = (PWM_MR0 * 160) / 2000;
PWM_MR4 = 0; //MR5 initial = 1.5ms pulse
PWM_MR2 = (PWM_MR5 * 150) / 2000;
PWM_LER = 0x37; //latch new values for MR0 and MR2 and MR5
PWM_PCR = 0x2424; //enable PWM2 and PWM5 in dual edge control mode
PWM_TCR = 0x09; //enable PWM and Counter
/*
* connect signal PWM2 to pin P0.7
*/
PINSEL0 &= ~0x0000c000; //clear bits related to P0.7
PINSEL0 |= 0x00008000; //connect signal PWM2 to P0.7 (second alternative function)
/*
* connect signal PWM5 to pin P0.21
*/
PINSEL1 &= ~0x00000c00; //clear bits related to P0.21
PINSEL1 |= 0x00000400; //connect signal PWM5 to P0.21 (second alternative function)
/*
* connect motor direction signals to pins p0.22 p0.23
*/
PINSEL1 &=0xffff0fff;
IODIR0 |= 0x00c00000;
IOSET0 |= 0x00c00000;
}
/*****************************************************************************
*
* Description:
* Update the duty cycle value of the PWM signal.
*
* Params:
* [in] dutyValue - the new duty cycle value in percent in increments
* of 0.01% (i.e., 10% = 1000).
*
****************************************************************************/
void
setPwmDutyPercent(int mleft, int mright)
{
PWM_MR5 = (PWM_MR0 * abs(mright)) / 100; //update duty cycle - right motor
PWM_MR2 = (PWM_MR0 * abs(mleft)) / 100; //update duty cycle - left motor
PWM_LER = 0x24; //latch new values for MR2 and MR5
if (mleft >= 0)
IOSET0 |= 0x00400000;
else
IOCLR0 |= 0x00400000;
if (mright >= 0)
IOSET0 |= 0x00800000;
else
IOCLR0 |= 0x00800000;
}
/*****************************************************************************
*
* Description:
* Update the pulse width of servo control signals.
*
* Params:
* [in] mleft, mright - between 0 and 100 translates to pulse of 1ms to 2ms
* value of 50 generates 1.5ms pulse
*
****************************************************************************/
void
setServos(int mleft, int mright)
{
if ((mleft < 0) || (mleft > 100))
mleft = 50;
if ((mright < 0) || (mright > 100))
mright = 50;
PWM_MR2 = (PWM_MR0 * (100+mleft)) / 2000; //update duty cycle - left motor
PWM_MR5 = (PWM_MR0 * (100+mright)) / 2000; //update duty cycle - right motor
PWM_LER = 0x2424; //latch new values for MR2 and MR5
}
/*****************************************************************************
*
* Description:
* Initialize p0.24 p0.25 p0.26 p0.27 for IR LEDs
*
****************************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?