飞思卡尔智能车大赛技术报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第九届“飞思卡尔”杯全国大学生智能车竞赛光电组技术报告
学校:中北大学
伍名称:ARES
赛队员:贺彦兴
王志强
雷鸿
队教师:闫晓燕甄国涌
关于技术报告和研究论文使用授权的说明书本人完全了解第八届“飞思卡尔”杯全国大学生智能汽车竞赛关保留、使用技术报告和研究论文的规定,即:参赛作品著作权归参赛者本人,比赛组委会和飞思卡尔半导体公司可以在相关主页上收录并公开参赛作品的设计方案、技术报告以及参赛模型车的视频、图像资料,并将相关内容编纂收录在组委会出版论文集中。
参赛队员签名:
带队教师签名:
日期:2014-09-15日
摘要
本文介绍了第九届“飞思卡尔杯全国大学生智能车大赛光电组中北大学参赛队伍整个系统核心采用飞思卡尔单片机MC9S12XS128MAA ,利用TSL1401线性CCD 对赛道的行扫描采集信息来引导智能小车的前进方向。
机械系统设计包括前轮定位、方向转角调整,重心设计器件布局设计等。
硬件系统设计包括线性CCD传感器安装调整,电机驱动电路,电源管理等模块的设计。
软件上以经典的PID算法为主,辅以小规Bang-Bang
算法来控制智能车的转向和速度。
在智能车系统设计开发过程中使用Altium Designer设计制作pcb电路板,CodeWarriorIDE作为软件开发平台,Nokia5110屏用来显示各实时参数信息并利用蓝牙通信模块和串口模块辅
助调试。
关键字:智能车摄像头控制器算法。
目录
1绪论 (1)
1.1 竞赛背景 (1)
1.2国内外智能车辆发展状况 (1)
1.3 智能车大赛简介 (2)
1.4 第九届比赛规则简介 (2)
2智能车系统设计总述 (2)
2.1机械系统概述 (3)
2.2硬件系统概述 (5)
2.3软件系统概述 (6)
3智能车机械系统设计 (7)
3.1智能车的整体结构 (7)
3.2前轮定位 (7)
3.3智能车后轮减速齿轮机构调整 (8)
3.4传感器的安装 (8)
4智能车硬件系统设计 (8)
4.1XS128芯片介绍 (8)
4.2传感器板设计 (8)
4.2.1电磁传感器方案选择 (8)
4.2.2电源管理模 (9)
4.2.3电机驱动模块 (10)
4.2.4编码器 (11)
5智能车软件系统设 (11)
5.1程序概述 (11)
5.2采集传感器信息及处理 (11)
5.3计算赛道信息 (13)
5.4转向控制策略 (17)
5.5速度控制策略 (19)
6总结 (19)
6.1效果 (20)
6.2遇到的问题以及解决办法 (20)
6.3队员之间的合作很重要 (21)
附录 (22)
源程序 (23)
1绪论
1.1 竞赛背景
随着经济发展,道路交通面临新的问题和新的挑战。
所以急需改变传统交通模式,解决当前面临的困境,正是在这样的背景下智能汽车迎来了大发展的时期,各国争相投入大量资金研究无人驾驶技术。
智能车的发展早期受限于技术手段,智能化较低,主要应用在自动化仓贮系统和柔性装配系统的物料运输,随着新型高精度,高可靠性的传感器不断涌现,现阶段智能车正在向适应城市道路,野外复杂地形等方向发展,在不久的将来即可真正替代人工驾驶。
1.2 国内智能车辆发展状况
1992年,国防科技大学研制成功了我国第一辆真正意义上的无人驾驶汽车。
由计算机及其配套的检测传感器和液压控制系统组成的汽车计算机自动驾驶系统,被安装在一辆国产的中型面包车上,使该车既保持了原有的人工驾驶性能,又能够用计算机控制进行自动驾驶行车。
2000年6月,国防科技大学研制的第4代无人驾驶汽车试验成功,最高时速达76km,创下国内最高纪录。
2003年7月,国防科技大学和中国一汽联合研发的红旗无人驾驶轿车高速公路试验成功,自主驾驶最高稳定时速130km,其总体技术性能和指标已经达到世界先进水平。
1.3 智能车大赛简介
飞思卡尔是业界领先的半导体公司,主要研发领域面向汽车应用领域,产品质量优秀,其他公司在汽车应用方面很难与之抗衡。
飞思卡尔智能车竞赛已经经历了7届比赛,并将于今年的夏天举办第八届比赛。
该竞赛由竞赛秘书处设计、规范标准硬软件技术平台,竞赛过程包括理论设计、实际制作、整车调试、现场比赛等环节,要求学生组成团队,协同工作,初步体会一个工程性的研究开发项目从设计到实现的全过程。
该竞赛融科学性、趣味性和观赏性为一体,是以迅猛发展、前景广阔的汽车电子为背景,涵盖自动控制、模式识别、传感技术、电子、电气、计算机、机械与汽车等多学科专业的创意性比赛。
该竞赛规则透明,评价标准客观,坚持公开、公平、公正的原则,力求向健康、普及、持续的方向发展。
竞赛主要分为竞速赛和创意赛两种。
在竞速赛中,规则规定了使用的车模、传感器类型、处理器类型和赛道尺寸等关键的因素,参赛选手可以在相同的条件下,自行设计硬件电路和软件算法,最终能以最快速度跑完全程。
竞速赛分为三个赛题组:光电组、摄像头组、电磁组。
不同之处在三个组的循线传感器是不一样的。
电磁组的赛道中心铺有细导线,导线中通有频率和电流稳定的电信号,能利用电磁感应原理检测中心导线的位置。
电磁组和另两个赛题组相比,优势在于检测信号稳定,不会受到外界采光条件的变化而影响,也不会受到赛道外的背景色所干扰,所以比较少在比赛中途因找不到赛道中心而冲出赛道的情况,缺点在于电磁传感器一般由电感电容组成,如果需要增加赛车前瞻的话需要加固定支架把传感器伸到赛车前方,这样会增加车子转弯时的转动惯量,影响车子转弯的灵活性,曾有强队想出来车体主动悬挂的方式抵消转弯时的转动离心力,从而提升车子转弯速度,使得电磁车速度得到很大提升。
1.4第九届比赛规则简介
参赛选手须使用竞赛秘书处统一指定的竞赛车模套件,采用飞思卡尔半导体公司的8位、16位、32位微控制器作为核心控制单元,自主构思控制方案进行系统设计,包括传感器信号采集处理、电机驱动、转向舵机控制以及控制算法软件开发等,完成智能车工程制作及调试,于指定日期与地点参加各分(省)赛区的场地比赛,在获得决赛资格后,参加全国决赛区的场地比赛。
参赛队伍的名次(成绩)由赛车现场成功完成赛道比赛时间来决定,参加全国总决赛的队伍同时必须提交车模技术报告。
大赛根据道路检测方案不同分为电磁、光电平衡与摄像头三个赛题组。
使用四轮车模通过指定的线阵CCD器件或者分立的光电管传感器获得一维连续或者离散点赛道信息的属于光电组,
光电组:四轮车模允许双向运行。
车模使用 B 型车模。
车模运行可以在比赛过程中,根据赛道要求随时调整
运行方向,如图2 所示
图X
原型车模如下
2 智能车系统设计总述
智能车主要分为机械系统、硬件系统、和软件系统三个部分,三个部分中以机械系统、硬件系统为基础,软件系统为核心。
在整个的后续调试和三部分之间的融合过程中也需要不断地修正已达到优良的效果。
2.1机械系统概述
机械系统作为智能车的基础影响着整个车的运行姿态和速度,轻巧的车身可以使车更加灵活容易操控,合理的重心位置可以让车运行更平稳,而前轮定位、舵机安装的方式和位置可以影响转向灵活度。
为了和传感器和系统PCB控制板的安装,也需要对车身,舵机,舵机的转度进行细致的调整。
图V整体车体结构
图VV线性CCD部分
图XX舵机部分
图BB编码器部分
2.2硬件系统概述
硬件系统作为小车的基础最重要的就是运行稳定,XS128单片机满足了智能车竞赛中对运算速度的需求,传感器部分的设计要注意模块间的分隔,避免相互干扰,要注意的是排列尽可能紧密,减小电路板面积。
在设计电源管理模块,传感器检测处理模块,起点检测模块,电机驱动
模块等的时候都积极思考,尽量做到减少干扰,安全可靠。
图XB硬件系统搭建简图
2.3软件系统概述
软件系统作为智能车的核心是决定最后运行速度和平稳性的关键,主要工作是对传感器采集到的数据进行处理,选择合适的方法解算赛道信息,制定合理的转向控制策略使转向平滑快速,制定有效的速度控制策略使智能车平均速度提高。
程序流程图:
3智能车机械系统设计
3.1智能车的整体结构如图所示:
为了排布pcb板,安装舵机和传感器固定杆,并根据规则和车体的尺寸,对智能车的机械结构做了一些调整包括减震弹簧的安装,车底盘的高度,电池位置,期间为了较强的稳固车体我们将电机部分和前车体进行了固定。
3.2前轮定位
前轮定位(转向轮定位)指转向轮、转向节和前轴三者之间与车架必须保持一定的相对安装位置。
在规则中只禁止改动车底盘结构轮距、轮径和轮胎。
前轮位置可以任意调整改变。
若要在不同速度,负载,重心条件下使车在轻快稳定的前进,那么最开始时候的前轮要力求最好的中心位置的摆正。
我们在舵机摆角设定的最小范围内,依次标算出它的左右摆点位置。
并形成查询表,根据不同道路的信息不同来计算不同路径下的最优曲率输出控制舵机的摆角。
3.3智能车后轮减速齿轮机构调整
齿轮传动机构对车模的驱动能力有很大的影响。
调整的原则是:两传动齿轮轴保持平行,齿轮间的配合间隙要合适,过松容易打坏齿轮,过紧又会增加传动阻力,浪费动力;传动部分要轻松、顺畅,不能有迟滞或周期性振动的现象。
判断齿轮传动是否良好的依据是,听一下电机带动后轮空转时的声音。
声音刺耳响亮,说明齿轮间的配合间隙过大,传动中有撞齿现象;声音闷而且有迟滞,则说明齿轮间的配合间隙过小,或者两齿轮轴不平行,电机负载变大。
调整好的齿轮传动噪音很小,并且不会有碰撞类的杂音,后轮减速齿轮机构就基本上调整好了,动力传递十分流畅。
3.4传感器的安装
首先根据理论计算得出比较适合的前瞻距离,来慢慢调整线性CCD的仰角和高度。
其引线尽可能的以最短的距离来将信息送入核心控制部分。
起初设定的前瞻距离为50cm,来调整CCD。
经过后期调试最佳前瞻距离达到了60cm的距离。
支架用的是材质轻巧强度很高的碳纤维管作为支撑杆。
4智能车硬件系统设计
4.1 主控芯片XS128芯片介绍:
最高可以超频到80MHz bus clock,BDM接口;PB0上接一个发光二极管“PB0”;电源
指示放光二极管“5V”;参考电压可以选择5V,也可以去掉VRH电阻外接;两个电源接
口;对单片机供电部分布线作了特殊处理,更稳定;插针为100mil的整数倍,标准点
阵板可以直接插上去。
板子尺寸:51*49mm,小而稳!
4.2硬件部分包括的几大部分:
4.2.1电源硬件设计部分
cpu最小系统部分,电机驱动部分,传感器处理部分,显示模块,按键模块。
整体硬件搭建原理图如图:
4.2.2电源管理部分:
电源管理模块需要为整个电路提供稳定而高质量的电源,特别是对单片机的供电。
本系统的设计中,编码器、串口通信、传感器和液晶显示部分都需要5v供电;单片机OLED 模块均使用3.3v供电。
考虑到电池电压7.8v左右,电源管理模块需要5v3.3v两个稳压其中5v稳压芯片使用的是8940稳压芯片使用AMS1117全部输出耦合采用红宝石的顶级电解电容,确保稳定型和可靠性。
为防止电源电压被拉低时引起单片机复位,采用二
极管/电感和40uf电容的电路为单片机储存电能,电路原理图如下:
4.2.3电机驱动模块
用两片英飞凌公司的半桥驱动芯片BTS7970组成全桥。
此电路只需要2片BTS芯片,外部电路简单,使用方便,性能可靠,方案成熟。
缺点是指标会比用MOSFET管搭建大,而且车速一旦较快,输出电流过大,会触发芯片内部的保护机制,不利于长距离长时间调试。
电路原理图如下:
4.2.4编码器
5智能车软件系统设计
5.1程序概述
程序使用了XS128芯片中的TIM模块、PIT模块、AD模块、I/O模块、PIT模块、PWM模块。
其中舵机和电机通过PWM模块来控制,舵机频率100Hz,通过对赛道黑线边缘部分的提取对赛道位置和赛道地形进行判断,I/0块主要用来作为人机交互模块使用。
PIT模块作为定时器产生1ms的定时中断,转向控制服务程序,速度控制服务程序均在PIT中断当中完成。
AD采样服务程序在AD中断中完成。
程序大概流程如下:
(1)进行各个模块的初始化。
(2)在按下启动键之后程序进入大循环,扫描是否有暂停键按下。
(3)AD中断服务程序进行AD采样,PIT中断服务程序,进行线性CCD返回数值数据析.
(4)转向控制,速度控制,输出相应的PWM波值控制电机和舵机,使智能小车在赛道上平稳运行。
5.2采集传感器信息及处理
TSLS1404线性CCD的工作时序图如图:
对赛道每扫描一次信息的初始化以及每取五次信息进行一次传输: for(i=0; i<128; i++)
{
*pixel_pt++ = 0;
}
StartIntegration();//预曝光
EnableInterrupts;//开中断
for(;;)
{
//SpeedControl();
MotorAction(10);
//key_scan();//键盘扫描
if(TimerFlag10ms == 1)
{
TimerFlag10ms = 0;//清10ms标志
cnt++;
if(cnt >=5)
{
cnt = 0;
SendImageData(PixNew);
}
5.3计算赛道信息:
在实际测试和比赛之中,CCD接收到的信息往往伴随着许多杂点,那么就要削减这些杂点对计算的影响,我们采用了高斯滤波去除错误点并实现曲化采集到的赛道信息点,为判断出黑线边界我们又对数据进行了二值化,以获取赛道的边缘线。
同时为了尽量减少CCD的曝光时间我们队CPU的执行进行了顺序化。
最后达到获取赛道的信息。
二值化的阈值在这里用了动态阈值,大大克服了CCD对环境的光亮强的狭小范围内依赖程度搞得高的缺点、
5.3.1,去噪点
void Enosing(uchar *a)
{
char i;
for(i=1;i<127;i++)
{
if(a[i]==0)
{
if((a[i-1]==1)&&(a[i+1]==1))
{
a[i]=1;
}
}
if(a[i]==1)
{
if((a[i-1]==0)&&(a[i+1]==0))
{
a[i]=0;
}
}
}
}
5.3.2计算动态阈值
void trends_threshold(uchar *a)
{
unsigned char i,j,zmax=0,zmin=255,zbmax=0,zbmin=255,zamax=0,zamin=255,t0,t1,za,zb;
for(i=0;i<row;i++)
{
for(j=0;j<column;j++)
{
if(a[j]>zmax)
{
zmax=a[j];
}
if(a[j]<zmin)
{
zmin=a[j];
}
}
}
t0=(zmax+zmin)/2;
if(Threshold!=t0)
{
for(j=0;j<column;j++)
{
if(a[j]>=t0)
{
if(a[j]>zamax)
{
zamax=a[j]; }
if(a[j]<zamin) {
zamin=a[j]; }
}
else
{
if(a[j]>zbmax) {
zbmax=a[j];
}
if(a[j]<zbmin) {
zbmin=a[j]; }
}
}
za=(zamax+zamin)/2;
zb=(zbmax+zbmin)/2;
t1=(za+zb)/2;
if(t1!=t0)
t0=t1;
}
Threshold=t1;
}
5.3.3获取赛道信息;通过对左丢线还是右丢线来判别车体偏离中心线的程度。
uchar RightLostCnt,LeftLostCnt;
void Getline2 (uchar *a)
{
uchar i;
uchar LeftLostFlog=1,RightLostFlog=1;
for(i=2;i<124;i++)
{
if(abs(a[i]-a[i+2])>Threshold)
{
if(abs(a[i-1]-a[i+3])&&abs(a[i-2]-a[i+4]))
{
if(a[i]<a[i+2])
{
LeftPot=i+1;
LeftLostFlog=0;
LeftLostCnt=0;
}
if(a[i]>a[i+2])
{
RightPot=i+1;
RightLostFlog=0;
RightLostCnt=0;
}
}
}
}
if((LeftLostFlog==0)&&(RightLostFlog==0))
RaceFlog=NotLost;
else if(LeftLostFlog==0)
{
RightLostCnt++;
RaceFlog=RightLost;
}
else if(RightLostFlog==0)
{
LeftLostCnt++;
RaceFlog=LeftLost;
}
else
RaceFlog=AllLost;
5.4转向控制策略;
转向控制信号的源输入控制信号源自CPU对编码器信息和传感器CCD信息经过一系PID计算分别对电机控制模块输出当前小车状态下赛道对电机运转的要求。
提取赛道信息:
float Direction_P;
float Direction_D;
float DirectionError0,DirectionError1,DirectionDiff; //0当前差值,1上次差值
int DirectionOut;
void DirectionControl1(void)
{
float fP,fD;
float BorderCom;//丢线补偿量
float BorderError;//丢线偏差
//取中线偏差
if(RaceFlog==NotLost)
{
Centerpot=(LeftPot+RightPot)/2;
DirectionError0=Centerpot-LineCenter;
}
else if (RaceFlog==RightLost)
{
BorderError=LeftPot;
BorderCom=BorderError_p1*BorderError*BorderError*BorderError +BorderError_p2*BorderError*BorderError
Centerpot = (LeftPot +127+BorderCom)/2;
DirectionError0 = Centerpot -LineCenter;
}
else if (RaceFlog==LeftLost)
{
BorderError=127-RightPot;
BorderCom=BorderError_p1*BorderError*BorderError*BorderError +BorderError_p2*BorderError*BorderError
+BorderError_p3*BorderError+BorderError_p4;;
Centerpot = (RightPot - BorderCom)/2;
DirectionError0 = Centerpot-LineCenter;
}
else
{
DirectionError0=DirectionError1;
}
//位置式pid
DirectionDiff=DirectionError0-DirectionError1
DirectionError1 = DirectionError0;
DirectionOut = fP +fD;
//角度限制在-290~290
if(DirectionOut>290)
DirectionOut=290;
if(DirectionOut<-290)
DirectionOut=-290;
//舵机转角
ServoAction(DirectionOut);
}
5.5速度控制策略
实际上是对电机驱动模块的控制通过编码器将当前小车的速度值反馈回来,从而形成控制闭环,利用PID制器配合不高,而对速度的变化速度要求很所以在控制的过程中当速度和升速度差别很大的时候用ang-Bang控制从而可以迅速达到设定速度周围,然后再通过PID控制平稳控制速度达到设定值。
在实运行当中,P的增大可以加快上升时间,使调节更快,但会引起较大震荡,而增加
D可以减少震荡会是上升之稳定的时间加长,由于车在运行过程中属于大惯性系统,调整PD 的时候优先调整在达到适合的时间之后再去调整D使速度变化平稳。
速度给定策略基本思想史入弯减速,出弯加速,在曲率不变的赛道上如直道,大的环形弯,十字弯上都加速通过。
同时设置最快最慢速度阈值保证能顺利入弯不会冲出赛道。
程序一开始小车需要静止在轨道上两秒,然后迅速加速达到设定速度,然后进入行驶阶段,在行驶阶段按照速度控制策略尽量做到加速刹车快速,变化过程平稳没有震荡,设定一个速度变化的阈值,避免速度剧烈变化,阈值的增加对于小车的适应性有影响,所量避免限制的过紧。
总结
6.1效果:
启动后,液晶显示模块各项参数显示正常,起跑后能顺利通过大小弯道直道。
蓝牙模块能正常传送各项参数到上位机。
6.2遇到的问题和解决办法:
6.2.1机械安装上
由于舵机安装过程和舵机本身的原因,在矫正前轮初始摆正过程中未能达到理想要求。
解决办法:适当调整拉杆的长度和舵机臂锁定螺丝的位置。
这个就要慢慢的调整了。
6.2.2方案问题:
(1)时序问题:
采集用的是蓝宙的20ms曝光自适应程序,但是稍微暗环境下上位机显示电压依然很低。
也许是我们没有领略到他的精华所在吧,晚上不能调车。
当光线很强的情况下,依然调不了车……
经过一系列调整参数,修改程序,最终确定方案如下:
5ms曝光,数据采集,滤波,动态阈值二值化,去除噪点,根据获取到的赛道信息,判定丢线情况。
根据丢线点数的多少进行补光量的计算并进行舵机摆角的控制输出。
(2)对环境光强赖性很强的问题弱
动态阈值二值化可以有效解决”自适应曝光”依然有的暗光下,输出电平依然很低的问题。
避障很好,估计是加入去噪点的原因吧。
动态阈值即使在很差的环境之下他都会有一个阈值的输出,二值化后可以清晰分辨出赛道信息的。
(3)计算问题:
很大可能是当时计算时候把此处的圆心到赛道中心线距离45按照圆心到内圆边沿45来算的整整差出将近25CM....还有一个硬件上的问题。
由于用的是几年前的一个后轮,昨天晚上发现重大缺陷,后轮没有差速.............……
根据提取到的赛道信息给定角度&红圈左后轮极限情况是刚刚压到内黑线和右前轮刚刚压到外圆边沿。
下面是对环形弯道的定时分析。
解决此问题尽可以适当增大离心率来解决其突发盲点。
6.3队员之间的合作尤为重要
在整个制作过程中,时时刻刻都会面临新的问题
附录:
各模块的部分程序:
A/D转换初始化,设置A/D转换时钟频率为4MHz
#include "includes.h"
/*
********************************************************************************* ************************
//函数名:AD_Init
//功能:A/D转换初始化,设置A/D转换时钟频率为4MHz
//参数:无
//返回:无
********************************************************************************* ************************
*/
void AD_Init_40M(void)
{
//ATD0CTL4: SRESS8=0, 将采集到的模拟量以10位二进制数表示
//SMP1=0,SMP0=0,采样时间:2 A/D 时钟周期
//PRS4=0,PRS3=0,PRS2=1,PRS1=0,PRS0=0 AD时钟频率
ATD0CTL4 = 0x04;//设置采样时间和频率,fATDCLK=fBUS/(2 ×(PRS + 1))
//ATD0CTL3: DJM=1,S8C=0,S4C=0,S2C=0,S1C=1,FIFO=0,FRZ1=0,FRZ0=0
ATD0CTL3 = 0x88; //采样结果右对齐,每个序列的转换个数为1
//ATD0CTL0: ??=0,??=0,??=0,??=0,WRAP3=0,WRAP2=0,WRAP1=0,WRAP0=1
ATD0CTL0 = 0x01; //AD循环采集到AN1后即可
//ATD0CTL1: ETRIGSEL=0,SRES1=1,SRES0=0,SMP_DIS=0,ETRIGCH3=1,ETRIGCH2=1
//ETRIGCH1=1,ETRIGCH0=1
ATD0CTL1 = 0x4F; //12位分辨率,采样前内部采样电容不放电
//ATD0CTL2: ??=0,AFFC=1,ICLKSTP=0,ETRIGLE=0,ETRIGP=0,ETRIGE=0,ASCIE=0,
//ACMPIE=0
ATD0CTL2 = 0x40; //下降沿触发,不接受外部信号,禁用ATD比较中断请求
}
/*
********************************************************************************* ************************
* Description: AD_Measure12
* function :通道选择,采样
********************************************************************************* ************************
*/
uint16_t AD_Measure12(uint8_t Channel) {
ATD0CTL5_Cx = Channel;
while(ATD0STAT0_SCF == 0);
return ATD0DR0;
}
电机控制
*************************************************************
*函数名称:SpeedControl
*描述;电机控制
*
*最后时间;
**************************************************************/
float Speed_P;
float Speed_I;
float SpeedOutLast,SpeedOut;
float SpeedError1,SpeedError0;
float SpeedFactor=330;
void SpeedControl(void)
{
float RealSpeed,TheorySpeed,SpeedErrorDiff;
float fP,fI;
TheorySpeed = DirectionError0/tan(DirectionOut*0.0016) ; //0.0016为方向参数转化为弧度的比例
RealSpeed= PACNT/SpeedFactor; //PT7接受脉冲
PACNT=0;
SpeedError0 = RealSpeed - TheorySpeed;
SpeedErrorDiff = SpeedError0 - SpeedError1;
fP = SpeedErrorDiff* Speed_P;
fI = SpeedError0 * Speed_I;
SpeedOut = SpeedOutLast+fP+fI;
SpeedOutLast = SpeedOut;
SpeedError1 = SpeedError0;
if(SpeedOut>100)
SpeedOut=100;
if(SpeedOut<-100)
SpeedOut=-100;
MotorAction(SpeedOut);
}
PWM模块:
void PWM_Init_40M(void)
{ PWME=0x00; //关PWM
PWMPRCLK=0x22; // 0011 0010 A=B=40M/4=10M 时钟预分频寄存器设置 PWMSCLA=5; // SA=A/2/5=1M 时钟设置
PWMSCLB=5; // SB=B/2/5=1M 时钟设置
PWMCTL=0x00; // 不级联控制寄存器设置
//motor_1
PWMCLK_PCLK0=1; // PWM0-----SA 时钟源的选择
PWMPOL_PPOL0=1; // Duty=High Time 极性设置
PWMCAE_CAE0=0; // Left-aligned 对齐方式设置
PWMPER0=100; // Frequency=SB/100=10K 周期寄存器设置
PWMDTY0=0; // Duty cycle = 0 占空比寄存器设置
//motor_2
PWMCLK_PCLK1=1; // PWM1-----SA 时钟源的选择
PWMPOL_PPOL1=1; // Duty=High Time 极性设置
PWMCAE_CAE1=0; // Left-aligned 对齐方式设置
PWMPER1=100; // Frequency=SA/100=10K 周期寄存器设置
PWMDTY1=25; // Duty cycle = 0 占空比寄存器设置
//servo
PWMPOL_PPOL7=1; // PWM输出先高后低
PWMCLK_PCLK7=1; // 选择Clock B作为通道7的时钟
PWMCAE_CAE7=0; // 左对齐,1为中心对对齐
PWMCTL_CON67=1; // 级联67
PWMPER67=20000; // 舵机PP67,,20MS
PWMDTY67=18525; // 舵机中间值 20000-1475
WME=0xC3; //开PWM
}
SCI模块
void SCI0_Init_40M(void)
{
/* Init_SCI init code */
SCI0CR1 = 0x00;
SCI0SR2 = 0x80; /* Switch to the alternative register set */
SCI0ASR1 = 0x83; /* Clear alternative status flags */
SCI0ACR1 = 0x00;
SCI0ACR2 = 0x00;
SCI0SR2 = 0x00; /* Switch to the normal register set */
(void) SCI0SR1; /* Reset interrupt request flags */
SCI0CR2 = 0x00; /* Disable error interrupts */
SCI0BD = 0x16; /* Set prescaler bits */ //115200
SCI0CR2 |= (SCI0CR2_TE_MASK | SCI0CR2_RE_MASK); /* Enable transmitter, Enable receiver */
}
void SCI0_Init_64M(void){
SCI0BDH=0x01; //When IREN=0, then SCI baud rate=SCI bus clock/(16*SBR[12:0])
SCI0BDL=0xa1; //SCI bus clock=BUs clock=64MHz,so if stet 9600 buad rate,then SBR[12:0]=0x01a1=417
SCI0CR2=0x2c; //enable Receive Full Interrupt,RX enable,Tx enable
}
PIT:
void PIT_Init_40M(void)
{
PITCFLMT_PITE=0; //PIT定时中断通道0关
PITCE_PCE0 = 1; //Enable Timer Channel0
PITMUX_PMUX0 = 0; //16-bit timer counts with micro time base 0
//time-out period = (PITMTLD + 1) * (PITLD + 1) / fBUS
//1ms
PITMTLD0 = 199; //PIT Micro Timer Load Register
PITLD0 = 199; //PIT Load Register
PITINTE_PINTE0 = 1; //Enable Timer Channel0 Interrupt
PITCFLMT_PITE = 1; //Enable Timer
}
void PIT_Init_64M(void)
{
PITCFLMT_PITE=0; //PIT定时中断通道0关
PITCE_PCE0 = 1; //Enable Timer Channel0
PITMUX_PMUX0 = 0; //16-bit timer counts with micro time base 0
//time-out period = (PITMTLD + 1) * (PITLD + 1) / fBUS //1ms
PITMTLD0 = 319; //PIT Micro Timer Load Register
PITLD0 = 199; //PIT Load Register
PITINTE_PINTE0 = 1; //Enable Timer Channel0 Interrupt
PITCFLMT_PITE = 1; //Enable Timer
}
波形显示通过Nokia5110显示CCD完成一次赛道信息采集:
void LCD_write_line(unsigned char *ptr)
{
unsigned char line;
LCD_set_XY(8,5);
LCD_write_byte(0xAA, 1);
LCD_set_XY(9,5);
for (line=0; line<64; line++)
{
if(*(ptr+2*line)==1)
LCD_write_byte(0xBD, 1); else
LCD_write_byte(0x81, 1); }
LCD_set_XY(73,5);
LCD_write_byte(0xAA, 1);
}。