中级会员
- 积分
- 227
- 威望
- 189
- 贡献
- 26
- 兑换币
- 6
- 注册时间
- 2009-4-8
- 在线时间
- 6 小时
|
#include <hidef.h> /* common defines and macros */
#include <MC9S12XS128.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
/*********************************************************************************/
/* *********** 角度检测 *********** */
/*********************************************************************************/
int Angle_Cur ; // 当前竖直角度
int Angle_Last ; // 之前竖直角度
int Angle ; // 绝对偏移角度
int Angle_Velocity_V; // 竖直角速度,也是相对偏移角度
int Angle_Last2;
unsigned char RxData; //串口数据
int output_right;
#define MOTOR_PERIOD 1000 // 直流电机PWM周期
#define MOTOR_RIGHT_PER1 PWMPER01 // 右电机正转PWM周期
#define MOTOR_RIGHT_DTY1 PWMDTY01 // 右电机正转PWM占空比
#define MOTOR_RIGHT_PER0 PWMPER23 // 右电机反转PWM周期
#define MOTOR_RIGHT_DTY0 PWMDTY23 // 右电机反转PWM占空比
/*===============================================================================*/
/* ------------- I/O口初始化 ------------ */
/*===============================================================================*/
void IO_Init(void)
{
DDRA = 0xFF; // PORT A 拨码开关输出
PORTA = 0xFF;
DDRB = 0xFF; // PORT B LED输出
PORTB = 0x00;
}
/*===============================================================================*/
/* ------------ 锁相环初始化 ------------ */
/*===============================================================================*/
// PLL_CLOCK = 2 * OSC_CLOCK * (SYNR + 1) / (REFDV + 1); BUS_CLOCK = PLL_CLOCK / 2
void PLL_Init(void)
{
CLKSEL_PLLSEL = 0; // 选择晶振为系统时钟源
PLLCTL_PLLON = 0; // 关闭PLL
REFDV = 0x43;
SYNR = 0x49; // BUS_CLOCK = 2 * 16MHz * (9 + 1) / (3 + 1) / 2 = 40MHz
PLLCTL_PLLON = 1; // 打开PLL
while(CRGFLG_LOCK == 0); // 等待锁相环稳定
CLKSEL_PLLSEL = 1; // 选择PLL为时钟源
}
/*===============================================================================*/
/* ------------ 定时器初始化 ------------ */
/*===============================================================================*/
void ECT_Init(void)
{
TIOS = 0x00; // 设为输入捕捉
TSCR1_TEN = 1; // 定时器使能
TSCR2_TOI = 0; // 禁止定时器溢出中断
TCTL3 = 0xA0; // 触发边沿:下降沿
TIE = 0xC0; // 中断允许
TFLG1 = 0xFF; // 清除输入捕捉/输出比较中断标志
}
/*===============================================================================*/
/* -------- 周期中断定时器初始化 -------- */
/*===============================================================================*/
// 定时周期 = (PITLD + 1) * (PITMTLD + 1) * BUS_CLOCK
void PIT_Init(void)
{
PITMUX = 0x00; // 与微定时器0相关联
PITLD0 = 0x9C3F;
PITMTLD0 = 0x09; // 定时周期 = (39999 + 1) * (19 + 1) / 40MHz = 20ms
PITINTE_PINTE0 = 1; // 通道0中断使能
PITTF_PTF0 = 1; // 清除通道0中断标志位
PITCE_PCE0 = 1; // 周期中断定时期通道0使能
PITCFLMT_PITE = 1; // 周期中断定时器使能
}
/*===============================================================================*/
/* ------------- 串口初始化 ------------ */
/*===============================================================================*/
void SCI_Init(void)
{
SCI0BDL = 0x83;
SCI0BDH = 0x80; // Bt = BUS_CLOCK / (32 * BR) = 40M / (32 * 131) = 9541 bit/s
SCI0CR1 = 0x00; // 8位数据,无校验
SCI0CR2 = 0x2C; // 允许发送与接受
}
void PWM_Init(void)
{
//-------------------------------------------------------------------------------//
// 禁止PWM输出
PWME = 0x00;
//-------------------------------------------------------------------------------//
// 01,23,45 ,67 通道级联
PWMCTL_CON01 = 1;
PWMCTL_CON23 = 1;
PWMCTL_CON45 = 1;
PWMCTL_CON67 = 1;
PWMPOL = 0xFF;
PWMCAE = 0x00;
PWMCLK = 0x00;
PWMPRCLK = 0x33;
//-------------------------------------------------------------------------------//
// 左、右电机的周期和占空比设定
MOTOR_RIGHT_PER1 = MOTOR_PERIOD; // 5MHz / 2500 = 2kHz
MOTOR_RIGHT_DTY1 = 0; // 1250 / 2500 = 50%
MOTOR_RIGHT_PER0 = MOTOR_PERIOD;
MOTOR_RIGHT_DTY0 = 0;
//-------------------------------------------------------------------------------//
PWME = 0xAA;
}
void AD_Init(void)
{
ATD0CTL1=0x00;//12位精度
ATD0CTL2=0x40;//禁止外部触发,标志位快速清零,中断禁止
ATD0CTL3=0x90;//右对齐无符号.转换序列长度为2,No FIFO模式,Freeze模式下继续转换
ATD0CTL4=0x43;//4AD采样周期,ATDClock=[BusClock*0.5]/[PRS+1] =4MHz ; PRS=3
ATD0CTL5=0x30;//特殊通道禁止,单通道采样,扫描模式连续采样,
ATD0DIEN=0x00;//禁止数字输入
}
void Sys_Init(void)
{
DisableInterrupts;
//-------------------------------------------------------------------------------//
// I/O口初始化
IO_Init();
//-------------------------------------------------------------------------------//
// 锁相环初始化
PLL_Init();
//-------------------------------------------------------------------------------//
// 定时器初始化
ECT_Init();
//-------------------------------------------------------------------------------//
// 周期中断定时器初始化
PIT_Init();
//-------------------------------------------------------------------------------//
// PWM初始化
PWM_Init();
//-------------------------------------------------------------------------------//
// 串口初始化
SCI_Init();
//-------------------------------------------------------------------------------//
// AD初始化
AD_Init();
EnableInterrupts;
}
void
SCI_Tx( char TxData )
{
SCI0DRH
= 0;
SCI0DRL
= TxData;
//将待发数据写入寄存器
while( !SCI0SR1_TDRE );
//等待发送结束
}
//-------------------------------------------------------------------------------//
//绝对值
int Abs(int abs)
{
if (abs>0)
return abs;
else
{
abs=0-abs;
return abs;
}
}
//平衡控制
void Car_Control(void)
{
int P,I,D;
Angle = 121-Angle_Cur; //绝对角度减去实际角度,绝对角度模拟值为2.5V,则8位AD转换后为128
if(Angle>-1&&Angle<1)
{
P = 40* (Angle - Angle_Last);
I = 23*Angle;
D = 30*(Angle_Cur - 2 * Angle_Last + Angle_Last2);
Angle_Last2 = Angle_Last;
Angle_Last = Angle;
output_right = P+I+D;
}else{
Angle_Last = Angle_Cur;
Angle_Last2 = Angle_Cur - Angle_Last;
output_right = 80* Abs(Angle) + 400* Angle_Last2;
}
if( Angle >0)
{
MOTOR_RIGHT_DTY1 = output_right; // 右电机正转PWM占空比
MOTOR_RIGHT_DTY0 =0; // 右电机反转PWM占空比
} else if(Angle<0)
{
Angle =0-Angle; //取绝对值
MOTOR_RIGHT_DTY0 =output_right; // 右电机正转PWM占空比
MOTOR_RIGHT_DTY1 =0; // 右电机反转PWM占空比
}
else
{
MOTOR_RIGHT_DTY1=0;
MOTOR_RIGHT_DTY0=0;
}
}
void main(void)
{
Sys_Init();
for(;;)
{
Car_Control();
PORTB
= ~( byte ) ATD0DR0L ;//显示转换结果
}
}
// 用于测量赛车速度,周期20ms
__interrupt 66 void Vpit0_ISR(void)
{
PITTF_PTF0 = 1;
while( !ATD0STAT0_SCF );
//等待一个序列结束
Angle_Cur = ( int )ATD0DR0L;
}
interrupt 20 void SCI_Rx_IRS( void )
{
DisableInterrupts;
RxData
= SCI0DRL;
EnableInterrupts;
}
#pragma CODE_SEG DEFAULT |
|