2020-09-05

嵌入式c:

嵌入式即嵌入式系统,IEEE(美国电气和电子工程师协会)对其定义是用于控制、监视或者辅助操作机器和设备的装置,是一种专用的计算机系统;国内普遍认同的嵌入式系统定义是以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统;从应用对象上加以定义来说,嵌入式系统是软件和硬件的综合体,还可以涵盖机械等附属装置。

嵌入式系统作为装置或设备的一部分,它是一个控制程序存储在ROM中的嵌入式处理器控制板。事实上,所有带有数字接口的设备,如手表、微波炉、录像机、汽车等,都使用嵌入式系统,有些嵌入式系统还包含操作系统,但大多数嵌入式系统都是由单个程序实现整个控制逻辑。

嵌入式C语言是作为嵌入式Linux开发的基础语言,也是学习嵌入式的必备语言。常用到的包括数据类型、运算符与表达式、控制语句、数组、指针、函数等内容。

嵌入式C语言就是针对嵌入式开发的C语言,其与标准c语言并非有什么大的差别,而在于其使用上我们考虑的角度不同,使用上的习惯不同。如嵌入式c语言开发会更在乎效率和内存有效使用等。

而涉及的嵌入式系统是将先进的计算机技术、半导体技术、电子技术和各行各业的具体应用相结合的产物,这就决定了它必然是一个技术密集、资金密集、高度分散、不断创新的知识集成系统。

一、位操作

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

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

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

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

 
  1. GPIOA-> BSRRL &=0XFF0F; //将第 4-7 位清 0

  2. 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

四、 extern  变量申明

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

 

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

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

          extern u16 USART_RX_STA;

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

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

          u16 USART_RX_STA;

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

五、typedef  类型别名

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

 

 
  1. struct _GPIO

  2. {

  3. __IO uint32_t MODER;

  4. __IO uint32_t OTYPER;

  5. }

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

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

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

方法如下:

 
  1. typedef struct

  2. {

  3. __IO uint32_t MODER;

  4. __IO uint32_t OTYPER;

  5. } GPIO_TypeDef

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

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

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

 
  1. typedef signed char int8_t;

  2. typedef signed short int int16_t;

  3. typedef signed int int32_t;

  4. 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;

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

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

总结文章

B站视频

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值