在线工博会

MM908E624单片机在汽车电子油门控制系统的应用
为节省流量,手机版未显示文章中的图片,请点击此处浏览网页版
1 引言
目前,轿车已深入家庭,轿车的安全行驶关系到每个家庭的幸福和国家的安定,但是轿车追尾事件的时有发生,以及情急之下误踩油门代替刹车造成车毁人亡的惨剧的事件,深深地触动我们设计人员。随着,电子技术特别是单片机的发展,单片机进入轿车控制系统,便汽车有了智能化可以紧急情况代替人的反应,更安全更可靠。
下面我介绍一下基于MM908E624 单片机的汽车智能油门。通常传统的油门通过右脚进行机械控制,并且紧急刹车也在用右脚控制,在紧急情况,刹车踏在油门的事故时有发生。并且由于通过机械传导,结构较为复杂,增加成本。我的设计完全避免这样的风险,使用简单方便。油门控制系统安装在方向盘上,通过指令控制执行部分(马达)控制油门的开度,实现轿车油门开度控制的目的。
与此同时,通过传感器可以从显示部分得知油门的实际开度,可以省油节油,并有利于新驾驶员驾驶避免半途熄火的危险驾驶。
智能判断功能,车前身的超声波测距可以得知轿车的车距并判断车距是否安全,并根据相应的车速报警。自动使油门开度变小变大。 其关键点,右脚只需进行刹车控制从而避免了误踩油门。并可同时进行油门控制,最大限度减少轿车刹车的惯性。可以说此项技术是现代汽车技术的伟大革新。使现代轿车从更安全更节能的方向发展造成深远的影响
2 结构与原理
2.1 传统的机械油门如图所示:

(图片)

我们知道,操纵节气门开度就能控制可燃混合气的流量,改变发动机的转速和功率,以适应汽车行驶的需要。传统发动机节气门操纵机构是通过拉索(软钢丝)或者拉杆,一端联接油门踏板(加速踏板),另一端联接节气门连动板而工作。但这种传统油门应用范畴受到限制并缺乏精确性。请注意:所有的传统电子油门的控制都基于人脑的判断,具有不确定性,油门开度不稳定,导致耗过多油比智能油门(燃油比恒定)。
2.2 智能油门工作原理如图所示:

(图片)

与传统油门比较,电子油门明显的一点是可以用线束(导线)来代替拉索或者拉杆,在节气门那边装一只微型电动机,用电动机来驱动节气门开度。即所谓的“导线驾驶”,用导线代替了原来的机械传动机构。
但这仅仅是电子油门表面的东西,它的实质和作用仅仅用连接代替方式来解析是远远不够的。首先通过,手调节位置传感器将需要的油门开度信号传递到MM908E624 ,经过得到的数据(扭矩及转速)分析,从而输出信号驱动电动机进行调节油气门开度。
电喷系统采用电子油门和扭矩结构控制原理,使得发动机时刻处于最优状态,大大改善了整车性能,提高了驾驶舒适性,降低了油耗,减少了排放污染;更好地满足环保要求。
2.3 智能油门设计说明:
电子油门控制系统主要由油门位移传感器DCU(电控单元)、数据总线、伺服电动机和节气门执行机构组成。MM908E624 单片机主要是为汽车和工业控制而设计的。它们都是由高性能的HC08 单片机(MCU)核和SmartMOS 集成电路芯片构成,具有集成度高、价格低等特点。在这里我采用此单片机作为控制核心主要基于以下原因。1、不需要外置晶振减少器件和成本。2、集成模拟器件使用更方便。3、芯片性能优异。在实际应用中将位移传感器安装在方向盘上,可以设定油门的开度(即目标车速),同时在油门的电机上安装油门开度传感器监测油门开度的实际位置。当数据扫描到位移传感器的模拟输入与油门开度传感器的输入不同有变化时,会瞬间将此信息送往MM908E624,该芯片对信息进行分析,当位移传感器的模拟输入量大于油门开度传感器的反馈量时,驱动电机继电器,驱动节气门执行机构油门马达正转(即进油量增加、并加速)。反之输入量小于反馈量则相反。通过以上方法实现对油门的控制,保持输出稳定和高的燃烧效率从而减少能源消耗。
电子油门智能控制系统主要由超声波传感器电路、车速度传感器系统以及LIN 总线加显示报警电路组成。超声波传感器电路输出电压0~5 伏,对应距离近0m 远5m。车速度传感器系统输出0~5 伏对应低速高速。当速度传感器系统输出减去超声波传感器电路输出大于一定值时。输出报警提醒注意和迫使油门马达反转(减速)。在这里能代替人的反应,及时减速,防撞。LIN 总线则是负责系统(MM908E624)与其它DCU 之间的通讯并显示超声波测距值和车速值。当刹车或离合器踩下时, L1 闭和油门马达反转(减速)。使用十分简便。
此外,电子智能油门系统是通过DCU 来调整节气门的,因此可以设置各种功能来改善驾驶的安全性和舒适性,其中最常见的就是ASR(牵引力控制系统)和速度控制系统(巡航控制)。电子油门当ASR 系统传感到车轮的旋转速度,ECU 就根据油门踏板的位置、车轮速度和方向盘转向角度等之间的不同而求出滑动率,通过减少节气门开度来调整混合气流量,以降低发动机功率来达到控制目的。而在ASR 系统中,电子油门起到十分关键的作用,它涉及整个ASR 系统中对车速控制、怠速控制等功能,使系统能迅速准确地执行指令。即当电子油门系统接受到ASR 系统指令时,它对节气门控制指令只来自于ASR,这样就可以避免驾车者的误操作。
当驾车者使用速度控制系统时,车速传感器将车速信号输入ECU,再由ECU 输出指令伺服电动机控制节气门开度。在这样的系统中,根据行驶阻力的变化由控制系统自动调节发动机节气门开度,使行驶车速保持稳定。因此电子油门系统也可以兼容巡航控制功能。
电路图设计,利用单片机MM908E624 其所带的HC08 单片机核基本都是一样的,都包括16K字节的片上flash 存储器,512 字节的RAM,两个16 位2 通道的定时器,增强型串行通讯接口(ESCI),10 位精度的模数转换器(ADC),串行外设接口(SPI)和16 个单片机通用I/O 口。其中,MM908E624 内部的SmartMOS 集成电路主要是由三个的高端输出口,LIN总线接口,电压调整器以及运算放大器接口和唤醒接口等构成。
MM908E624 共有三个高端输出口:其中前两个高端输出接口HS1 和HS2,带有过流及过温保护功能,最大输出电流范围为200mA~500mA,可以用来驱动马达。在驱动电感性负载的情况下,这两个输出口的内部还带有钳位电路,可以限制输出的电压。对这两个输出口的控制是通过SPI 接口实现的,另外还可以通过PWMIN 端口,实现PWM 控制功能。在使用PWM 功能的时候,芯片内部驱动高端输出接口的电路会把SPI 寄存器的HS1ON 位(或HS2ON 位)和PWMIN 输入引脚的电平进行逻辑与运算,然后根据与的结果控制高端输出口的状态。
MM908E624/都带有一个LIN 物理层,提供了一个LIN 总线端口LIN,该端口为单总线收发,可以与三线LIN 总线兼容。LIN (Local Interconnect Network)是一种低成本的串行通讯网络,基于SCI(UART)数据格式,采用单主控制器/多从设备的模式,主要用于实现汽车中的分布式电子系统控制。与CAN(Control Area Network)相比,LIN 的设计更为简单廉价。在很多应用的场合,使用LIN 来替代CAN 能够大幅度的降低产品的成本。
MM908E624 带有两个专门的唤醒输入接口L1、L2。在SLEEP 或STOP 模式下,如果唤醒输入接口的电平发生变化,系统就会被唤醒并进入NORMAL 模式。在正常(NORMAL)模式下,通过SPI 接口可以读取这两个端口的状态,因此唤醒接口也可以用来监控外接开关的状态变化,通过方向盘上触摸RESET 或刹车和离合器上安置接触开关。使之系统被唤醒,控制轿车的油门开度,实现缓冲和节油。
MM908E624 带有一个电压调整器输出接口。在正常模式和STOP 模式下,该电压调整器,可以输出一个5V 电压,从而可以给单片机供电。但需要注意的是,该端口需外接一个电容来稳定电压的输出。另外,该电压调整器还具有限流功能,主要用于STOP 模式下。
2.3 智能油门结构简图:

(图片)

2.4 智能油门电路图:

(图片)

电路简介如下:
1. A/D 采样部分,位置设置传感器的模拟输出到MM908E624 的PTB3/AD3 口,同时芯片的PTB4/AD4 接收油门位移反馈。超声波测距电路,由NE555 驱动传感器40S 发射超声波,40R 接收反射的超声波信号并将微弱的电压信号经集成运放LF357 信号放大输出0~5V 电压。输出的模拟量到PTB5/AD5 口。速度模拟采样在PTB7/AD7 口。
2. 主控芯片部分,MM908E624 对外部传感电路的信号进行运算和分析,判断是否HS1,HS2端口输出,从而驱动油门马达,并将报警信号输出通过PTA3,PTA4。同时通过LIN 总线与主控制器连接及时反馈信息。
3. RESET 部分,通过该复位键L1,及时唤醒芯片进行油门马达反转刹车缓冲。
4. 电源部分,超声波电路部分供电采用12V,芯片采用LIN 总线供电,马达部分采用12V 电源供电。
3.软件结构框图
3.1 软件总体框图:

(图片)

3.2 程序流程图:

(图片)

3.3 程序:
void main(void) {
l_bool l_NoBusActivity;
UINT8 scpsc_buf,srsr_buf;
// ----- Config registers (write once)
#if defined(MON08)
rCONFIG2 = bEXTCLKEN|bSSBPUENB|bESCIBDSRC|bTMBCLKSEL; // allow ext.
clock, disable default SS pull ups, ESCI clock = bus clock, TBM clock /128
while(rICGCR!= (bCS|bECGON|bECGS)) {
rICGCR = (bCS|bECGON|bECGS); // turn to
external clock source for debugging
}
#else
rCONFIG2 = bSSBPUENB|bESCIBDSRC|bTMBCLKSEL; // disable
default SS pull ups, ESCI clock = bus clock, TBM clock /128
#endif
rCONFIG1 = bLVI5OR3|bSTOP|bCOPD; // 5V operation,
allow stop, disable Watchdog
rICGTR = 128; // trim to ideal:
4.9152MHz
rICGMR = 64; // 4.9152MHz
internal Bus
srsr_buf=rSRSR
SPI_Init(); // Initialize
SPI
SPI_Enable();
ADC_Init();
(void) l_sys_init();
l_ifc_init_sci0();
(void) l_ifc_connect_sci0();
SPIout = bwMODE2|bwMODE1; // normal mode,
slewrate 20kbit, HSx off
SPIin = SPI_ReadWrite(SPIout);
// PTD0 connected to PWMIn -> static to 5V
rDDRD |= bDDRD0;
rPORTD |= bPTD0;
TimerBInit();
lastDir = eSTOP;
PositionInit();
// init Timer Base Module
TimerInit();
TimerValue[TIMER1IDX] = TIMERBASEINTERVALLMS; // 1,66ms
TimerStart(TIMER1);
cli(); // enable
interrupt
for(;;) { // Main Loop
PositionUpdate();
// ----- No LIN Bus activity -----
// l_ifc_ioctl_sci08(l_op_getidle, &l_NoBusActivity);
// if(l_NoBusActivity) State = eAsleep;
rADSCR = !bADCH4|!bADCH3|!bADCH2|bADCH1|bADCH0; // select channel
and start conversion
while(!(rADSCR&bCOCO));
fADC_Value1 = rADRL;
rADSCR = !bADCH4|!bADCH3|bADCH2|!bADCH1|!bADCH0; start conversion
while(!(rADSCR&bCOCO));
fADC_Value2 = rADRL;
if((fADC_Value1 - fADC_Value2)>5)
{
SPIout=bwHS1|!bwHS2;}
else if((fADC_Value2 - fADC_Value1)>5)
{SPIout=!bwHS1|bwHS2;}
else{
SPIout=bwHS1|bwHS2;}
rADSCR = !bADCH4|!bADCH3|bADCH2|!bADCH1|bADCH0;
while(!(rADSCR&bCOCO)); // wait till Conversion Complete
fADC_Value3 = rADRL;
rADSCR = !bADCH4|!bADCH3|bADCH2|bADCH1|bADCH0; // select
channel and start conversion
while(!(rADSCR&bCOCO)); // wait till Conversion Complete
fADC_Value4 = rADRL;
if((fADC_Value3 - fADC_Value4)>35)
{
rDDRA = bDDRA3;
rPORTA = bPTA3;}
else{ rDDRA = bDDRA4;
rPORTA = bPTA4;}
if(l_u8_tst_SysCmd()){
if(SysMasterRequest_Sleep()) { // first byte = 0
//State = eAsleep; // goto Sleep
Signal received
EnterLowPowerMode(); // call
LIN_GotoSleep()
}else if(l_u8_rx_SysNodeID()==NodeId){ // for
this node ?
if(SysMasterRequest_DataTx()) {
l_u8_tx_SysCmd(cmdDataTx);
l_u8_tx_SysNodeID(NodeId);
l_u8_tx_SysAdr(l_u8_rx_SysAdr());
if((l_u8_rx_SysAdr()&0xC0)==0x00) { // ADC Reg.
l_u8_tx_SysData0(ADC_Value((l_u8_rx_SysAdr()&0x1F)));
}else if((l_u8_rx_SysAdr()&0xC0)==0x40) { // SPI-Reg.
SPIin = SPI_ReadWrite(SPIout);
l_u8_tx_SysData0(SPIin);
}else if(l_u8_rx_SysAdr()==0x97) { // MCU-Reg. 0x0017
l_u8_tx_SysData0(scpsc_buf);
}else if((l_u8_rx_SysAdr()&0xC0)==0x80){ // MCU-Reg. 0x0000-0x003F
l_u8_tx_SysData0(IOBYTE(l_u8_rx_SysAdr()&0x3F));
}else if((l_u8_rx_SysAdr()&0xC0)==0xC0){ // MCU-Reg. 0xFFFE-0xFFFF
l_u8_tx_SysData0(srsr_buf);
}else{ // SRSR (0xFE01)
//tbd
}
LinMsgStatus[2] = LIN_MSG_UPDATED;
}else if(SysMasterRequest_DataRx()) {
l_u8_tx_SysCmd(cmdDataRx);
l_u8_tx_SysNodeID(NodeId);
l_u8_tx_SysAdr(l_u8_rx_SysAdr());
l_u8_tx_SysData0(l_u8_rx_SysData0());
SPIout = l_u8_rx_SysData0();
SPIin = SPI_ReadWrite(SPIout);
LinMsgStatus[2] = LIN_MSG_UPDATED;
}else if(SysMasterRequest_Reset()) { // reset target
}else if(SysMasterRequest_ChNodeID()) { // change Node ID
newnode = l_u8_rx_SysData0();
Flash_ErasePage(0xC000);
(void)Flash_ProgRow(0xC000,&newnode);
l_u8_tx_SysCmd(cmdChNodeID);
l_u8_tx_SysNodeID(NodeId);
LinMsgStatus[2] = LIN_MSG_UPDATED;
}else if(SysMasterRequest_ChICGTR()) { // change Node ID
newnode = NodeId;
newtrim = l_u8_rx_SysData0();
Flash_ErasePage(0xC000);
(void)Flash_ProgRow(0xC000,&newnode);
l_u8_tx_SysCmd(cmdChICGTR);
l_u8_tx_SysNodeID(NodeId);
l_u8_tx_SysData0(NodeIcgtr);
rICGTR = NodeIcgtr;
LinMsgStatus[2] = LIN_MSG_UPDATED;
}
}
l_u8_clr_SysCmd(); // clear Flag
}
if (LinMsgStatus[2] == LIN_MSG_UPDATED){
scpsc_buf=rSCPSC;
}
// new command received ?
if(l_u8_tst_Command()) {
SPIout = l_u8_rx_SPIData();
TimerBSetPWMduty(l_u8_rx_PWMDuty()); // change duty
cycle
l_u8_clr_Command();
}
// if only one hall sensor is used need to specify direction !!
if(SPIout&bwHS1) {
lastDir = eCW;
}else if(SPIout&bwHS2) {
lastDir = eCCW;
}
SPIin = SPI_ReadWrite(SPIout);
// send debug information
l_u16_tx_Position(PositionValue());
l_u8_tx_Current(ADC_Value(ADC_CHANNEL_PTB1));
l_u8_tx_PTA0(IOBYTE(0));
l_u8_tx_SPIData(SPIin);
l_u8_tx_ADC5(ADC_Value(ADC_CHANNEL_PTB5));
l_u8_tx_ADC7(ADC_Value(ADC_CHANNEL_PTB7));
l_u8_tx_ADC3(ADC_Value(ADC_CHANNEL_PTB3));
l_u8_tx_ADC4(ADC_Value(ADC_CHANNEL_PTB4));
// Timer
if(TimerElapsed(TIMER1)) {
TimerValue[TIMER1IDX] = TIMERBASEINTERVALLMS; // 1,66ms
TimerStart(TIMER1);
PositionUpdate();
}
}
}
}
// --------------------------------------------------------
// --------------------------------------------------------
// --------------------------------------------------------
void Reset(void) {
asm JMP $2000; // forces a reset
Illegal Address Reset
}
// --------------------------------------------------------
void EnterLowPowerMode(void) { // Initialize
Sleep/Stop Mode
(void)l_ifc_disconnect_sci08(); // disconnect
SCI (port E)
sei();
TimerDisable();
TimerBDisable();
ADC_PowerOff();
// ---------------------
// all unused pins to output
// all outputs to output
// all inputs to input
//
// EY16 / KOBI interface
//
// PTA5/SPSCK (EY16 -> KOBI) PULL DOWN
// PTA6/SSB (EY16 -> KOBI) PULL UP
// PTB1/OUT (EY16 <- KOBI)
// PTC0/MISO (EY16 <- KOBI)
// PTC1/MOSI (EY16 -> KOBI) PULL DOWN
// PTD0/PWMIN (EY16 -> KOBI) PULL ?
// PTE0/TXD (EY16 -> KOBI) PULL UP
// PTE1/RXD (EY16 <- KOBI)
rDDRA = bDDRA6|bDDRA5|bDDRA4|bDDRA3|bDDRA2|bDDRA1|bDDRA0; // all
out
rDDRB = bDDRB7|bDDRB6|bDDRB5|bDDRB4|bDDRB3|bDDRB2|!bDDRB1|bDDRB0; // B1 in
rDDRC = bMCLKEN|bDDRC4|bDDRC3|bDDRC2|bDDRC1|!bDDRC0; // C0 in
rDDRD = bDDRD1|bDDRD0; // all out
rDDRE = !bDDRE1|bDDRE0; // E1 in
rPORTA = !bPTA5|bPTA6; // A5 down, A6 up
rPORTB = 0;
rPORTC = !bPTC1; // C1 down
rPORTD = !bPTD0; // D0 down
rPORTE = bPTE0; // E0 up
/*
(void)SPI_ReadWrite(bwLINSL2|bwLINSL1|bwMODE1);// Stop Command (MCU supplied)
(void)SPI_ReadWrite(bwLINSL2|bwLINSL1|bwMODE1);// needs to be send twice*/
(void)SPI_ReadWrite(bwLINSL2|bwLINSL1); // Sleep Command (MCU off)
(void)SPI_ReadWrite(bwLINSL2|bwLINSL1); // needs to be send twice
SPI_Disable(); // Disable SPI
// Sleep=1; // Sleep
stop(); // enter ULPM
}
// --------------------------------------------------------
// Interrupt Service Routines
// --------------------------------------------------------
#pragma TRAP_PROC
void isrESCIReceive(void) { // SCI Rx
interrupt handler
l_ifc_rx_sci08();
}
// --------------------------------------------------------
#pragma TRAP_PROC
void isrESCIError(void) { // SCI Error
interrupt handler
l_ifc_rx_sci08();
}
// -------------------------------------------------------
l_irqmask l_sys_irq_disable(void){ //Disable
interrupts
sei();
return 0;
}
// -------------------------------------------------------
void l_sys_irq_restore(l_irqmask previous){ //Restore
interrupts
cli();
}
// -------------------------------------------------------
#pragma TRAP_PROC
void ISR_DUMMY(void){ //Dummy ISR
// while(1);
}
// -------------------------------------------------------
#pragma TRAP_PROC
void isrKeyBoard(void) {
swi();
}
// -------------------------------------------------------
// -------------------------------------------------------
#pragma TRAP_PROC
void isrHWIRQ(void) {
UINT8 res;
//swi();
nop();
SPIout = bwMODE2|bwMODE1;
res = SPI_ReadWrite(SPIout);
/*
if(res&brINTSRC) {
}
*/
TimerEnable();
TimerBEnable();
}
4.功能展示

(图片)

5.参考文献:
I.〈〈传感器与接口技术〉〉中国石化化出版社 苏铁力 关振海 孙继红 编著
II. <清华大学出版社 谢瑞和 杨明编著
III.<<908E624 DATA SHEET>> MOTOROLA REV1.0,09/2003
IV. <> REV 5.0, 09/2003 5/31/2005


电脑版 客户端 关于我们
佳工机电网 - 机电行业首选网站