#include "Includes.h"
void main(void)
{
DisableInterrupts;
xianshi_init();
vPLLInit();
PWM_Init();
Timerch2Init() ;
delay(3500);
vIOPortInit();
EnableInterrupts;
//delay(1500);
asm(nop);
asm(nop);
for(;;)
{
Image_binaryzation();
black_extract();
control_actuator();
}
}
//************************************************************************
*
//*
*
//* ***********************头文件及宏定义*******************
*
//*
*
//************************************************************************
*
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
#include <hidef.h> /* common defines and macros */
#include <MC9S12XS128.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
//************************************************************************
*
//* ***********************初始化****************************
*
//************************************************************************
*
#include "Init.h"
//************************************************************************
*
//* ***********************数据采集****************************
*
//************************************************************************
*
#include "ImageAcquisition.h"
//************************************************************************
*
//* ***********************图像处理函数************************
*
//************************************************************************
*
#include "ImageProcess.h"
//************************************************************************
*
//* ***********************调试函数****************************
*
//************************************************************************
*
#include "Function.h"
//************************************************************************
*
//* ***********************自动控制函数************************
*
//************************************************************************
*
#include "Control.h"
#endif
#ifndef __INIT_H__
#define __INIT_H__
extern void vPLLInit(void); //锁相环初始化
//extern void vECTInit(void); //定时器初始化
extern void vIOPortInit(void); //I/O 口初始化
extern void PWM_Init(void); //PWM 初始化
extern void Timerch2Init(void);
#endif
#include "Includes.h"
//锁相环初始化
void vPLLInit(void)
{
CLKSEL=0x00; //48mhz
PLLCTL_PLLON=1;
SYNR=0XC0 | 0X05;
REFDV=0XC0 | 0X01;
POSTDIV=0X00;
_asm(nop);
_asm(nop);
while(0==CRGFLG_LOCK);//锁相环锁定
CLKSEL_PLLSEL=1;//选定外部时钟
}
//定时器初始化
/*void vECTInit(void)
{
TIOS =0x00;//定时器通道0,1 为输入捕捉
TSCR1=0x80;//定时器使能
TCTL4=0x09;//通道0 捕捉上升沿通道1 捕捉下降沿
TIE=0x03; //通道0,1 中断使能
TFLG1=0xFF;//清中断标志位
} */
void Timerch2Init(void)
{
//TSCR2 = 0x04; // 禁止定时器溢出中断,计数器自由运行,禁止复位,预分频系
数为16
// busclock/16=48Mhz/16=3000000
TIOS = 0x00; // 设置通道2 工作在输出比较状态,其它通道工作在输入状态
//TC2 = 0x2328; // 0x2328*(1/3000000)=3ms
//TCTL2 = 0x00; // 切断OC2 与输出引脚断开
// TCTL3=0X80;
TCTL4=0x09;
//TSCR1_TFFCA=1; // 通道自动清除
TIE= 0x83; // 通道0,1,2,7 中断使能
//TIE= 0x84;
TSCR1_TEN = 1; // 定时器使能
PACTL = 0x40; //脉冲累加器使能,事件计数,下降沿计数,16 位A 累加器
PACNT = 0x0000;
TFLG1=0xFF; //清中断标志位
}
//端口初始化
void vIOPortInit(void)
{
DDRM=0x00;//M 口为输入口
DDRB=0x0FF;//B 口为输出口在指示中心位置
DDRK_DDRK0 = 1; //K0,K1 为输出口
全国大学生智能汽车邀请赛技术报告
47 / 82
DDRK_DDRK1 = 1;
asm(nop);
asm(nop);
PORTB=0x0FF; //B 口为高电平
PORTK_PK0 = 1; //电机使能K0=1;K1=0;
PORTK_PK1 = 0;
}
//pwm 初始化
void PWM_Init(void)
{
PWME = 0x00; //pwm 禁止
PWMCTL = 0x10; //通道0,1 级联,形成16 位pwm 通道
PWMPRCLK = 0x00; //clockA,B 分频值为总线时钟的0 分频,40MHz
PWMSCLA = 6; //clockSA 的频率为4MHz
PWMSCLB = 12; //clockSB 的频率为2MHz
PWMCLK = 0x0FF; //时钟来源选择 clockSA clockSB
PWMPOL = 0x0FF; //在周期开始时,PWM 所有通道输出高电平
PWMCAE = 0x00; //所有PWM 通道输出左对齐
PWMPER01 = 40000; //PTP1 输出频率100Hz
PWMDTY01 = steer_centre; //通道1 占空比0.075 右极限7200 左极限4700
PWMPER2 = 200; /*PTP1 输出频率10000Hz*/
PWMDTY2 = 88; /*通道1 占空比0.1*/
PWME = 0x06; //PWM1.2 输出
}
#ifndef __IMAGEPROCESS_H__
#define __IMAGEPROCESS_H__
extern unsigned int Line_Center[ROW_VALUE];//黑线中心数组
extern void Image_binaryzation(void); //图像的二值化和缓存交换
extern void black_extract(void); //黑线提取程序
#endif
#include "Includes.h"
//************图像二值化和数据交换****************//
#define stop_time 300
#define stop_sep_min 15
#define stop_sep_max 30
#define THRESHOLD 40 //黑白阈值白天45 晚上35
#define WHITE 1 //白点
#define BLACK 0 //黑点
#define BLACK_LINE_MAX0 11 //最大黑线宽度0
#define BLACK_LINE_MIN0 4 //最小黑线宽度0
#define BLACK_LINE_MAX1 8 //最大黑线宽度1
#define BLACK_LINE_MIN1 2 //最小黑线宽度1
#define BLACK_LINE_MAX2 6 //最大黑线宽度2
#define BLACK_LINE_MIN2 1 //最小黑线宽度2
#define LEFT_LIMIT 1 //左极限黑线位置
#define RIHGT_LIMIT 84 //右极限黑线位置
#define BLACK_LOSTED 3 //黑线丢失限度
#define EDGE_SEP_MAX 8 //最大边缘间距
#define EDGE_SEP_MIN 5 //最大边缘间距
#define ROW_MIN 1 //黑线搜索起始
#define ROW_MIDDLE 6 //黑线搜索中间
#define ROW_MAX 25 //黑线搜索末尾
unsigned int Line_Center[ROW_VALUE];//定义黑线中心数组
void Image_binaryzation(void) //二值化程序
{ unsigned char *p_Image;
unsigned char *q_Image;
q_Image=&uca_Buffer1[0][0];
for(p_Image=&uca_Buffer[0][0];p_Image<=&uca_Buffer[ROW_VALUE-1][COLUMN_
VALUE-1];p_Image++)
{if((*p_Image<THRESHOLD)&&(*(p_Image+1)<THRESHOLD))*(q_Image++)=BLAC
K;
else
*(q_Image++)=WHITE;
}
/*unsigned thread=40;
unsigned char ucRow,ucColumn,min,max;
unsigned char *pucTemp;
q_Image=&uca_Buffer1[0][0];
p_Image=&uca_Buffer[0][0];
全国大学生智能汽车邀请赛技术报告
50 / 82
for(ucColumn=0;ucColumn<ROW_VALUE ;ucColumn++)
{ min=50,max=80;
if(ucColumn>=ROW_MAX)
{
for(ucRow=0;ucRow<COLUMN_VALUE;ucRow++)
{
pucTemp=p_Image+ucColumn*COLUMN_VALUE+ucRow;
if(*pucTemp<min)
min= *pucTemp;
else if(*pucTemp>max)
max=*pucTemp;
}
thread=(max+min)/2;
}
for(ucRow=0;ucRow<COLUMN_VALUE;ucRow++)
{
pucTemp=p_Image+ucColumn*COLUMN_VALUE+ucRow;
if((*pucTemp<thread)&&(*(pucTemp+1)<thread))
*(q_Image++)=BLACK;
else
*(q_Image++)=WHITE;
}
}*/
}
//*******************黑线的提取**********************//
void black_extract(void)
{
unsigned char black_lost=0;//黑线丢失计数器
unsigned char stop=0; //停车圈数计数器
unsigned char i=0,j=0,left=0,right=0,start_flag1=0,start_flag2=0;
unsigned char left_line=0,right_line=0,left_edge=0,right_edge=0;
int temp=0;
//DisableInterrupts;
Line_Center[0]=Line_Center[ROW_VALUE-1];
//每场的末尾给新的一场的开始,让图窳饩浜苤匾�
////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//////////////////////图像 前 端 黑 线 搜 索\\\\\\\\\\\\\\\\\\\\
////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
for(i=ROW_MIN;i<ROW_MIDDLE;i++)
{ start_flag1=0;
left=0; //左右跳变清零,这是必须的!!
right=0;
for(j=1;j<=COLUMN_VALUE-1;j++) //两边搜索
{ if(uca_Buffer1[i][j]-uca_Buffer1[i][j+1]>0)
{left=j;left_line=left;start_flag1++; }
if(uca_Buffer1[i][COLUMN_VALUE-j]-uca_Buffer1[i][COLUMN_VALUE-j-1]>0)
{right=COLUMN_VALUE-j;right_line=right;}
}
//过滤过宽的黑线和过细的黑线
if(start_flag1==1)
{
if((right-left>=BLACK_LINE_MIN0)&&(right-left<=BLACK_LINE_MAX0))
{ Line_Center[i]=(right+left+1)/2;
_asm(nop);
black_lost=0;//黑线丢失清零
}
}
//如果不满足黑线的要求则利用插值求出本行位置 4 月22 5 月1 日修改
else
{ //当黑线丢失三行以上认为黑线丢失,退出搜索!
if(black_lost>BLACK_LOSTED)
{if(Line_Center[i-1]==Line_Center[i-3])//判断是否相邻黑线位置相等
{if(Line_Center[i-1]<=black_centre) //若相等判断是小于黑线中心
还是大于
{ //若小于则每行黑线位置减一
while(i<ROW_VALUE)//插值计算并且返回
{temp=Line_Center[i-1]-1;
if(temp<LEFT_LIMIT)temp=LEFT_LIMIT;
Line_Center[i]=temp;
i++;
}
return;
}
else //若大于黑线中心位置则每行加一
{
while(i<ROW_VALUE)
{temp=Line_Center[i