嵌入式C语言(入门必看)

这篇具有很好参考价值的文章主要介绍了嵌入式C语言(入门必看)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

     

目录

STM32的数据类型

const关键字

static 关键字

volatile关键字

extern关键字

 struct结构体

enum

 typedef

#define

回调函数

#ifdef 、#ifndef、#else  、#if    


嵌入式开发中既有底层硬件的开发又涉及上层应用的开发,即涉及系统的硬件和软件,C语言既具有汇编语言操作底层的优势,又具有高级语言功能性强的特点,当之无愧地成为嵌入式开发的主流语言。在 STM32开发过程中,不论是基于寄存器开发还是基于库开发,深入理解和掌握嵌入式C语言的函数、指针、结构体是学习STM32的关键。
嵌入式C语言的结构特点如下。
(1)程序总是从main函数开始执行,语句以分号“;”结束,采用/*…*/或//做注释。

(2)函数是C语言的基本结构,每个C语言程序均由一个或多个功能函数组成。

(3) 函数由两部分组成:说明部分和函数体。
 

  函数名(参数)
  {
      [说明部分];
      函数体;
  }

(4)一个C语言程序包含若干个源程序文件(.c文件)和头文件(.h文件),其中.h头文件主要由预处理命令(包括文件、宏定义、条件编译等)和数据声明(全局变量、函数等声明)组成;c源文件主要是功能函数的实现文件。
(5)采用外设功能模块化设计方法,一个外设功能模块包括一个源文件(.c文件)和一个头文件(.h文件),.c文件用于具体外设功能模块函数的实现,.h头文件用于对该外设功能模块参数及功能函数的声明。
      嵌入式系统开发多采用模块化、层次化的设计思想,系统层次架构清晰,便于协同开发。图1为嵌入式系统的软件基本结构框图。
嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

                            图1 嵌入式系统的软件基本结构框架图

STM32的数据类型


数据是嵌入式C语言的基本操作对象,数据类型是指数据在计算机内存中的存储方式,如基本数据类型中的整型(存放整数)、浮点型(存放实数)、字符型(存放字符)、指针(存放地址)以及派生出的复合数据类型(如数组、结构体、共用体、枚举类型)。嵌入式C语言的数据类型如图2所示。

嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

                                                     图二 嵌入式C语言的数据类型

      由于不同CPU定义的数据类型的长度不同,因此ARM公司联合其他半导体厂商制定了统一的CMSIS 软件标准,这个标准中预先定义了相关的数据类型,ST公司也为开发人员提供了基于C语言的标准外设库,其定义的数据类型如表1所示,相关源代码请参考STM32标准外设库v3.5.0的stdint.h头文件。
      stm32f10x.h头文件还对标准外设库之前版本所使用的数据类型进行了说明,v3.5.0版本已不再使用这些旧的数据类型,为了兼容以前的版本,新版本对其进行了兼容说明,如图3所示。

                                                  表1   STM32定义的数据类型
 

嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

                                 图3  STM32标准外设库数据类型兼容说明

图3中的_I、_O以及_IO为IO类型限定词,内核头文件 core_cm3.h定义了标准外设库所使用的IO类型限定词,如表2所示。注意,IO类型限定词加下画线是为了避免命名冲突。
表1的数据类型与表2中的IO类型限定词相结合,在标准外设库中常用来定义寄存器和结构体变量,图4为stm32f10x.h头文件中相关外设的寄存器定义。

                                                表2   STM32的IO类型限定词

嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

                                              图4 stm32f10x.h头文件中相关外设的寄存器定义

       结合表2和图3,可以看出同一数据类型有多种表示方式,如无符号8位整型数据有unsigned char、uint8_t、u8三种表示方式,在不同的ST标准外设库版本中这三种表示方式都可以表示无符号8位整型数据,初学者应了解这三种表达方式,最新的v3.5.0版本采用 CMSIS软件标准的C99标准,即 uint8_t方式。

const关键字

      const关键字用于定义只读的变量,其值在编译时不能被改变,注意,const关键字定义的是变量而不是常量。
      使用 const关键字是为了在编译时防止变量的值被误修改,同时提高程序的安全性和可靠性,一般放在头文件中或者文件的开始部分。
      在C99标准中,const关键字定义的变量是全局变量。const 关键字与#definc关键字存在区别,#define关键字只是简单的文本替换,而const关键字定义的变量是存储在静态存储器中的。使用#define关键字定义常量的形式为

#define PI3.14159


      使用该方式定义后,无论在何处使用PI,都会被预处理器以3.14159替代,编译器不对PI进行类型检查,若使用不慎,则很可能由预处理引入错误,且这类错误很难发现。用const声明变量的方式虽然增加了分配空间,但可以很好地消除预处理引入的错误,并提供了良好的类型检查形式,保证安全性。
利用 const关键字进行编程时需要注意以下三点。
(1)使用const关键字声明的变量,只能读取,不能被赋值。如:

const uint8t sum = 3.14;
uint8_t abs=0;

...
sum= abs;//非法,将导致编译错误,因为sum 只能被读取,不能赋值
abs- sum: //合法


(2) const关键词修饰的变量在声明时必须初始化,上述语句表示 sum值是3.14,且sum值在编译时不能修改,若在编译过程中直接修改sum值,则编译器会提示出错。
(3)函数的形参声明为const,则意味着所传递的指针指向的内容只能读,不能被修改。如C语言的标准函数库中用于统计字符串长度的函数 int strlen(const char*str)。

static 关键字

      在嵌入式C语言中,static关键字可以用来修饰变量,使用static关键字修饰的变量,称为静态变量。
      静态变量的存储方式与全局变量一样,都是静态存储方式。全局变量的作用范围是整个源程序,当一个源程序由多个源文件组成时,全局变量在各个源文件中都是有效的,即一个全局变量定义在某个源文件中,若想在另一个源文件中使用该全局变量,则只需要在该源文件中通过 extern关键字声明该全局变量就可以使用了。若在该全局变量前加上关键字static,则该全局变量被定义成一个静态全局变量,其作用范围只在定义该变量的源文件内有效,其他源文件不能引用该全局变量,这样就避免了在其他源文件中因引用相同名字的变量而引发的错误,有利于模块化程序设计。
      利用static关键字进行编程时需要注意以下要点。
      (1)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中的其他函数调用,而不能被其他模块的文件使用,即定义了一个本地函数,有效避免了因其他模块的文件定义了同名函数而引发的错误,充分体现了程序的模块化设计思想。
(2) 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。

volatile关键字


      嵌入式开发中,常用到volatile关键字,它是一个类型修饰符,含义为“易变的”。使用方式如下:

volatile char i;


      这里使用volatile关键字定义了一个字符型的变量i,指出i是随时可能发生变化的,每次使用该变量时都必须从i的地址中读取。
      由于内存的读/写速度远不及CPU中寄存器的读/写速度,为了提高数据信息的存取速度,一方面在硬件上引入高速缓存Cache,另一方面在软件上使用编译器对程序进行优化,将变量的值提前从内存读取到CPU的寄存器中,以后用到该变量时,直接从速度较快的寄存器中读取,这样有利于提高运算速度,但同时也可能存在风险,如该变量在内存中的值有可能被程序的其他部分(如其他线程)修改或覆盖,而寄存器中存放的仍是之前的值,这就导致应用程序读取的值和实际变量值不一致;也有可能是寄存器中的值发生了改变,而内存中该变量的值没有被修改,同样也会导致不一致的情况发生。因此,为防止由于编译器对程序进行优化导致读取错误数据,使用 volatile关键词进行定义。
      简单地说,使用volatile关键字就是不让编译器进行优化,即每次读取或者修改值时,都必须重新从内存中读取或者修改,而不是使用保存在寄存器的备份。
      举个简单的例子:大学里的奖/助学金的发放一般都是直接转给学校,学校再发给每名学生,学校财务处都登记了每名学生的银行卡号,但不可避免地会有一些学生因各种原因丢失银行卡或不再使用这张银行卡,而没来得及去财务处重新登记,从而影响奖/助学金的发放,这里,学生就是变量的原始地址,而财务处的银行卡号就是变量在寄存器中的备份,使用 volatile关键字来定义学生这个变量,这样每次发放奖/助学金时都去找学生这个变量的原始地址,而不是直接转到财务处保存的银行卡上,进而避免错误的发生。
       const关键字的含义为“只读”,volatile关键字的含义为“易变的”,但volatile关键字解释为“直接存取原始内存地址”更为合适,使用 volatile关键字定义变量后,该变量就不会因外因而发生变化了。一般来说,volatile 关键字常用在以下场合。
     (1)中断服务程序中修改的、供其他程序检测的变量需要使用volatile关键字。

     (2)多任务环境下各任务间共享的标志应添加 volatile关键字。

  (3)外设寄存器地址映射的硬件寄存器通常要用volatile关键字进行声明。

extern关键字


       extern关键字用于指明此函数或变量定义在其他文件中,提示编译器遇到此函数或变量时到其他模块中寻找其定义。这样,extern关键字声明的函数或变量就可以在本模块或其他模块中使用,因此,使用extern关键字是一个声明而不是重新定义。使用方法如下:

extern int a;
extern int  funA( ):


      解析:第一条语句仅仅是变量a的声明,而不是定义变量a,并未为a分配内存空间,变量a作为全局变量只能被定义一次。第二条语句声明函数funA(),此函数已在其他文件中定义。
       STM32中,extern关键字还有一个重要作用,即与"C一起连用,即 extern "c",进行链接指定。例如,stm32f10x.h头文件中有如下代码。

#ifndef _STM32F10× H
#define _STM32F10x_H
#ifdef .epluspius
extern "C"{
#endif
...
#ifdef _eplusplus
}
"endif

       这段代码的含义是,若没有定义_STM32F10x_H,则定义_STM32F10x H,若已经定义_cplusplus,则执行 extern "C"中语句,extern "C"是告诉C++编译器括号中的程序代码是按照C语言的文件格式进行编译的,_cplusplus是C++编译器中自定义的宏,plus是“+”的意思。
C+H+支持函数重载,即在编译时会将函数名与参数联合起来生成一个新的中间函数名称,而C语言不支持函数重载,这就导致在C++环境下使用C函数会出现链接时找不到对应函数的情况,这时就需要使用extern "C"进行链接指定,告知编译器此时采用的是C语言定义的函数,需要使用C语言 的命名规则来处理函数,不要生成用于链接的中间函数名。
       一般将函数声明存放在头文件中,当函数有可能被C语言或C+使用时,将函数声明存放在 extern "C"中以免出现编译错误,完整的使用方法如下:
 

#ifdef__cplusplus
   extern "C"{
    #endif
   //函数声明
    #ifdef_Cplusplus
     }
#endif

       STM32中很多头文件都采用这样的用法,如标准外设库中的 stm32f1 0x_adc.h ,stm32f10x can.h、 stm32f1Ox_gpio.h 等。
      利用extern 关键字进行编程时需要注意以下要点。
      嵌入式开发一般采用模块化设计思想,因此,为保证全局变量和功能函数的使用,extern关键字一般用在.h头文件中对某个模块提供给其他模块调用的外部函数及变量进行声明,实际编程中只需要将该.h头文件包含进该模块对应的.c文件中,即在该模块的.c文件中加入代码#include "xxx.h”。实例如下:
嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

 struct结构体

      struct用于定义结构体类型,其作用是将不同数据类型的数据组合在一起,构造出一个新的数据类型。struct一般用法如下:

 struct  结构体名
	{
	 数据类型   成员名1;
	 数据类型   成员名2;
	 数据类型   成员名n;
	 };
struct Student{         //声明结构体
    char name[20];      //姓名
    int num;            //学号
    float score;        //成绩
};

enum

       有时一个变量会有几种可能的取值,如一个星期有7天、每学期开设的课程、12种不同的颜色(红、橙、黄、绿、青、蓝、紫、灰、粉、黑、白、棕)等,C语言提供了一种enum枚举类型,用来将变量或对象的所有可能的值一一列出,变量取值只限于列举出来的值。enum枚举类型的用法如下:
 

enum枚举名
{
枚举成员1,
枚举成员2,
...
枚举成员n;
}枚举变量;

      enum枚举类型是一个集合,将所有可能的取值用花括号括住,花括号中的各枚举成员之间用逗号隔开,最后一个枚举成员后省略逗号。enum枚举类型以分号结束,这里的枚举变量可以省略,在后面需要时再根据枚举名进行定义。
例如,利用enum枚举类型列举几种常见的颜色。
 

enum Color
{
RED,
GREEN,
BLACK,
YELLOw
};

      上述名为 Color的枚举类型只有4个成员:RED、GREEN、BLACK、YELLOW,即意味着Color类型变量的取值只能取这4种颜色中的某一种颜色。
      例如,利用enum定义一个 Weekdays枚举类型名,包括7个枚举成员:从星期一到星期日,并定义枚举变量 Mydays 与 Olddays.

enumweekdays
{
Monday=1,
Tuesday,
wednesday,
Thursday,
Friday,
Saturday,
sunday
}Mydays.olddays;

      注意:enum枚举类型具有自动编号功能,第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员值上自动加1,也可以自定义枚举成员的值,若把第一个枚举成员的值定义为1,则第二枚举成员的值就为2,依此类推,如上述例子中 Friday 的值为5。因此,enum枚举类型中的枚举成员的值是常量而不是变量,不能在程序中用赋值语句再对它赋值,但可以将枚举值赋给枚举变量。
例如,以下两条语句是正确的。

Mydays=Thursday;
olddays=Friday;


      但以下两条语句是错误的。

Tuesday=o;
Mydays=1;

 typedef

      typedef用于为复杂的声明定义一个简单的别名,它不是一个真正意义上的新类型。在编程中使用 typedef的目的一般有两个:①为变量起一个容易记忆且意义明确的新名称;②简化一些比较复杂的类型声明。其基本格式如下:
typedef类型名自定义的别名;
例如:

typedef signed char int8_t;//为数据类型signed char起别名int8_t
typedef signed int int32_t;//为数据类型signed int起别名int32_t


      STM32开发中,typedef主要有以下三种用法。
      1. typedef的基本应用
      为已知的数据类型起一个简单的别名,如上例。
      2. typedef 与结构体struct结合使用
      该用法用于自定义数据类型。如 stm32f10x_gpio.h头文件中的GPIO初始化结构体GPIO_InitTypeDef。

typedef struct
{
   uint16_t GPIO_ Pin;
   GPIOSpeed_TypeDef GPIO_Speed;
   GPIOMode TypeDef GPIO_Mode;
}IGPIo_InitTypeDef;


       上述语句利用 struct创建了一个新的结构体,这个新结构体有三个成员 GPIO_Pin、GPIO_Speed和 GPIO_Mode,同时又使用 typedef为这个新建的结构体定义一个新的名称GPIO_InitTypeDef,在应用时就可以直接使用GPIO_InitTypeDef 来定义变量。例如:

GPIO_InitTypeDef GPIO_ InitStrueture;


       上述语句利用 GPIO_InitTypeDef结构体定义了一个变量GPIO_InitStructure,引用三个成员的方法如下:

GPIO InitStructure.GPIO_Pin;
GPIO_InitStructure.GPIO_Speed;
GPIO InitStructure.GPIO Mode;

3. typedef 与 enum结合使用
      利用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明,STM32标准外设库v3.5.0版本中有很多enum和 typedef结合使用的应用。stm32f10x_gpio.h头文件中的代码如下。

Typedef enum
{
GPIO Speed_1OMHz=1,
GPIo_Speed_2MHz,
GPIOSpeed_50MHz;
}GPIOSpeed_TypeDef;


       该例中enum枚举类型共有三个成员:GPIO Speed_10MHz、GPIO Speed_2MHz和GPIO_Speed_50MHz,并将第一个枚举成员GPIO_Speed_10MHz赋值为1,enum枚举类型会将枚举成员的赋值在第一个枚举成员赋值的基础上加1,因此GPIO_Speed_2MHz 默认值为2,GPIO_Speed_50MHz默认值为3。同时,利用typedef关键字将此枚举类型定义一个别名GPIOSpeed TypeDef,这里省略了枚举类型的枚举名,只用 typedef为枚举类型定义一个别名。

#define

      #define是C语言的预处理命令,它用于宏定义,用来将一个标识符定义为一个字符串,该标识符称为宏名,被定义的字符串称为替换文本,采用宏定义的目的主要是方便程序编写,一般放在源文件的前面,称为预处理部分。
      所谓预处理是指在编译前所做的工作。预处理是C语言的一个重要功能,由预处理程序负责完成,程序编译时,系统将自动引用预处理程序对源程序中的预处理部分进行处理,处理完毕后自动进入对源程序的编译。
      STM32标准外设库中,#define的使用方式主要有以下两种。
1.无参数宏定义
无参数宏定义的一般形式如下:

#define<宏名>字符串>


其中,字符串可以是常数、字符串和表达式等。
       例如:#define UINT8_MAX 255
       该语句表示定义了宏名UINT8_MAX,它代表255,例如:#define_IO volatile;
       该语句表示定义宏名_IO,代表 volatile,若以后程序中再需要用到 volatile,则可以使用IO。
       例如:#define RCC AHBPeriph_DMA1 ((uint32_t)0x00000001)
       该语句表示定义RCC_AHBPeriph_DMA1宏名,代表32位的无符号数据0x00000001.

       STM32中有很多此类用法,如标准外设库 v3.5.0的 stm32f1 0x_rcc.h文件中APB2_peripheral外设基地址的定义,如图5所示。

嵌入式c语言,STM32,C语言,笔记,c语言,开发语言,stm32

                          图5  APB2_peripheral各外设基地址的定义

2.带参数的宏定义
宏定义格式如下:

#define<宏名>(参数1,参数2,…,参数n)<替换列表>

例如:

define SUM(x,y) (x+y)
…
a=SUM(2,2):


其中,a的结果是4,将 SUM(X,y)定义为x+y,预编译时会将SUM(x,y)替换为xty。
例如:

#define IsGPIO_SPEED(SPEED)(((SPEED) = GP1o_Speed_10MHz)||((SPEED)==GPIO_Speed_ 2MHz)||((SPEED)==GP10_Speed_50MHz))


使用宏定义#define 将 IS_GPIO_SPEED(SPEED)替换为 GPIO_Speed_10MHz、GPIO_Speed_2MHz或者GPIO_Speed_50MHz。
      注意:带参数的宏定义同样也只是进行简单的字符替换,替换是在编译前进行的,展开并不分配内存单元,不进行值的传递处理,因此替换不会占用运行时间,只占用编译时间,因此该方式可以提高运行效率。
       #define与 typedef的区别为:typedef是在编译阶段处理的,具有类型检查的功能,而#define是在预处理阶段处理的,即在编译前,只进行简单的字符串替换,而不进行任何检查。

回调函数

       回调函数是一个通过函数指针调用的函数。操作系统中的某些函数常需要调用用户定义的函数来实现其功能,由于与常用的用户程序调用系统函数的调用方向相反,因此将这种调用称为回调(Callback),而被系统函数调用的函数就称为回调函数。
      STM32的HAL库在stm32flxx_hal_xxx.c文件中定义了相应的回调函数,并由中断触发,其实质是中断处理程序。如 stm32flxx_hal_gpio.c代码中通过GPIO中断处理函数voidHAL _GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)调用相应的回调函数HAL_GPIO_EXTICallback(GPIO_Pin),开发人员只需要在回调函数中编写应用程序就能实现中断服务功能。

#ifdef 、#ifndef、#else  、#if    


#define            定义一个预处理宏
#undef            取消宏的义
 #if                  编译预处理中的条件命令,相当于C语法中的if语句
#ifdef              判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef            与#ifdef相反,判断某个宏是否未被定义
#elif                若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else              与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif             #if, #ifdef, #ifndef这些条件命令的结束标志.
defined          与#if, #elif配合使用,判断某个宏是否被定义

指针相关内容我这里就不在赘述了网上有很多丰富的资料。文章来源地址https://www.toymoban.com/news/detail-799330.html

到了这里,关于嵌入式C语言(入门必看)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式学习笔记——STM32的USART通信概述

    上两篇文章中,已经实现了GPIO的通用输出以及通用输出模式,从本文开始,笔者将开始有关GPIO的复用功能的介绍,首先是最常用复用功能——串口,本文主要是介绍一些关于通信以及串口的基本概念。 通信协议:通信双方进行信息交换(接收或发送)要满足的规则,而这个规

    2023年04月08日
    浏览(59)
  • 嵌入式系统开发笔记104:在STM32CubeIDE中导入工程

      本文讲述如何在STM32CubeIDE中导入现有工程。

    2024年02月16日
    浏览(57)
  • 嵌入式学习笔记——STM32的USART收发字符串及串口中断

    上一篇中,介绍了串口收发相关的寄存器,通过代码实现了一个字节的收发,本文接着上面的内容,通过功能函数实现字符串的收发,然后引入中断解决收发过程中while()死等的问题。 根据昨天的字符发送函数,只需要稍作修改即可实现发送函数了,一个字符串的结尾会有一

    2024年02月03日
    浏览(79)
  • 嵌入式学习笔记——STM32的USART相关寄存器介绍及其配置

    上一篇中,对串口做了个概述,主要是介绍了串口通信的特征,异步串行全双工通信,然后就是结合串口的框图梳理了一下STM32中USART的配置流程以及发送接收数据的流程,本文将接着上篇的内容,对串口的寄存器做个介绍,然后实现一个简单的收发实验。 根据之前GPIO的经验

    2024年02月05日
    浏览(58)
  • 蓝桥杯嵌入式CT117E-M4学习笔记02-STM32G431RBT6芯片学习

    首先学习了解一下蓝桥杯嵌入式CT117E-M4开发板的主控芯片STM32G431RBT6,本文仅为个人学习成果总结,如有错误,恳请指正。 上图为STM32CubeMX选型界面,如图可以看出STM32G431RBT6具有以下特点和硬件集成。 采用Cortex-M4 32位RISC核心架构,工作频率最高可达170Mhz。 128kBytes的FLASH,32

    2023年04月09日
    浏览(63)
  • C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)

    参考: 麦子学院-嵌入式C语言高级-内存空间 内存类型资源地址、门牌号的代名词 指针:地址的代名词 指针变量:存放指针这个概念的盒子 *P char *p *p; C语言娟译器对指针这个特殊的概念,有2个疑问? 1、分配一个盒子,盒子要多大? 在32bit系统中,指针就4个字节 2、盘子里存放

    2023年04月22日
    浏览(70)
  • stm32嵌入式实验考核

    STM32 实验考核题目 1. 利用 STM32 小板实现:控制外接 LED 灯每隔 3 秒钟亮暗变换,同 时在 PC 机上显示 MCU 的计时时间,MCU 的初始时间由 PC 机 方设置。 2. 利用 STM32 小板实现:利用导线外接 GPIO 口模拟 2 个按键输入, 根据输入组合的四种情况,分别控制三色灯四种流水灯效果

    2024年02月03日
    浏览(53)
  • 嵌入式 STM32 通讯协议--MODBUS

    目录 一、自定义通信协议 1、协议介绍 2、网络协议 3、自定义的通信协议  二、MODBUS通信协议 1、概述 2、MODBUS帧结构  协议描述 3、MODBUS数据模型   4、MODBUS事务处理的定义 5、MODBUS功能码  6、功能码定义   7、MODBUS数据链路层 8、MODBUS地址规则  9、MODBUS帧描述 10、MODBUS两种

    2024年02月11日
    浏览(66)
  • STM32的时钟系统(嵌入式学习)

    时钟是指用于计量和同步时间的装置或系统。时钟是嵌入式系统的脉搏,处理器内核在时钟驱动下完成指令执行,状态变换等动作,外设部件在时钟的驱动下完成各种工作,例如:串口数据的发送、AD转换、定时器计数等。因此时钟对于计算机系统是至关重要的,通常时钟系

    2024年02月16日
    浏览(50)
  • 嵌入式——新建STM32工程(标准库)

    目录 一、初识标准库 1.CMSIS标准及库层级关系 2.库文件介绍 (1)Libraries文件夹 ①CMSIS文件夹 ②STM32F10x_Std_Periph_Driver文件夹 ③ 在用库建立一个完整的工程时,还需要添加stm32f10x_it.c、 stm32f10x_conf.h 和 system_stm32f10x.c文件 (2)Project文件夹 (3)Utilities文件夹 3.库各文件之间的关

    2024年01月23日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包