嵌入式开发从入门到入土

写在前面的话

嵌入式开发涉及的层面很广,它既有底层硬件的开发,又涉及上层应用的开发,也就是所谓的系统集成的硬件和软件。而C语言不仅具有汇编语言操作底层的优势,又具有高级开发语言的功能性强的特点,当之无愧地成为了嵌入式开发中的主流语言。

所以,”在STM32开发过程中,不论是基于寄存器开发还是基于库开发,深入理解和掌握嵌入式C语言的函数、指针、结构体,这是学习STM32的关键“

嵌入式为何物?

网上一搜,教材一翻,关于嵌入式的简介满天飞,分析的很专业,解释的很透彻,但是…看不懂

伟大的现代哲学家吕小布说过,所谓教材就是把一堆简单易懂的名词扩写成一堆谁也看不懂的句子。

“沿波讨源,虽幽必显”,嵌入式其实就在我们身边,一些小家电,电饭煲、热水壶、冰箱、空调、洗衣机等,在这些琳琅满目的家电里面有那么一块电路板,上面焊满了各式各样的电子元器件和芯片。如果这些家电需要带上一些**“智能化”**功能如按键、显示屏、定时、感应等功能,则需要加一个可编程芯片,这个芯片就是单片机,也是微控制器,是这个电路板的大脑,单片机编程,从某种意义来说就是嵌入式开发

比如这个芯片:
在这里插入图片描述

STM32的数据类型

  • 数据是嵌入式中C语言的基本操作对象,数据类型指的是数据在计算机内的存储方式

一些基本类型如下图:

在这里插入图片描述

  • 由于不同CPU定义的数据类型的长度不同,因此ARM公司联合其他半导体厂商制定了统一的CMSIS 软件标准,这个标准中预先定义了相关的数据类型,ST公司也为开发人员提供了基于C语言的标准外设库 :
1	STM32定义的数据类型
CSTM功能
unsigned charuint8_t0~255
unsigned short intuint16_t0~65535
unsigned intuint32_t0 ~ (2^32) - 1
unsigned long longuint64_t0 ~ (2^64) - 1
signed charint8_t(-128) ~ (+127)
signed short intint16_t(-32768) ~ (+32767)
signed intint32_t(-2^31) ~ (+2^31) - 1
signed long longint64_t(-2^64) ~ (+2^64) - 1
2	STM32的IO类型限定词
IO类型限定词类型说明
_IVolatile const只读
_Ovolatile只写
_IOvolatile读写

C语言中常用的关键字

1. const

  • const关键字用于定义只读的变量,其值在编译时不能被改变,注意,const关键字定义的是变量而不是
  • 使用 const关键字是为了在编译时防止变量的值被误修改,同时提高程序的安全性可靠性,一般放在头文件中或者文件的开始部分
  • const关键字定义的变量是全局变量
  • const 关键字与#definc关键字存在区别,#define关键字只是简单的文本替换,而const关键字定义的变量是存储在静态存储器中的 。
  • 使用**#define**关键字定义常量的形式为
#define PI 3.14159  
/*使用该方式定义后,无论在何处使用PI,都会被预处理器以3.14159替代,
编译器不对PI进行类型检查,若使用不慎,则很可能由预处理引入错误,
且这类错误很难发现。*/

用const声明变量的方式虽然增加了分配空间,但可以很好地消除预处理引入的错误,并提供了良好的类型检查形式,保证安全性。

  • 利用 const关键字进行编程时需要注意以下三点 :

    • 使用const关键字声明的变量,只能读取,不能被赋值。 如:
    const uint8t sum = 3.14;
    uint8_t abs=0;
     
    ...
    sum= abs; //非法,将导致编译错误,因为sum 只能被读取,不能赋值
    abs- sum: //合法
    
    • const关键词修饰的变量在声明时必须初始化,上述语句表示 sum值是3.14,且sum值在编译时不能修改,若在编译过程中直接修改sum值,则编译器会提示出错。
    • 函数的形参声明为const,则意味着所传递的指针指向的内容只能读,不能被修改。如C语言的标准函数库中用于统计字符串长度的函数 int strlen(const char*str)。

2.static关键字

static关键字可以用来修饰变量,使用static关键字修饰的变量,称为静态变量。

  • 静态变量的存储方式与全局变量一样,都是静态存储方式

  • 全局变量的作用范围是整个源程序,当一个源程序由多个源文件组成时,全局变量在各个源文件中都是有效的

  • 即一个全局变量定义在某个源文件中,若想在另一个源文件中使用该全局变量,则只需要在该源文件中通过 extern关键字声明该全局变量就可以使用了

  • 若在该全局变量前加上关键字static,则该全局变量被定义成一个静态全局变量,其作用范围只在定义该变量的源文件内有效,其他源文件不能引用该全局变量,这样就避免了在其他源文件中因引用相同名字的变量而引发的错误,有利于模块化程序设计。

    • static关键字不仅可以用来修饰变量,而且可以用来修饰函数。模块化程序设计中,若用static声明一个函数,则该函数只能被该模块内的其他函数调用
      #include "stm32f1xx_hal .h”
      static void DMA_SetConfig (DMA_HandleTypeDef *hdma,uint32_t SrcAddress,uint32_t DstAddress, uint32_t DataLength);
...
      HAL_statusTypeDef HAL_DMA_start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
      HAL_StatusTypeDef status- HAL_OK;.... ...
      if(HAL_DMA_STATE_REA.DY m- hdma->state)
  {
        DMA_Setconfig(hdma, SrcAddress, DstAddress, DataLength);
       ... ...
  }
      ... ...
}

/*上述代码为DMA模块的源文件stm32f1xx_hal_dma.c,
若利用static将DMA_SetConfig()函数声明为一个静态函数,
则 DMA_SetConfig)函数只能被stm32flxx_hal_dma.c中的其他函数调用,
而不能被其他模块的文件使用,即定义了一个本地函数,
有效避免了因其他模块的文件定义了同名函数而引发的错误,
充分体现了程序的模块化设计思想*/
    • static除了用于定义静态全局变量,还用于定义静态局部变量,保证静态局部变量在调用过程中不被重新初始化。典型应用案例有实现计数统计功能。
void fun_count()
{
      static count_num=0;
      //声明一个静态局部变量,count_num用作计数器,初值为0
      count_num++;
      printf("%d\n",count_num) :
}
int main(void)
(
     int i=0;
     for( i=0;i<=5;i++)
  {
     fun_count();
  }
     return 0;
}
    
/*在main函数中每调用一次 fun_count()函数,静态局部变量count_num加1,
而不是每次都被初始化为初值0。*/

3.volatile关键字

volatile关键字,它是一个类型修饰符,含义为“易变的”

volatile char i;
/*使用volatile关键字定义了一个字符型的变量i,指出i是随时可能发生变化的,
每次使用该变量时都必须从i的地址中读取*/
  • 由于内存的读/写速度远不及CPU中寄存器的读/写速度
  • 为了提高数据信息的存取速度
    • 一方面在硬件上引入高速缓存Cache
    • 另一方面在软件上使用编译器对程序进行优化 – 将变量的值提前从内存读取到CPU的寄存器中,以后用到该变量时,直接从速度较快的寄存器中读取
  • 这样有利于提高运算速度,但同时也可能存在风险:
    • 如该变量在内存中的值有可能被程序的其他部分(如其他线程)修改或覆盖
    • 而寄存器中存放的仍是之前的值,这就导致应用程序读取的值和实际变量值不一致
    • 也有可能是寄存器中的值发生了改变,而内存中该变量的值没有被修改,同样也会导致不一致的情况发生
  • 为防止由于编译器对程序进行优化导致读取错误数据,使用 volatile关键词进行定义
  • 使用volatile关键字就是不让编译器进行优化,即每次读取或者修改值时,都必须重新从内存中读取或者修改,而不是使用保存在寄存器的备份。
  • 使用 volatile关键字定义变量后,该变量就不会因外因而发生变化了 :
    • 中断服务程序中修改的、供其他程序检测的变量需要使用volatile关键字
    • 多任务环境下各任务间共享的标志应添加 volatile关键字
    • 外设寄存器地址映射的硬件寄存器通常要用volatile关键字进行声明

4.extern关键字

extern关键字用于指明此函数或变量定义在其他文件中,提示编译器遇到此函数或变量时到其他模块中寻找其定义

extern关键字声明的函数或变量就可以在本模块或其他模块中使用,因此,使用extern关键字是一个声明而不是重新定义

extern int a;
/*第一条语句仅仅是变量a的声明,而不是定义变量a,并未为a分配内存空间,
变量a作为全局变量只能被定义一次*/
extern int  funA( ):
/*第二条语句声明函数funA(),此函数已在其他文件中定义*/

下期预告

今天简单介绍了嵌入式开发的几个方向和几个常见的关键字介绍,其实很多知识都是我从别的博主中的博客中看到的,然后进行一个搬运总结,下期继续回顾结构体等C语言常用类型

万事开头难,所有的领域在学习的初期都是一个从无到有的过程,独自探索这个过程无疑是非常枯燥且痛苦的,没有结果产出的喜悦,也没有醍醐灌顶的振奋。
慢慢来吧,先搞起来再说,希望在这个领域,能遇到许多不以山海为远的相知者,一起交流
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/181500.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

cefsharp119.4.30(cef119.4.3Chromium119.0.6045.159)版本升级体验支持x86_h264及其他多个h264版本

Cefsharp119.4.30,cef119.4.3,Chromium119.0.6045.159 此更新包括一个高优先级安全更新 This update includes a high priority security update. 说明:此版本119.4.3支持x86_H264视频播放(需要联系我),其他版本。.NETFramework 4.6.2 NuGet Gallery | CefSharp.WinForms …

接口自动化测试难点:数据库验证解决方案!

接口自动化中的数据库验证&#xff1a;确保数据的一致性和准确性 接口自动化测试是现代软件开发中不可或缺的一环&#xff0c;而数据库验证则是确保接口返回数据与数据库中的数据一致性的重要步骤。本文将介绍接口自动化中的数据库验证的原理、步骤以及示例代码&#xff0c;帮…

数据结构与算法编程题16

已知长度为n的线性表A&#xff0c;请写一时间复杂度为O(n)、空间复杂度为O(1)的算法&#xff0c;该算法删除线性表中所有值为item的数据元素。 item 3 数组下标 i 0 1 2 3 4 5 6 7 8 顺序表&#xff1a; 1 2 3 4 3 3 5 3 7 #include <iostream> using namespace std;typ…

hive return code 40000 from org.apache.hadoop.hive.ql.exec.MoveTask解决思路

参考学习 https://github.com/apache/hive/blob/2b57dd27ad61e552f93817ac69313066af6562d9/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java#L47 为啥学习error code 开发过程中遇到以下错误&#xff0c;大家觉得应该怎么办&#xff1f;从哪方面入手呢&#xff1f; 1.百…

在Linux上搭建JavaWeb项目运行环境

文章目录 安装JDK安装Tomcat安装数据库 安装JDK 安装Oracle官方的JDK比较麻烦&#xff0c;我们在此处选择安装开源社区维护的openjdk。他们俩的差别不大且兼容。 安装Tomcat 我们把本地下载好的 tomcat.zip 包拖到Linux页面上&#xff0c;让Linux也有一个zip包&#xff0c;再…

建设数字工厂管理系统对企业来说有哪些优势

随着科技的飞速发展&#xff0c;数字化转型已成为企业持续发展的必由之路。在这一背景下&#xff0c;建设数字工厂管理系统显得尤为重要。本文将详细分析数字工厂管理系统给企业带来的优势&#xff0c;以及企业如何选择合适的管理系统和成功实施数字化转型。 一、数字工厂管理系…

智能导视电子指路牌是什么?

SVIP-3800系列智能电子指路牌也称智慧指路灯杆&#xff0c;智能指路牌&#xff0c;导航立柱&#xff0c;多功能指示牌&#xff0c;多功能路标&#xff0c;智能指路机器人&#xff0c;智能导视指路牌&#xff0c;问路导航机器人&#xff0c;智能路牌&#xff0c;叁仟智慧路牌、智…

工作五年,我为什么要转行学网络安全技术

在一个工作岗位上持续工作了5年&#xff0c;一般来说&#xff0c;可以算是一位资深的专业人士了。 先从发展的角度来看&#xff1a;一个方向是向上发展&#xff0c;逐步晋升至管理岗位&#xff1b;另一个方向是向专业线发展&#xff0c;成为专家角色。 针对这两个方向&#x…

主流的低代码平台有哪些?程序员应该如何与低代码相处?

本文主要阐述低代码的概念&#xff0c;介绍目前主流的低代码平台&#xff0c;总结低代码平台的典型特征、存在优势以及未来发展趋势。并站在程序员的角度&#xff0c;分析如何在已经到来的低代码战争中&#xff0c;找到自己的定位&#xff0c;一展所长。 什么是低代码&#xff…

leetcode刷题日志-167.两数之和II-输入有序数组

给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index2 < numbers.…

高端猫罐头有哪些?精选的5款优质的猫罐头推荐!

很多铲屎官看猫猫吃猫粮吃腻了&#xff0c;或者猫猫平时不喜欢喝水&#xff0c;又或者看猫猫太瘦了就想入手几款猫罐头但是又愁于不会选择&#xff0c;而且现在猫罐头风这么大不知道选什么好~ 作为一个开宠物店7年的店长&#xff0c;对于猫咪的饮食健康我一直都很重视&#xff…

jquery实现:多个输入框字数统计示例

一、实现效果&#xff1a; 二、代码实现&#xff1a; 每个输入框添加了相同的类名 inputField 并且每个输入框旁边的字数统计使用相同的类名 charCount。 然后使用 jQuery 的类选择器 $(‘.inputField’) 来选中所有具有该类名的输入框&#xff0c;并为它们绑定了 input 事件。…

玻色量子“揭秘”之多项式回归问题与QUBO建模

摘要&#xff1a;多项式回归&#xff08;Polynomial Regression&#xff09;是一种回归分析方法&#xff0c;通过拟合一个多项式方程来模拟自变量与因变量之间的非线性关系。多项式回归的目标是找到一组多项式系数&#xff0c;使得拟合曲线尽可能地接近数据点。这种方法可以用于…

Python编写的爬虫为什么受欢迎?

每每回想起我当初学习python爬虫的经历&#xff0c;当初遇到的各种困难险阻至今都历历在目。即便当初道阻且长&#xff0c;穷且益坚&#xff0c;我也从来没有想过要放弃。今天我将以我个人经历&#xff0c;和大家聊一聊有关Python语音编写的爬虫的事情。谈一谈为什么最近几年py…

面试送分题!“商品分类浏览”如何测试?

电商项目无论是工作中&#xff0c;还是面试中&#xff0c;都是一个高频出现的词。 面试官非常热衷提问关于电商项目的问题。例如商品分类怎么测试&#xff1f;购物车怎么测试&#xff1f;订单怎么测试&#xff1f;优惠券怎么测试&#xff1f;支付怎么测试&#xff1f;等等。 …

每天学习一点点之 Tomcat 是如何清除过期 Session 的

今天使用一种很临时的方案解决 Session 泄漏的问题&#xff1a;缩短 Session 的过期时间。这种方法虽然简单&#xff0c;但却非常有效。然而&#xff0c;这引发了一个问题&#xff1a;我们应该将过期时间设置为多短呢&#xff1f;在 Spring Boot 中&#xff0c;最短的过期时间是…

修改Docker默认镜像和容器存储位置(超详细!!!)

Ubuntu20.04 修改Docker默认镜像和容器存储位置 Docker 默认安装的情况下&#xff0c;会使用 /var/lib/docker/ 目录作为存储目录&#xff0c;用以存放拉取的镜像和创建的容器等。不过由于此目录一般都位于系统盘&#xff0c;遇到系统盘比较小&#xff0c;而镜像和容器多了后就…

母婴团队半年破亿秘诀揭秘,合规经营成就辉煌

这支母婴产品销售团队在短短半年内实现了过亿的销售额&#xff0c;这是一个令人瞩目的成就。他们既不依赖线下门店&#xff0c;也不是传统的电商平台&#xff0c;那么他们是如何做到这一点的呢&#xff1f; 这个团队从16年10月开始经营母婴产品&#xff0c;如今已经过去了6年时…

【JavaEE】Spring小练习——存储和获取对象

一、题目&#xff1a; 在 Spring 项目中&#xff0c;通过 main 方法获取到 Controller 类&#xff0c;调用 Controller 里面通过注入的方式调用Service 类&#xff0c;Service 再通过注入的方式获取到 Repository 类&#xff0c;Repository 类里面有一个方法构建⼀个 User 对象…

unordered_map 与 unordered_set 的使用

unordered_map unordered_map 的介绍文档 unordered_map 的介绍文档&#xff1a;来自cpluscplus.com 的中文翻译 unordered_map是存储<key, value>键值对的关联式容器&#xff0c;其允许通过keys快速的索引到与 其对应的value。在unordered_map中&#xff0c;键值通常用…