关于嵌入式开发的C语言基础总结

2023-05-16

一、位操作

    C语言支持的6种位操作符如下:

1. 不改变其他位的值的状况下,对某几个位进行设值。

        方法:先对需要设置的位用&操作符(对应位&0)进行清零操作,然后用|操作符设值(对应位|你想要设定的值)。

举例:改变 GPIOA-> BSRRL 的状态  

GPIOA-> BSRRL &=0XFF0F;  //将第 4-7 位清 0
GPIOA-> BSRRL |=0X0040; //设置相应位的值,不改变其他位的值

2.  移位操作提高代码的可读性

         位操作在单片机开发中也非常重要,我们来看看下面一行代码

    GPIOx->ODR |= (((uint32_t)0x01) << pinpos);

这个操作就是将 ODR 寄存器的第 pinpos 位设置为 1,为什么要通过左移而不是直接设置一个固定的值呢?

其实,这是为了提高代码的可读性以及可重用性。这行代码可以很直观明了的知道,是将第 pinpos 位设置为 1。

如果你写成GPIOx->ODR =0x0040; 这样的代码就不好看也不好重用了。

3. ~取反操作使用技巧

 

        SR 寄存器的每一位都代表一个状态,某个时刻我们希望去设置某一位的值为 0,同时其他位都保留为 1,

简单的作法是直接给寄存器设置一个值:

        TIMx->SR=0xFFF7;

        这样的作法设置第 3 位为 0,但是这样的作法同样不好看,并且可读性很差。看看库函数

代码中怎样使用的:

        TIMx->SR &= (uint16_t)~TIM_FLAG;

        而 TIM_FLAG 是通过宏定义定义的值:

    #define TIM_FLAG  ((uint16_t)0x0001)

        看这个应该很容易明白,可以直接从宏定义中看出 TIM_FLAG_ 就是设置的第 0位了,可读性非常强。

 

二、 define 宏定义

        define 是 C 语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供

方便。常见的格式:

    #define  标识符  字符串

“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。例如:
    #define  PLL_M  8

    定义标识符 PLL_M 的值为 8。至于 define 宏定义的其他一些知识,比如宏定义带参数这里我们就不多讲解。

三、 ifdef 条件编译

        单片机程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而
当条件不满足时则编译另一组语句。条件编译命令最常见的形式为:
            #ifdef   标识符
                程序段 1
            #else
                程序段 2
            #endif
它的作用是:当标识符已经被定义过(一般是用#define 命令定义),则对程序段 1 进行编译,
否则编译程序段 2。 其中#else 部分也可以没有,即:
            #ifdef
                程序段 1
            #endif

这个条件编译在MDK里面是用得很多的,在stm32f4xx.h这个头文件中经常会看到这样的语句:
            #if  defined   (STM32F40_41xxx)
                    STM32F40x 系列和 STM32F41x 系列芯片需要的一些变量定义
            #end

而STM32F40_41xxx 则是我们通过 #define 来定义的。

        条件编译经常在头文件中使用,是为了防止一些.c文件重复包含头文件,导致重复编译出错。

具体看我的另外一篇博客点击打开链接。

四、 extern  变量申明

         C 语言中 extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编

 

译器遇到此变量和函数时在其他模块中寻找其定义。 这里面要注意,对于 extern 声明变量可以多

次,但定义只有一次。在我们的代码中你会看到看到这样的语句:

          extern u16 USART_RX_STA;

      这个语句是申明 USART_RX_STA 变量在其他文件中已经定义了,在这里要使用到。所以,你肯定

可以找到在某个地方有变量定义的语句:

          u16 USART_RX_STA;

        对于函数也是同样的应用。

五、typedef  类型别名

        typedef 用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。
typedef 在 MDK 用得最多的就是定义结构体的类型别名和枚举类型了。
 
struct _GPIO
{
__IO uint32_t MODER;
__IO uint32_t OTYPER;
…
}

上面定义了一个结构体 GPIO,这样我们定义变量的方式为:

        struct _GPIO GPIOA;//定义结构体变量 GPIOA

但是这样很繁琐,MDK 中有很多这样的结构体变量需要定义。这里我们可以为结体定义一个别
名 GPIO_TypeDef,这样我们就可以在其他地方通过别名 GPIO_TypeDef 来定义结构体变量了。

方法如下:

typedef struct
{
__IO uint32_t MODER;
__IO uint32_t OTYPER;
…
} GPIO_TypeDef

Typedef 为结构体定义一个别名 GPIO_TypeDef,这样我们可以通过 GPIO_TypeDef 来定义结构体
变量:
        GPIO_TypeDef _GPIOA,_GPIOB;

这里的 GPIO_TypeDef 就跟 struct _GPIO 是等同的作用了。

        当然typedef在程序代码可移植性上也有很大的帮助。比如在一些头文件中使用typedef如下:

typedef   signed          char int8_t;
typedef   signed short     int int16_t;
typedef   signed           int int32_t;
typedef   signed       __INT64 int64_t;

 

六、结构体

 

声明结构体类型:

            Struct 结构体名{
             成员列表;
            }变量名列表;
例如:
            Struct U_TYPE {
            Int BaudRate
            Int WordLength;
            }usart1,usart2;

在结构体申明的时候可以定义变量,也可以申明之后定义,方法是:

    Struct 结构体名字 结构体变量列表 ;

    例如:struct U_TYPE usart1,usart2;

    结构体成员变量的引用方法是:

    结构体变量名字.成员名

    比如要引用 usart1 的成员 BaudRate,方法是:usart1.BaudRate;

 

结构体指针变量定义也是一样的,跟其他变量没有啥区别。

    例如:struct U_TYPE *usart3;//定义结构体指针变量 usart1;

    结构体指针成员变量引用方法是通过“->”符号实现,比如要访问 usart3 结构体指针指向的结

构体的成员变量 BaudRate,方法是:

    Usart3->BaudRate;

使用结构体的好处是防止函数的入口参数过多,当然也利于增加变量时不用修改函数定义,对于一组描述

同一对象的参数,用结构体使他们形成一个整体,也有利于代码的可读性,不会使变量定义显得混乱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于嵌入式开发的C语言基础总结 的相关文章

  • Python 调用API接口方式,通过http.client调用api接口,远程调用flask接口方式

    一 创建接口 xff08 如果调用别人的接口 xff0c 跳过此条 xff09 如果没有api xff0c 首先自己写一个接口玩一下 xff1a 必备知识 xff1a 一个项目最基本的文件 xff0c 接口run py文件 config文件
  • git tag和branch的区别

    tag 和branch的区别 Git tag是一系列commit的中的一个点 xff0c 只能查看 xff0c 不能移动 branch是一系列串联的commit的线 git tag的用法 我们常常在代码封板时 使用git 创建一个tag 这
  • 结构体对齐计算(超详细讲解,一看就会)

    想要计算结构体大小 xff0c 咱就先要清楚结构体内存对齐的规则 xff1a 1 结构体的第一个成员直接对齐到相对于结构体变量起始位置为0处偏移 2 从第二个成员开始 xff0c 要对齐到某个 对齐数 的整数倍的偏移处 3 结构体的总大小
  • RTK差分编码

    一 概念 DCB xff08 Differential Code Bias 差分码偏差 xff09 是全球卫星导航系统 xff08 GNSS xff09 中 xff0c 通过不同信号得到的观测值之间存在的系统性偏差 DCB是由卫星和接收机硬
  • 详解JAVA的事件监听机制和观察者设计模式

    一 事件监听机制的三要素 事件源 事件监听器 xff0c 事件对象 监听器一般是JAVA接口 xff0c 用来约定可以执行的操作 二 事件监听机制简要说明 事件源注册一个或者多个事件监听器 xff0c 事件源对象状态发生变化或者被操作时 x
  • Nginx控制IP(段)的访问策略配置

    Nginx engine x 是一个高性能的HTTP和反向代理web服务器 xff0c 同时也提供了IMAP POP3 SMTP服务 有着负载均衡 动静分离等强大的功能 xff0c 而且还有众多三方插件来满足应用要求 这里重点介绍nginx
  • 敏捷开发-互联网时代的软件开发方式

    一 什么是敏捷开发 敏捷开发简单的描述为 xff1a 是一种应对需求快速变化的软件开发方式 敏捷开发的核心思想就是小步快跑 不断迭代 xff0c 在一次次的迭代升级中完成 小目标 最终完成那个 大目标 正因为敏捷开发的这种不断迭代升级的开发
  • Window系统查看端口是否启用以及占用程序

    1 打开DOS命令行窗口 开始 gt 运行 gt cmd xff0c 或者是 window 43 R gt cmd xff0c 调出命令窗口 2 查看当前正在使用的所有端口 命令 xff1a netstat ao 包括协议 xff0c 端口
  • ThreadLocal的深度解读

    一 J2SE的原始描述 This class provides thread local variables These variables differ from their normal counterparts in that eac
  • 消息中间件如何保证消息不丢失

    一 消息队列MQ的三个阶段 1 生产者发送消息到MQ 2 MQ存储消息到内存或者硬盘 3 消费者消费消息 由于网络的原因 服务器的原因 程序的原因等等 xff0c 在每个阶段都有可能引起消息的丢失 xff1a 1 生产者发送消息到MQ xf
  • 32位系统为什么最大只支持4GB运存?

    首先要明白 1B 61 2 3b 1KB 61 2 10B 1MB 61 2 20B 1GB 61 2 30B 4GB 61 2 2 2 30B 61 2 32B b表示一个比特位 xff0c B表示一个字节 xff0c 一字节等于8个比特
  • 数据库和Spring事务隔离级别

    事务隔离级别 xff0c 指的是数据库多个并发事务操作共享数据时 xff0c 共享的数据对多个并发事务之间的可见性和影响程度 隔离的内容主要指数据方面 具体举例来说就是一个事务A读操作时 xff0c 其他并发事务修改操作事务A读的数据时 x
  • Java中各种锁的详细介绍(二):悲观锁和乐观锁

    Java中锁的类型多种多样 xff0c 有简单有复杂 xff0c 适合各种不同的应用场景 xff0c 接下来会分几章给大家详细介绍java中各种类型的锁 一 悲观锁和乐观锁的说明 1 悲观锁 Pessimistic Lock xff1a 对
  • Java中各种锁的详细介绍(三):自旋锁 VS 适应性自旋锁

    一 自旋锁 在介绍自旋锁前 xff0c 需要介绍一些前提知识来帮助大家更好的明白自旋锁的概念 阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成 xff0c 这种状态转换需要耗费处理器时间 如果同步代码块中的内容过于简单 xff0c
  • Java中各种锁的详细介绍(四):无锁|偏向锁|轻量级锁|重量级锁

    无锁 偏向锁 轻量级锁和重量级锁 xff0c 都是指锁的状态 xff0c 专门针对synchronized的 一 Synchronized如何实现线程同步 xff1f Java对象中有两个重要概念 xff1a Java对象头 和 Monit
  • A-star 算法原理分析

    搜索算法 图论中 xff0c 应用最广泛的就是搜索算法了 xff0c 比如 xff0c 深度优先搜索 广度优先搜索等 在介绍 Dijkstra 算法那篇中 xff0c 除了深度优先 广度优先这种暴力搜索算法 xff0c 还有一些最短路算法也
  • ROS物理仿真环境学习 gazebo + rviz【问题记录】

    Turtlebot3与仿真 仿真环境搭建 span class token comment 一个命令安装所有TurtleBot3依赖项 span span class token function sudo span span class
  • 机器人技术-HC-SR04超声波传感器数据及机器人避障的应用

    比较详细的HC SR04超声波传感器数据及机器人避障的应用方法 言 超声波传感器概述 超声波传感器型号繁多 价格从几元钱到几百元不等 主要用于检测距离 同时根据声速计算出物体的距离 但超声波传感器有四个缺点 1 声音速度易受温度和风向等环境
  • 自旋锁基本原理

    自旋锁基本原理 轻量级锁在加锁过程中 xff0c 用到了自旋锁 所谓自旋 xff0c 就是指当有另外一个线程来竞争锁时 xff0c 这个线 程会在原地循环等待 xff0c 而不是把该线程给阻塞 xff0c 直到那个 获得锁的线程释放锁之后
  • python获取视频帧率,总帧数,python ffmpeg获取视频信息ffmpeg.prob,python opencv获取视频信息cap.get(cv2.CAP_PROP_FRAME_WIDTH)

    文章目录 1 xff0c 效果2 xff0c ffmpeg获取视频信息2 xff0c opencv获取视频信息 1 xff0c 效果 2 xff0c ffmpeg获取视频信息 其中key xff1a streams 对应的值是一个list

随机推荐