中级会员
- 积分
- 246
- 威望
- 224
- 贡献
- 20
- 兑换币
- 0
- 注册时间
- 2010-3-4
- 在线时间
- 1 小时
|
#include <hidef.h> /* common defines and macros */
#include <MC9S12XS128.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
#define ATD_SEQURE 8 //定义转换序列长度
#define Steer_Center 1500 //设定舵机中间值
#define Speed_Wanted 10 //目标速度
#define Speed_K 100 //速度Kp
#define Steer_K 40 //舵机Kp
#define Steer_left 1250 //舵机左侧限幅
#define Steer_right 1750 //舵机右侧限幅
unsigned char LedCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char LedData[]={0,0,0,0};
unsigned char LedNum = 0;
uchar ad_data[ATD_SEQURE]; //存放AD转换结果
int speed; //存放脉冲累加结果
int LED_offset; //光电管偏移量
uchar Black_num; //检测到的黑线的数目
int Line_center; //中心线位置
uchar Get_Line; //指示此次有无检测到黑线
int Pre_Control_Speed=0;
int Control_Speed;
int Control_Steer;
int Pre_offset=0;
int This_offset=0;
uchar b;
#pragma CODE_SEG DEFAULT
void ATD_init(void){ //ATD初始化
ATD0CTL0 = 0x07; //多路转换时转换8路
ATD0CTL1_SRES = 0; //转换精度为8位
ATD0CTL2_AFFC = 1; //中断标志位自动清零
ATD0CTL2_ASCIE = 1; //一个序列传唤结束触发中断
ATD0CTL3 = 0xC0; //结果寄存器对齐方式右对齐,转换序列长度为8,循环转换,freeze模式下继续转换
ATD0CTL4 = 0x00; //采样周期为4个周期,atdclk=busclk/2*(0+1),无锁相环总线时钟为8M,故
//ATDclk=4M
ATD0CTL5_SCAN = 1; //连续转换模式
ATD0CTL5_MULT = 1; //多通道采样
}
void initGPIO(void){ //通用IO口初始化
DDRA = 0x00; //A口输入
DDRB = 0xFF; //B口输出
DDRK = 0xFF; //K口输出
}
void initPWM(void){ //PWM初始化
PWME=0x00; //关闭所有PWM通道
PWMPOL = 0xFF; //PWM极性选择,选择一个周期开始时为高电平
PWMPRCLK = 0x33; //CLOCK A,B时钟分频,均选择从总线四分频 1M
//PWMSCLA = 5; //CLOCK SA从CLOCK A十分频,1M
//PWMSCLB = 5; //CLOCK SB从CLOCK B十分频,1M
PWMCTL = 0xF0; //01级联,23级联,45级联,67级联
PWMCLK = 0x00; //PWM始终选择,选择CLOCK A B为PWM时钟
PWMPER01=200; //电机PWM正转频率5k
PWMDTY01=0;
PWMPER23=200;
PWMDTY23=0; //电机反转频率为1k
PWMPER45=20000; //舵机PWM频率为50Hz
PWMDTY45=Steer_Center; //舵机占空比
PWME_PWME3=1;
PWME_PWME1=1; //电机PWM波开始输出
PWME_PWME5=1; //舵机PWM波开始输出
}
void InitRTI(void) { // 实时中断初始化
RTICTL = 0x8F; //20ms中断一次
CRGINT = 0x80; // 开实时中断
}
void InitPACNT(void){
PACTL = 0x40; //脉冲累加功能,下降沿计数
PACNT = 0;
}
void main(void) {
/* put your own code here */
DisableInterrupts;
ATD_init();
InitRTI();
initGPIO();
initPWM();
InitPACNT();
EnableInterrupts;
for(;;) {} /* wait forever */
/* please make sure that you never leave this function */
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 7 RTI_INT(void) {
int j;
uchar a;
uchar i;
DisableInterrupts; //关中断
speed = PACNT; //读脉冲累加寄存器
PACNT = 0; //脉冲累加器置0
Pre_offset = This_offset; //偏差信号赋值
This_offset = (int)(Speed_Wanted)-speed;
LED_offset = 0;
Black_num = 0;
/*for(i=0;i<ATD_SEQURE;i++){
if(ad_data[i]<Threshold||ad_data[i]==Threshold){
Threshold = ad_data[i]; a=i;
Black_num++;
}
} */
if(ad_data[0]<10){ Black_num++; a=0; //第0个传感器阈值
}
if(ad_data[1]< 60){ Black_num++; a=1; // 第1个传感器阈值
}
if(ad_data[2]<10){ Black_num++; a=2; // 第2个传感器阈值
}
if(ad_data[3]< 20){ Black_num++; a=3; // 第3个传感器阈值
}
if(ad_data[4]<80){ Black_num++; a=4; // 第4个传感器阈值
}
if(ad_data[5]< 20){ Black_num++; a=5; // 第5个传感器阈值
}
if(ad_data[6]< 10){ Black_num++; a=6; // 第6个传感器阈值
}
if(ad_data[7]< 20){ Black_num++; a=7; // 第7个传感器阈值
}
if(Black_num!=0){
if(Black_num==1) {
//Line_center = LED_offset/(uint)(Black_num);
Line_center = (uint)(a*2-7);
Get_Line = 1;
}
else EnableInterrupts;
}
else{
Get_Line = 0;
}
Pre_Control_Speed = Control_Speed;
Control_Speed = Pre_Control_Speed + (int)(Speed_K)*(This_offset-Pre_offset); //P控制式,增量式
if(Control_Speed>200){ //限幅控制
Control_Speed=200;
}
else if(Control_Speed<0){
Control_Speed=0;
}
Control_Steer=(int)(Steer_Center) - (int)(Steer_K)*Line_center; //舵机P控制式,位置式
if(Control_Steer<Steer_left){ //舵机输出值限幅
Control_Steer = Steer_left;
}
else if(Control_Steer>Steer_right){
Control_Steer = Steer_right;
}
if(Control_Steer>1540||Control_Steer<1460) { //如有拐弯,减速,转向
PWMDTY01 = 0; PWMDTY45 = Control_Steer;
for(i=0;i<100;i++) { //延时一段时间,减速
for(j=0;j<3;j++){
}
}
PWMDTY01 = 100;
}
else {
PWMDTY45 = Control_Steer;
PWMDTY01 = Control_Speed;
}
// PWMDTY01 = Control_Speed; //舵机控制
LedData[0] = 0;
LedData[1] = Control_Speed/100%10;
LedData[2] = Control_Speed/10%10;
LedData[3] = Control_Speed%10;
PORTK = 0x01 << LedNum;
PORTB = LedCode[LedData[LedNum]];
LedNum++;
if(LedNum >= 4)
LedNum = 0;
CRGFLG = 0x80;
EnableInterrupts; //开中断
}
interrupt 22 void ATD_Process(void){ //AD转换中断服务程序
DisableInterrupts; //关中断
ad_data[0] = ATD0DR0L;
ad_data[1] = ATD0DR1L;
ad_data[2] = ATD0DR2L;
ad_data[3] = ATD0DR3L;
ad_data[4] = ATD0DR4L;
ad_data[5] = ATD0DR5L;
ad_data[6] = ATD0DR6L;
ad_data[7] = ATD0DR7L;
EnableInterrupts; //开中断
}
#pragma CODE_SEG DEFAULT |
|