首页 > 其他分享 >《ARM Cortex-M3与Cortex-M4权威指南》 第2章 嵌入式软件开发简介

《ARM Cortex-M3与Cortex-M4权威指南》 第2章 嵌入式软件开发简介

时间:2025-01-13 12:58:27浏览次数:3  
标签:LED TIM CMSIS M4 嵌入式软件 Cortex GPIO void 微控制器

2.1 ARM微控制器是怎样构成的

ARM微控制器通常由处理器内核(如Cortex - M3或Cortex - M4)、片上外设(如定时器、串口、ADC等)、内存(包括Flash用于存储程序代码,SRAM用于数据存储)以及总线系统组成。处理器内核负责执行指令,片上外设实现与外部设备的交互,内存用于存储程序和数据,总线系统则负责在各个组件之间传输数据和控制信号。

2.2 开始时需要准备什么

2.2.1 开发组件

开发ARM微控制器通常需要以下组件:

  • 编译器:将高级语言(如C)编写的代码转换为微控制器能够执行的机器语言。例如GCC(GNU Compiler Collection),它是一款常用的开源编译器。
  • 调试器:用于查找和修复代码中的错误。例如OpenOCD,它支持多种调试接口(如JTAG、SWD)。
2.2.2 开发板

开发板是进行开发的硬件平台,它集成了ARM微控制器以及相关的外围电路,如电源电路、通信接口等。常见的开发板有STMicroelectronics的STM32系列开发板,方便开发者快速搭建开发环境。

2.2.3 调试适配器

调试适配器用于连接开发板和调试主机(如PC),实现调试器与微控制器之间的通信。例如,ST - Link就是STMicroelectronics为其STM32系列微控制器提供的调试适配器,支持JTAG和SWD调试接口。

2.2.4 软件设备驱动

软件设备驱动是控制微控制器片上外设的程序代码。例如,UART驱动程序用于实现串口通信,它负责配置UART外设的寄存器,实现数据的发送和接收。

2.2.5 例子

以一个简单的LED闪烁程序为例,假设使用STM32开发板:

#include "stm32f10x.h" // 包含对应芯片的头文件,定义了寄存器等

// 初始化LED GPIO口
void LED_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct; // 定义GPIO初始化结构体

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; // 选择PA5引脚
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 设置为推挽输出模式
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 设置输出速度
    GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化GPIOA
}

int main(void) {
    LED_Init(); // 初始化LED

    while (1) {
        GPIO_SetBits(GPIOA, GPIO_Pin_5); // 点亮LED
        for (volatile int i = 0; i < 500000; i++); // 简单延时
        GPIO_ResetBits(GPIOA, GPIO_Pin_5); // 熄灭LED
        for (volatile int i = 0; i < 500000; i++); // 简单延时
    }
}

在这个例子中,LED_Init函数用于初始化LED连接的GPIO口,这里体现了初始化模式,即将特定的GPIO口配置为所需的输出模式。main函数中通过循环点亮和熄灭LED,使用了简单的轮询模式来控制LED闪烁。

2.2.6 文档和其他资源

开发过程中需要参考多种文档和资源:

  • 芯片数据手册:详细描述微控制器的硬件特性,如引脚功能、寄存器配置等。
  • 参考手册:提供更深入的技术细节,如指令集、系统架构等。
  • 应用笔记:由芯片厂商提供,介绍如何在特定应用场景下使用微控制器。
2.2.7 其他设备

根据具体应用需求,可能还需要其他设备,如传感器用于数据采集,执行器用于控制外部设备等。

2.3 软件开发流程

  1. 需求分析:明确应用的功能需求,例如设计一个温度监测系统,需要确定测量范围、精度要求等。
  2. 设计:包括硬件设计(选择合适的微控制器和外围电路)和软件设计(确定软件架构、模块划分等)。例如,在温度监测系统中,选择带有ADC外设的微控制器用于采集温度传感器数据,软件设计上划分温度采集、数据处理和显示等模块。
  3. 编码:使用编程语言(如C)编写代码实现设计的功能。
  4. 调试:使用调试器查找和修复代码中的错误,确保程序按预期运行。
  5. 测试:对软件进行功能和性能测试,验证是否满足需求。

2.4 编译应用程序

以GCC编译器为例,编译过程通常包括以下步骤:

  1. 预处理:处理源代码中的预处理指令(如#include#define)。例如,#include "stm32f10x.h"指令会将指定的头文件内容插入到源文件中。
  2. 编译:将预处理后的代码转换为汇编代码。编译器会对C语言代码进行语法和语义分析,生成对应的汇编指令。
  3. 汇编:将汇编代码转换为目标文件(.o文件),目标文件包含机器语言指令,但还未进行链接。
  4. 链接:将多个目标文件以及所需的库文件链接成可执行文件。链接过程会解决函数和变量的引用问题,将各个模块组合成一个完整的可执行程序。

2.5 软件流程

2.5.1 轮询

轮询是一种简单的软件流程,程序通过不断查询某个条件或状态来执行相应操作。例如,查询按键状态:

#include "stm32f10x.h"

void Button_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 设置为浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStruct);
}

int main(void) {
    Button_Init();

    while (1) {
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) { // 查询按键是否按下
            // 执行按键按下后的操作
        }
    }
}

这里体现了轮询设计模式,程序不断检查按键状态,一旦检测到按键按下,就执行相应操作。这种模式简单直接,但会占用较多CPU资源,适用于对实时性要求不高且任务相对简单的场景。

2.5.2 中断驱动

中断驱动方式下,当特定事件发生时(如外部中断、定时器中断等),微控制器会暂停当前执行的任务,转而执行中断服务程序。例如,使用定时器中断实现定时功能:

#include "stm32f10x.h"

// 定时器初始化函数
void TIM3_Init(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能TIM3时钟

    TIM_TimeBaseStructure.TIM_Period = 9999; // 设置自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 设置预分频器
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 使能更新中断

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; // 选择TIM3中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; // 设置抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; // 设置子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM3, ENABLE); // 使能定时器
}

// 定时器3中断服务函数
void TIM3_IRQHandler(void) {
    if (TIM_GetITStatus(TIM3, TIM_IT_Update)!= RESET) {
        // 执行定时任务
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清除中断标志位
    }
}

int main(void) {
    TIM3_Init();

    while (1) {
        // 主循环可以执行其他任务
    }
}

这里体现了中断驱动设计模式。通过定时器中断,在设定的时间间隔触发中断服务程序,执行定时任务。主循环可以继续执行其他任务,提高了CPU的利用率,适用于对实时性要求较高的场景。

2.5.3 多任务系统

多任务系统允许在一个微控制器上同时运行多个任务,每个任务可以看作是一个独立的程序。例如,使用FreeRTOS实时操作系统实现多任务:

#include "FreeRTOS.h"
#include "task.h"

// 任务1函数
void Task1(void *pvParameters) {
    while (1) {
        // 任务1的代码
        vTaskDelay(pdMS_TO_TICKS(1000)); // 任务1延时1秒
    }
}

// 任务2函数
void Task2(void *pvParameters) {
    while (1) {
        // 任务2的代码
        vTaskDelay(pdMS_TO_TICKS(2000)); // 任务2延时2秒
    }
}

int main(void) {
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL); // 创建任务1
    xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL); // 创建任务2

    vTaskStartScheduler(); // 启动任务调度器

    while (1) {
        // 正常情况下不会执行到这里
    }
}

这里体现了多任务设计模式。通过FreeRTOS,创建了两个任务Task1和Task2,每个任务有自己独立的执行逻辑和运行时间。任务调度器负责在不同任务之间进行切换,使得多个任务看似同时运行,提高了系统的并发处理能力,适用于复杂的应用场景。

2.6 C程序中的数据类型

在ARM微控制器开发中,常用的C数据类型包括:

  • 基本数据类型:如char(字符型,通常占1字节)、short(短整型,通常占2字节)、int(整型,通常占4字节)、long(长整型,通常占4字节或8字节)、float(单精度浮点型,通常占4字节)、double(双精度浮点型,通常占8字节)。
  • 派生数据类型:如数组、指针、结构体、联合体等。数组用于存储多个相同类型的数据,指针用于存储变量的地址,结构体用于将不同类型的数据组合在一起,联合体则允许不同数据类型共享同一内存空间。

2.7 输入、输出和外设访问

通过微控制器的寄存器来访问外设。例如,访问GPIO口控制LED:

#include "stm32f10x.h"

int main(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟

    GPIOA->CRL &= ~(0x0F << (4 * 5)); // 清除PA5的配置位
    GPIOA->CRL |= (0x03 << (4 * 5)); // 设置PA5为推挽输出,50MHz

    while (1) {
        GPIOA->BSRR = GPIO_Pin_5; // 点亮LED
        for (volatile int i = 0; i < 500000; i++);
        GPIOA->BRR = GPIO_Pin_5; // 熄灭LED
        for (volatile int i = 0; i < 500000; i++);
    }
}

这里通过直接操作GPIO寄存器(如CRLBSRRBRR)来配置GPIO口的模式并控制LED的亮灭,实现了对外设的访问。

2.8 微控制器接口

微控制器常见的接口包括:

  • GPIO(通用输入输出口):用于连接外部设备,如LED、按键等,通过配置GPIO寄存器可以设置其输入或输出模式。
  • UART(通用异步收发传输器):用于串行通信,如与PC进行串口通信,需要配置波特率、数据位、停止位等参数。
  • SPI(串行外设接口):用于高速同步串行通信,常用于连接Flash、传感器等设备。
  • I2C(集成电路总线):用于低速同步串行通信,常用于连接多个IC设备,如EEPROM、传感器等。

2.9 Cortex微控制器软件接口标准(CMSIS)

2.9.1 CMSIS简介

CMSIS(Cortex Microcontroller Software Interface Standard)是ARM公司为Cortex - M系列微控制器制定的软件接口标准,旨在提供统一的软件编程接口,提高软件的可移植性和可重用性。

2.9.2 CMSIS - Core所做的标准化
  • 内核寄存器访问:提供了一组标准的函数和宏,用于访问Cortex - M内核的寄存器,如NVIC(Nested Vectored Interrupt Controller)寄存器,使不同厂商的微控制器在中断处理方面有统一的编程接口。
  • 系统初始化:定义了系统初始化函数SystemInit,用于初始化微控制器的系统时钟、外设等,确保在不同微控制器上有一致的初始化流程。
2.9.3 CMSIS - Core的组织结构

CMSIS - Core主要包括以下几个部分:

  • 内核头文件:定义了内核寄存器的结构体和访问函数,如core_cm3.hcore_cm4.h,针对Cortex - M3和Cortex - M4内核。
  • 启动文件:包含启动代码,用于初始化堆栈、调用SystemInit函数等,不同厂商的微控制器可能有不同的启动文件,但都遵循CMSIS标准。
  • 系统头文件:定义了系统相关的配置和函数,如system_stm32f10x.h,针对特定厂商的微控制器系列。
2.9.4 如何使用CMSIS - Core
  1. 包含头文件:在源文件中包含相应的CMSIS头文件,如#include "core_cm3.h"(对于Cortex - M3内核)。
  2. 调用初始化函数:在程序开始时调用SystemInit函数进行系统初始化。
  3. 使用寄存器访问函数:通过CMSIS提供的函数和宏访问内核寄存器,例如使用NVIC_SetPriority函数设置中断优先级。
2.9.5 CMSIS的优势
  • 可移植性:基于CMSIS编写的代码可以在不同厂商的Cortex - M微控制器上轻松移植,减少了软件移植的工作量。
  • 可重用性:CMSIS提供的标准接口和函数可以被多个项目重用,提高了开发效率。
  • 代码一致性:不同厂商的微控制器在使用CMSIS后,软件编程风格更加一致,便于开发人员学习和维护代码。
2.9.6 CMSIS的多个版本

CMSIS有多个版本,随着Cortex - M系列处理器的发展和新特性的加入,CMSIS也不断更新。每个版本在功能和兼容性上有所改进,例如支持新的内核特性、优化代码结构等,开发者需要根据所使用的微控制器和开发需求选择合适的CMSIS版本。

标签:LED,TIM,CMSIS,M4,嵌入式软件,Cortex,GPIO,void,微控制器
From: https://blog.csdn.net/qq_40844444/article/details/145049911

相关文章

  • 在keil中ARMCC v6 编译器中用C语言实现ARM cortex-M4 实现startup代码
    #include"stdint.h"#defineStack_Size0x00000800U#defineHeap_Size0x00000400Uuint8_tStack_Mem[Stack_Size]__attribute__((section("STACK")));uint32_t*const__initial_sp=(uint32_t*)&Stack_Mem[Stack_Size];uint8_tHeap_......
  • JSP客制化键盘网站ql5m4(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求: 开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、项目背景随着电子竞技的迅猛......
  • exam4-作业整理(包含部分统考真题)
    exam4-作业整理(包含部分统考真题)H1概述相关CPU提速计算答案是D这里把这道题拿过来,主要是因为容易出小错误,速度提升50%,不意味着时间变成50%v=v*3/2;t=t*2/3CPI与时间答案是C这里要算时间,CPI*指令数量*指令周期时间机器字长的寄存器机器字长......
  • 某苏人社异步JS逆向加解密分析(sm2+sm3+sm4)
    前期准备网址:aHR0cHM6Ly9ycy5qc2hyc3MuamlhbmdzdS5nb3YuY24vaW5kZXgv目标:接口请求内容加密和响应内容解密请求头加密参数Web-Encrypt-Response-Encrypt-Key和Web-Encrypt-Sign涉及内容:jsworker多线程通信axios网络请求库国密sm2、sm3、sm4Axios网址:Axios这......
  • 复盘---我的第一次嵌入式软件工程师笔试_25/1/4
    复盘---我的第一次嵌入式软件工程师笔试_25/1/4总结​ 结果上来说,笔试的结果很差。自己三天准备的方向与实际笔试的题目偏差很大。通过网络上获取的笔试信息以及同学的经验,对比实际笔试还是有很大差异的。但根本原因还是自身的硬实力不够。有以下几个改善方向:通信协议方面,不能......
  • 《我的嵌入式软件之旅:在创新与优化的道路上自我反省》
            作为一名嵌入式软件工程师,我至今的职业生涯虽仅短短五年,但却充满了对创新和优化的不懈追求。特别是在阅读《设计原本》后,深刻反省了关于创新、优化、问题空间和解空间关系。也陷入了自我矛盾的状态,更甚与当代主流的AI有过激烈的“争论”,结果出人意料——Ai被成......
  • ARM Cortex-M系列
    单片机是一种集成在电路芯片上的计算机系统,它将中央处理器(CPU)、内存、输入/输出接口等主要组件集成在一个或少数几个大规模集成电路芯片上。这种高度集成的设计使得单片机具有体积小、功耗低、成本低以及可靠性高的特点,广泛应用于各种自动化控制领域,如家用电器、工业设备、汽车......
  • 关于SM4加解密的记录
    开头:最近对接的项目要求对用户信息进行SM4加秘传递,所以了解了一下使用方法1,使用方式安装依赖:npmi gm-crypto2,使用 const{SM4}=require('gm-crypto')constkey='0123456789abcdeffedcba9876543210'//Anystringof32hexadecimaldigitsconstoriginalData=......
  • 东方通TongWeb7.0.4.9M4部署SuperMap iServer 11.2.1
    一、软件版本操作系统:CentOSLinuxrelease7.5.1804(Core)JDK:11.0.18东方通:TongWeb7.0.4.9M4SuperMapiServer:11.2.1JDK和TongWeb软件分享:链接:https://pan.baidu.com/s/1HGDTPnPID0PEOMbg3FjTVQ?pwd=bh8v提取码:bh8v东方通软件许可请从其官网申请二、东方通......
  • SM4加密算法介绍
    1.SM4算法介绍引用百度百科的介绍:SM4.0(原名SMS4.0)是中华人民共和国政府]采用的一种[分组密码标准,由国家密码管理局于2012年3月21日发布。相关标准为“GM/T0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”。在商用密码体系中,SM4主要用于数据加密,其算法公开,分组长度与密钥......