在前面的章节中,我们首先复习了STM32最小系统的搭建,又复习了UCOS移植的理论,这样使我们对整个UCOS的移植有了整体印象。在本章节中,我们将通过具体的实际编码,实现STM32最小系统在原子探索者开发板(主控芯片STM32F407ZGT6)的代码移植和功能验证。

emwin 最小 最小系统代码_proteus如何添加stm32

    上图是正点原子的探索者开发板全貌,支持的硬件和外围设备较多,但是在本章中,我们仅仅按照最小系统的需求,使用其中的【USB转串口】功能单元,用于调试信息Debug的输出和二进制代码的烧录。根据前面章节的复习,我们在本章中将按照如下的顺序完成STM32最小系统的软件开发及代码烧录验证工作。

emwin 最小 最小系统代码_emwin 最小_02

【代码文件架构组织】

    合理的代码架构,便于代码的管理和再次开发,也便于后续的代码维护。根据最小系统代码的类别,我们对最小系统的代码进行如下分类:

emwin 最小 最小系统代码_emwin 最小_03

    其中:各个文件夹的用途如下图所示:

emwin 最小 最小系统代码_emwin 最小_04

【MDK5的代码编译设定】

MDK 源自德国的 KEIL公司,使用uVision5 IDE 集成开发环境,是目前针对 ARM 处理器,尤其是 Cortex M 内核处理器的最佳开发工具。我们使用的版本为MDK5.14版本。如何安装MDK软件和如何使用MDK软件不是本章的重点。本章节中,我们重点讲解如何配置MDK软件进行代码编译。

    根据上一个章节的代码架构,我们在MDK软件中创建STM32Test项目,并添加完对应的文件。

emwin 最小 最小系统代码_iapp启动图代码_05

    仅仅添加完这些C语言的源文件(c文件和S文件),是完全不够的。我们还需要告诉MDK在编译这些源文件的时候,声明用的头文件在哪里寻找,否则编译是无法通过的。

emwin 最小 最小系统代码_iapp启动图代码_06

    添加完之后的效果如下图所示:

emwin 最小 最小系统代码_iapp启动图代码_07

    最后,定义全局宏定义STM32F40_41xxx,USE_STDPERIPH_DRIVER指明该项目为STM32F4系列,同时使用STM32标准的驱动库。

emwin 最小 最小系统代码_GPS 校验和 代码_08

    至此,基本的STM32F407的MDK代码项目建立完成,编译通过。下面将开始下一步的最小系统的代码修改工作。(现在用的都是STM32固件库的默认配置,所以下面我们需要根据使用的硬件具体的配置进行对应修改)

emwin 最小 最小系统代码_proteus如何添加stm32_09

【时钟代码配置】

我们使用的开发板,外部高速晶振频率为8MHz,同时为了使CPU达到最大的168MHz工作频率,需要配置相关的PLL锁相环电路,实现准确的分频操作。具体修改如下:

- 修改外部高速时钟晶振宏定义:

emwin 最小 最小系统代码_proteus如何添加stm32_10

- 修改PLL锁相环电路分频宏定义:

emwin 最小 最小系统代码_proteus如何添加stm32_11

【启动文件编写】

因为我们不需要修改意法半导体提供的启动文件中的堆栈大小设置,故此处直接使用startup_stm32f40_41xxx.s文件即可。

【串口Debug功能代码开发】

    正如前面提及到Debug功能,为了验证最小系统正常启动和运行,我们需要借助于其他辅助的方式,如串口打印输出,Led跑马灯等作为验证最小系统正常运行的指标和信号。在本章中,我们设计并开发串口驱动功能,以实现调试信息的对外输出。

emwin 最小 最小系统代码_GPS 校验和 代码_12

开启时钟

emwin 最小 最小系统代码_emwin 最小_13

从开发板的硬件原理图中我们可以看到,串口1的硬件连接使用了PA9和PA10共计两个GPIO引脚,所以我们既要开启GPIOA的时钟,也必须开启USART1的时钟。

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);  //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  //使能USART1时钟

    具体是选择那条总线时钟,请参考对应的STM32芯片手册。

GPIO初始化

    每个通用的GPIO引脚,为了保证支持更多的功能,都支持端口复用功能,即一个引脚可以支持多个功能输入,但是具体使用何种功能,需要在使用之前进行配置。同样,即使选择某种复用功能,也必须完成基本的GPIO相关配置,具体详细代码如下图所示:

emwin 最小 最小系统代码_proteus如何添加stm32_14

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //PA9 复用USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);//PA10复用USART1

基本的GPIO配置代码如下:

GPIO_InitStructure.GPIO_Pin   =GPIO_Pin_9 | GPIO_Pin_10; //使用Pin9和10
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;             //端口复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;            //推挽复用输出
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;             //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure);                     //初始化

串口参数配置

串口的参数,涉及到波特率,校验方式等相关信息,需要针对工程的需要进行配置,我们根据Debug需要,对串口进行如下配置:

USART_InitStructure.USART_BaudRate   = 9600;               //波特率为 9600;
USART_InitStructure.USART_WordLength =USART_WordLength_8b;//字长为8位
USART_InitStructure.USART_StopBits   = USART_StopBits_1;   //一个停止位
USART_InitStructure.USART_Parity     = USART_Parity_No;    //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode =USART_Mode_Rx | USART_Mode_Tx;//收发模式
USART_Init(USART1,&USART_InitStructure);                      //初始化串口

初始化串口后,我们还必须对其进行使能操作:

USART_Cmd(USART1, ENABLE);   //使能串口USART1

中断配置

到现在为止,基本上完事具备,只差中断了。为什么这么说呢?中断,作为外界事件和内部运行情况的一种通知机制,就是用来告诉STM32 CPU,外面和内部发生了什么,需要停下来看看情况进行CPU的处理和决策。

在使用中断前,需要对中断进行配置:

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;        //串口1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;       //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);                    //初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);          //开启接收中断

    配置了中断,但是我们还必须提供中断服务函数ISR,否则即使CPU知道了中断发生,没有ISR的话,也没有办法进行处理。从startup_stm32f40_41xxx.s中,串口1的接收中断如下定义:

emwin 最小 最小系统代码_iapp启动图代码_15

也就是说,我们必须使用代码实现USART1_ISRHandler接口,以实现USART1的串口中断处理过程。因为我们最小系统主要实现信息的对外输出,该ISR并未有具体实现。但是为了实现信息的对外输出,我们需要调用USART_SendData函数。例如:USART_SendData (USART1, data)。因为串口是硬件的一种,我们将新创建的uart.c文件放在Hardware文件夹中。

emwin 最小 最小系统代码_proteus如何添加stm32_16

【main函数代码开发】

    通过编写简单的main函数,实现对外的信息输出,验证最小系统的启动情况。

【代码烧录】

    因为不同的开发板,有不同的代码烧录步骤,此部分就不再论述。请参考所选择的开发板手册进行学习。

    经过烧录到板子验证,输出了打印调试信息,证明STM32最小系统已经顺利启动。

emwin 最小 最小系统代码_emwin 最小_17