汽车电子技术——ECU/MCU嵌入式软件开发

ECU(Electronic Control Unit)电子控制单元,又称“行车电脑”、“车载电脑”等。
它和普通的电脑一样,由微控制器(MCU)、存储器(ROM、RAM)、输入/输出接口(I/O)、模数转换器(A/D)以及整形、驱动等大规模集成电路组成。用一句简单的话来形容就是“ECU就是车的大脑”。
在自己的前面的博文《汽车电子技术——传感器感知技术》已经论述过,自动驾驶汽车三大关键系统分为:感知、决策、执行等三个层面。“感知”环节即由摄像头、超声波雷达、毫米波雷达、激光雷达等各种传感器完成数据采集,再传输给各类传感器所对应的ECU(电子控制单元)进行数据的分析及处理,各类ECU将处理结果发送至决策微控制器(MCU),MCU将各类ECU发送的处理结果综合之后再向各类汽车系统(例如刹车系统、传动系统等)发出控制指令,最终接受到控制指令的汽车系统将指令予以执行,从而完成整个ADAS系统的功能。
同样博主也在前面的博文《汽车电子技术——软件、硬件、系统集成和项目管理之学习与分享概述》中讨论过,汽车电子控制系统被分为多个子系统,每个子系统包含一个或多个电子控制单元(ECU),软件定义汽车时代之下,一辆现代汽车的ECU数量更可高达上百个。目前博世,电装,大陆,德尔福,采埃孚等都是汽车ECU行业的领导者。
ECU通俗来讲就是MCU加上一些外围必要的电路组成的一个系统,可以对各种输入信号(传感器信号、车载网络信号等)进行加工处理,然后进行信号输出(控制执行器的信号、车载网络信号等)的一个专用嵌入式系统。博主本来在工作中就有接触ECU的实际开发及相关项目管理的部分内容,并且一直保持和开发工程师及软件PM虚心求教学习,本篇博文仅作简要论述下自己在ECU/MCU软件开发中的学习储备,并简要介绍下后续就基于MCU开发板做的一些实际开发学习思路,以供感兴趣的小伙伴参考及讨论。
关于MCU开发板的选择,其实我们公司的ECU中一般都是英飞凌的车规级32位MCU,可以满足安全性与动力要求总成的车用要求。但自己在学习过程中,综合考虑了目前市面上易于获得及学习材料较丰富等因素,我自己选择了意法半导体的主流MCU——STM32F103,这是STM32系列32位MCU,该系列的MCU由于其低廉的价格和强大的功能在嵌入式产品中被广泛应用,同样也可以满足自己了解和学习ECU/MCU软件开发的目的需要。

1. ECU/MCU软件开发知识储备

1.1 ECU/MCU相关基础知识

前面也已经说到,ECU通俗来讲就是MCU加上一些外围必要的电路组成的一个系统,所以本身在学习ECU/MCU软件开发的过程中,相关的基础知识是需要不断积累的。当然博主的博客专题中《汽车电子技术 博客专栏》已经分享了一些自己的学习思路及参考书目,感兴趣的小伙伴们可以查阅参考一下。不过在这里还是进一步分享一下自己的思路:
1.1.1 ECU/MCU相关硕博论文的学习
相比于参考书籍,我认为硕博论文是更加详实和丰富的材料。很多书籍一般都是概括总览性的介绍汽车电子方面的知识,但是往往不会深入到太具体ECU/MCU的开发细节,因为这也是可以理解的,不可能一本书把所有功能应用的技术都写到。具体到更深入的知识学习,则可以通过其他更丰富的资料去获取与学习。网上渠道就可以获取的,硕博论文是很不错的详实材料。关于这一点,自己研究生写硕士论文的时候也深有感悟,硕博论文需要将必要的基础知识与实际具体的研究应用都要逐步展开论述的,从知识的完备和技术论述的细节性来说,都是非常好的。所以找到相关ECU/MCU的硕博论文,仔细学习和深入理解,是很不错的。
1.1.2 工作中产品开发学习
掌握了基础知识之后,如果在实际项目中可以接触到ECU/MCU开发的细节,可以在实践交流中加深对知识的融会贯通。如果自身岗位涉及开发细节不多,那就需要自己创造条件,就拿博主自己来说,博主本身的岗位并不在软件开发岗位,但是整个项目中软件开发相关的PM、开发人员和测试人员等都是有接触的。每次开项目会的时候,关于软件开发进度和问题都是会上会讨论的,认真聆听和学习,是可以把整个软件开发的流程和进度管控等项目管理的点学到,并且会上讨论项目中的问题之时,开发的细节知识就会涉及,也可以好好研学。除此之外,工作之中找熟悉的软件开发相关同事,找他们了解学习工作实践的知识是更关键的,比如更细节具体的开发流程和知识,软件开发过程中的工具链,软件开发核心环节和常规问题及解决方案,以及相应供应链及合作内容等等,这些都是需要用自己的人际关系技能和团队技能去获取的,人际关系技能等也是项目经理的必备技能。如果处在一个完备的开发管理及项目管理的大公司,则公司本身就是一个很好的学习平台。
1.1.3 知识和实践的融会贯通
前面两点,需要融会贯通。知识是基础,是你在工作实践中,无论是去提问咨询或交流学习的基础;工作实践的内容,则是知识的应用和拓展,通过对工作实践中应用到的点,再去针对性学习和拓展自己的知识学习;以上两点不断地融会贯通,自己才能够一步一步加深学习相关领域的知识。
当然除了以上写出来的方法,还是有很多可以补充加深学习的。比如网上很多的公开课视频也是可以学习的,老师的视频授课的学习也是很有助于加深知识理解的,在这里自己推荐一门慕课——《吉林大学 微机原理与接口技术》。

《微机原理与接口技术》课程包括三部分内容:微处理器(CPU)的工作原理、汇编语言程序设计方法和微机接口技术。通过学习,学生可以了解微处理器的基本结构、指令系统和汇编语言程序设计方法、微处理器与主存储器的基本接口、微处理器与设备之间的基本输入输出接口、中断技术、数模(D/A)转换与模数(A/D)转换技术等,还将介绍几款典型数字接口芯片、数/模和模/数转换芯片,同学们由此入门可以达到举一反三触类旁通的效果。

MCU微控制器是ECU的组成基础器件,所以先学习其相关知识,是更好的理解ECU软件开发的。

1.2 C语言编程知识

在嵌入式编程中,C语言是需要掌握的。C语言被称为适合嵌入式系统开发的编程语言之一,是开发者和MCU进行沟通的语言,通过C程序告诉MCU你要它完成什么工作和实现什么样的功能(比如通过一个端口输出一个PWM)。从语法上来说C语言并不复杂,但真正要编写优质可靠的嵌入式C程序并非易事,不仅需要熟知硬件特性和缺陷,还需要对编译原理和计算机技术知识有着一定的了解。
博主在学校的时候考过了计算机二级C语言和三级数据库,并且后来常用的Fortran/Python等语言的学习中,本身对编程开发技术有一定的掌握,自己也买有C语言的经典教材《C Primer Plus》常翻翻和学习。但是学习编程语言,最重要的还是动手coding刷题来得快。

1.3 外围电路

MCU结合搭建相应的外围电路,才能实现其相应的功能,所以需要学习掌握MCU交互的外围电路的原理图。比如下面示例的LED电路图。
在这里插入图片描述

比如要MCU控制一个LED的亮灭,首先需要明确电路上这个LED连在了MCU的哪一个端口上了,可以通过控制该端口的电平状态来点亮和熄灭该LED。其次还要明确端口输出什么电平可以点亮LED,输出什么电平熄灭LED。
就以上图来简要举例,上图中LED_G是由MCU上的PB0端口控制,可以通过该端口来控制绿色LED的亮灭。本身LED一端接的是3V电压,则PB0控制为低电平时导通灯亮,控制为高电平时不导通灯灭。了解了这些以后,再去查阅开发板的具体手册,通过控制GPIO端口时钟,配置IO口和控制ODR寄存器等操作实现开发控制,更便捷的则是通过固件库编程。在实际的项目中,除了控制LED的亮灭外,还要控制LED的亮度水平,这就涉及MCU的PWM(脉冲宽度调制)功能,PWM是一个频率和占空比可以调节的方波,通过调节占空比的大小(0%-100%)来调节LED的亮度,调节占空比其实可以就是调节加在LED上面的电压。
博主大学的时候学过一些电路相关的课程,所以现在都是在学习的过程中,碰上不懂的知识点马上查阅回顾相关知识点,这样在实践中学习进步更快的。网络上还是有很多的电路基础知识的材料,大家也可以自行查阅。
西安交通大学 电路 视频公开课
电子元器件与电路基础知识

2 MCU开发板实践学习

基于上面的一些知识储备,其实就可以开始简单的MCU编程开发了,自己基于市面上主流的32位MCU产品及相关学习材料完备程度等情况综合考虑后,决定采用STM32F103开发板进行学习实践,该开发板上有丰富的外围电路设备,可以实现多种功能,学习后可了解熟悉此类开发板的通用开发流程和技术。

2.1 STM32F103开发板

意法半导体公司(ST)所生产的STM32主流系列产品中的 STM32F103ZET6 芯片,该芯片内核属于 ARM 32 位的 Cortex-M3 型的 STM32F103 系列微型控制器
,该内核采用 7V-ARM 构架,不仅支持 2-Thumb 指令集,而且拥有很多新特性,与其他 ARM 系列芯片相比, 3M-Cortex 拥有更强劲的性能、更高的代码密度、支持位带操作、可嵌套中断、低成本、低功耗等众多优势。芯片嵌入了 512K 的闪存程序存储器,工作频率高达 72MHz,提供了多达 11 个定时器、13 个通信接口,支持 I2C 、ADC、 SDIO、I2S、SPI、USART 和定时器,103 个快速的 I/O 端口,-40到+85℃工作温度可满足车载要求,适用于电机驱动、应用控制、电力电子系统、GPS 平台、打印机、警报系统、扫描仪、打印机、视频对讲等方面的应用。

在这里插入图片描述
下图为该开发板集成的众多外设示意图:
在这里插入图片描述

2.2 MDK5软件集成开发

自己在MCU开发过程中使用的开发工具是MDK5 。MDK(Real View MDK)是德国的 keil 公司开发的开源软件。MDK5开发工具是使用最广泛的编译软件之一,集成了 STM32底层软件程序的编辑、编译、仿真与下载的功能。全世界有超过 10 万多的嵌入式开发工程师在使用 MDK。经过多年的实践开发,目前这 MDK 已经升级为MDK5.14,这个版本的 MDK 使用 u Vision5 IDE(集成开发环境),这个版本的 MDK 主要针对于 ARM 处理器,尤其针对于 Cortex M 内核处理器,是这个内核处理器最好的开发工具。MDK5 兼容之前的 MDK4 和 MDK3 等,支持以前的项目进行再次开发(不过得需要自己添加头文件),MDK5 不仅在技术方面支持了 Cortex M 处理器,而且对传统的界面和开发模式进行了全面的升级,更加人性化。目前的 MDK5 由 MDK Core 和 Software Packs 这两个部分组成。其中 Software Packs可以单独对芯片和中间库进行升级工作。如图下图所示:
在这里插入图片描述
从上面的图中可以看出,MDK Core 可以分成四个主要部分,分别是 u Vision IDEwith Editor( 编辑器)、ARMC/C++ Compiler( 编译器)、Pack Installer( 包安装器)和 u Vision Debugger with Trace( 调试跟踪器)。Software Pack(包安装器)大致可以分为 Device(芯片支持)、CMSIS( ARM Cortex 微控制器软件接口标准)和Mdidleware(中间库)三个小集合。通过 Software Pack,开发人员可以安装最新的配套组件来支持最新的设备和例程等。通过这个 Software Pack 大大加开了开发人员的工作进程。对于安装组件,MDK5 也与之前的版本的组件已经有了很大的改进,MDK5 的组件是与设备等其他的组件分别安装,这样有利于选择不同的设备组件,这样大大减小了MDK Core 安装文件。对于设备驱动和 CMSIS 等其他组件,可以通过点击 MDK5 中的Build Toolbar 来进行各个组件的安装。安装完 MDK5 后,还得需要安装有关 STM32F103的器件安装包,这样才可以进行相应的开发工作。

2.3 简单应用示例——流水灯

博主使用的是MDK528版本软件,在创建工程的时候,记得注意做好芯片类型和仿真器等配置工作,根据自己买的这块开发板信息,选择的是STM32f103ZE 这个芯片,不同的芯片区别在于对应的电路引脚图不同,也就是GPIO口可能会不同,不过道理和方法都还是一样的。仿真器为Fire-Debugger,其遵循ARM公司的CMSIS-DAP 标准,支持所有基于Cortex-M内核的单片机,常见的M3、M4 和M7 都可以完美支持。一些配置选项如下:

在这里插入图片描述

硬件设计

LED硬件原理图
STM32f103ZE 芯片的LED灯硬件原理图如下,这是一个RGB 灯,里面由红蓝绿三个小灯构成, 使用PWM控制时可以混合成256256256 种不同的颜色。本次只给出简单的三色流水灯控制实现。
在这里插入图片描述

这些LED 灯的阴极都是连接到STM32 的GPIO 引脚,只要我们控制GPIO 引脚的电平输出状态,即可控制LED灯的亮灭。以点亮绿灯来举例,上图中LED_G是由MCU上的PB0端口控制,可以通过该端口来控制绿色LED的亮灭。本身LED一端接的是3V电压,则PB0控制为低电平时导通灯亮,控制为高电平时不导通灯灭。
总线构架和存储器
下图为STM32F10xxx的总线架构和存储器信息,系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通过这根系统总线来完成的。从AHB 总线延伸出来的两条APB2 和APB1 总线,上面挂载着STM32各种各样的特色外设,GPIO、串口、I2C、SPI这些外设就挂载在这两条总线上,两个AHB/APB桥在AHB和2个APB总线间提供同步连接。APB1操作速度限于36MHz,APB2操作于全速(最高72MHz)。
在这里插入图片描述

有上面可知,LED灯的都是由GPIO端口B控制,APB2是操作于全速(最高72MHz)的总线,对APB2进行操作前,需要结合AHB总线的控制,通过复位和时钟控制(RCC)来开启端口GPIOB的时钟。也就是结合GPIOB的时钟及端口参数控制,进而实现LED灯的点亮和关闭。

软件设计

开发板中把芯片的引脚引出来,连接到各种传感器上,然后在STM32 上编程(实际就是通过程序控制这些引脚输出高电平或者低电平)来控制各种传感器工作,本节就LED灯的编程控制做简要的介绍。
在硬件设计部分已经分析了,通过开启相应端口的时钟及端口参数的设置,即可控制LED灯的亮灭。实际上,被控单元的FLASH,RAM,FSMC和AHB到APB的桥(即片上外设),这些功能部件共同排列在一个4GB 的地址空间内。在实际编程的时候,可以通过他们的地址找到他们,然后来操作他们(通过C语言对它们进行数据的读和写)。
比如,我们找到GPIOB端口的输出数据寄存器ODR的地址是0x4001 0C0C,ODR 寄存器是32bit,低16bit有效,对应着16个外部IO,写0/1对应的的IO 则输出低/高电平。通过C语言指针的操作方式,可以指定GPIOB的IO端口都输出低/高电平。结合刚才LED硬件设计的分析后,我们可以直接通过绝对地址访问内存单元,编程实现点亮某单色灯-如绿灯,该主程序如下:

#include "stm32f10x.h"
int main (void)
{
	// 打开 GPIOB 端口的时钟 PB0绿灯
	*( unsigned int * )0x40021018 |=  ( (1) << 3 );	

	// 配置IO口为输出 打开
	*( unsigned int * )0x40010C00 |=  ( (1) << (4*0) );
	
	// 控制 ODR 寄存器 低电平
	*( unsigned int * )0x40010C0C &= ~(1<<0);
}

然而通过绝对地址访问内存单元不好记忆且容易出错,实际上ST公司已经提供的标准软件库,包含了STM32芯片所有寄存器的控制操作,直接学习如何使用ST标准库,会极大地方便控制STM32 芯片。STM32 的标准库文件中为我们编写好驱动外设的函数接口,我们只要调用这些库函数,就可以对STM32 进行配置,达到控制目的。通过查阅库帮助文档,即可了解调用函数的功能、可传入的参数及其意义、和函数的返回值等信息。这为我们的实际软件开发工作提供了极大的便利。
以下就给出自己编程实现的三色LED流水灯程序的核心部分的代码,注意流水灯实现过程中,只要让其中一个灯亮,其他都灭就可以,也就是让其中一个GPIO口的值是低电平0,其他都是1就可以了。
在这里插入图片描述
实际流水灯效果如下:
在这里插入图片描述

核心程序代码如下:
main.c:注意只让其中一个灯亮,其他都灭。

#include "stm32f10x.h"
#include "bsp_led.h"

#define SOFT_DELAY Delay(0x0FFFFF);

void Delay(__IO uint32_t nCount)	 //延时函数
{
	for(; nCount != 0; nCount--);
} 

int main(void)
{	
	/* LED 端口初始化 */
	LED_GPIO_Config();	 

	while (1)
	{
		LED_B(OFF);			
		LED_R(OFF);
		LED_G(ON);		 //亮绿灯  
		SOFT_DELAY;
		LED_R(OFF);
		LED_G(OFF);
		LED_B(ON);	   //亮蓝灯 			   
		SOFT_DELAY;
		LED_B(OFF);	
		LED_G(OFF);		
		LED_R(ON);     //亮红灯 				   
		SOFT_DELAY;	 
	
	}
}

bsp_led.c:注意开启所有LED相关的GPIO外设时钟。

#include "bsp_led.h"   
void LED_GPIO_Config(void)
{		
		/*定义一个GPIO_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef GPIO_InitStructure;

		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( LED_R_GPIO_CLK | LED_G_GPIO_CLK | LED_B_GPIO_CLK, ENABLE);

		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

		/*设置引脚速率为50MHz */   
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	
		/*选择要控制的GPIO引脚-PB0-红灯*/
		GPIO_InitStructure.GPIO_Pin = LED_R_GPIO_PIN;	
		/*调用库函数,初始化GPIO*/
		GPIO_Init(LED_R_GPIO_PORT, &GPIO_InitStructure);	
		
		/*选择要控制的GPIO引脚-PB0-绿灯*/
		GPIO_InitStructure.GPIO_Pin = LED_G_GPIO_PIN;
		GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStructure);
		
		/*选择要控制的GPIO引脚-PB0-蓝灯*/
		GPIO_InitStructure.GPIO_Pin = LED_B_GPIO_PIN;
		GPIO_Init(LED_B_GPIO_PORT, &GPIO_InitStructure);

}

bsp_led.h:注意LED相关的GPIO端口明确,置位函数与复位函数等函数定义。

#ifndef __LED_H
#define	__LED_H

#include "stm32f10x.h"

/* 定义LED连接的GPIO端口 */
// R-红色
#define LED_R_GPIO_PORT   GPIOB			              /* GPIO端口 */
#define LED_R_GPIO_CLK 	  RCC_APB2Periph_GPIOB		/* GPIO端口时钟 */
#define LED_R_GPIO_PIN		GPIO_Pin_5			        /* 连接到SCL时钟线的GPIO */

// G-绿色
#define LED_G_GPIO_PORT   GPIOB			              
#define LED_G_GPIO_CLK 	  RCC_APB2Periph_GPIOB	
#define LED_G_GPIO_PIN	  GPIO_Pin_0			        

// B-蓝色
#define LED_B_GPIO_PORT   GPIOB			             
#define LED_B_GPIO_CLK 	  RCC_APB2Periph_GPIOB		
#define LED_B_GPIO_PIN		GPIO_Pin_1			        

#define ON  0
#define OFF 1

/* 使用标准的固件库控制IO*/
#define LED_R(a)	if (a)	\
					GPIO_SetBits(LED_R_GPIO_PORT,LED_R_GPIO_PIN);\
					else		\
					GPIO_ResetBits(LED_R_GPIO_PORT,LED_R_GPIO_PIN)

#define LED_G(a)	if (a)	\
					GPIO_SetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);\
					else		\
					GPIO_ResetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN)

#define LED_B(a)	if (a)	\
					GPIO_SetBits(LED_B_GPIO_PORT,LED_B_GPIO_PIN);\
					else		\
					GPIO_ResetBits(LED_B_GPIO_PORT,LED_B_GPIO_PIN)

void LED_GPIO_Config(void);

#endif /* __LED_H */

以上即为基于STM32f103ZE开发板实现的简单三色流水灯控制,以上只是论述了部分关键原理及核心代码,还有很多的知识点并未一一列举出来,有兴趣有疑问的小伙伴可以随时提问出来,共同讨论学习进步。关于ECU/MCU软件开发及STM32f103ZE开发板的相关学习,自己始终都在持续进行,除了自己看书及编程实践学习之外,还在工作中找我们产品软件开发的小伙伴们学习探讨,但是限于个人时间有限等原因,很多的点并没有时间和功夫分享上来,但是对这些方面有兴趣或同样持续学习中的小伙伴们,欢迎大家提问探讨。

3. 参考学习的书籍

  1. 《汽车电子学教程》李建秋 等著
  2. 《C Primer Plus》 Stephen Prata 著
  3. 《汽车电子技术—硬件、软件、系统集成和项目管理》Kai Borgeest 著 武震宇 译
  4. 《嵌入式系统 硬件软件及软硬件协同》 Tammmy Noergaar 著 马志欣 等译
  5. 《电子系统设计 面向嵌入式硬件电路 马洪连 等著
  6. 《STM32F10x-中文参考手册》 意法半导体(中国)投资有限公司
  7. 《零死角玩转STM32—F103霸道》 野火STM32教程

=文档信息=
本学习笔记由博主整理编辑,仅供非商用学习交流使用
由于水平有限,错误和纰漏之处在所难免,欢迎大家交流指正
如本文涉及侵权,请随时留言博主,必妥善处置
版权声明:非商用自由转载-保持署名-注明出处
署名(BY) :zhudj
文章出处:https://zhudj.blog.csdn.net/

  • 92
    点赞
  • 790
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值