前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【通信专栏】附录一:单片机C语言基础/逻辑运算/按位运算/结构体/宏定义

【通信专栏】附录一:单片机C语言基础/逻辑运算/按位运算/结构体/宏定义

作者头像
周旋
发布2020-06-04 15:41:27
6830
发布2020-06-04 15:41:27
举报
文章被收录于专栏:行走的机械人行走的机械人

在单片机开发中,总有一些C语言基础知识是常常用到的而我们又不易掌握的,今天以STM32单片机为例,总结一下那些常用的C语言基础知识,例如逻辑运算符,结构体,宏定义以及按位运算符。

逻辑运算符

逻辑运算符包含三类:逻辑与(&&)逻辑或(||)以及逻辑非(!),它们的使用还是非常简单的,就不多做解释了,使用说明看下表:

需要注意的是,逻辑运算的结果只有0和1,并不能有其他臆想的使用方法。在STM32单片机开发中,最常用到的大概就是逻辑非了,例如在跑马灯实验中,我们可以应用逻辑非(!)反复置反LED0的状态,以达到使其闪烁的目的:

结构体

结构体是32单片机开发中最常用的数据结构了,整个库函数包都是以结构体为基石搭建起来的,因此熟练掌握结构体的使用非常有必要。这里我们就以单片机中最常见到的算法:PID算法来进行示例。

结构体的声明与定义

声明结构体的一般形式为:

struct 结构体名

{ 成员表列 } ;

例如声明一个包含PID成员变量的结构体:

struct PID

{

float P;

float I;

float D;

}; //全局变量

在声明完毕后,可以另行定义PID结构体变量,例如:

struct PID PID_X;

struct PID PID_Y;

这时便定义了两个PID结构体:PID_XPID_Y

此外还可以在声明结构体时直接定义结构体变量:

struct 结构体名

{

成员表列

} 变量名表列;

结构体的初始化与引用

在结构体定义完后,可以采用两种方式进行初始化:

方法一:在声明时直接初始化

struct PID

{

float P;

float I;

float D;

} PID_X={1.1,2.0,3.4},PID_Y={2.3,4.2,6.2} ;

方法二:在声明后进行额外初始化

至于结构体变量的引用,就用点(.)运算符就好了:

PID_X . P = 1.1 ;

typedef声明

typedef声明可以定义新的类型名来取代已有的类型名,在STM32单片机开发时常用到的u8 , u16就是这么来的,我们可以双击u8 选中并查看它的定义:

我们可以看到是一个typedef声明的结构体,而里面的uint8_t其实就是无符号字符型,我们可以双击选中它并查看定义,如下图。同样u16,u32也是一个道理。

1:使用简单的类型名代替复杂的类型名:如上图中的

typedef unsigned char uint8_t ;

2:定义一个新的类型名来代替结构体类型:

例如当我们需要定义一个PID结构体时,按照上文,我们需要:

在上图中,结构体名字为

struct PID ,在声明时也需要写为:

struct PID PID_X;

但若使用typedef定义一个新的结构体名时,可以如下:

宏定义define

#开头的语句为 “ 编译预处理指令 ”。

定义一个宏:

#define PI 3.1415926

在程序中用3.1415926 原封不动的替换掉 PI 。

原封不动,就是直接替换,不会隐形的添加括号,例如语句:

#define a 3+3

那么程序中 a*a是什么呢?是 3+3*3+3;而非(3+3)*(3+3)。

没有值的宏

#define _DEBUG

没有值的宏常常用来做条件编译宏,比如在程序中我们来检测是否存在该宏,若没有则执行某程序,若有则执行另外的程序。

按位运算符

C语言的按位运算符已经非常接近底层操作了,包含六个基本运算符号:

  • & 按位与
  • | 按位或
  • ~ 按位取反
  • ^ 按位异或
  • << 左移
  • >> 右移

在前三个里面呢,按位与,按位或,按位取反与本文开头的逻辑运算符相类似,只不过按位运算符是将一个数变为二进制之后对每一位进行计算。在STM32单片机开发中,我们最常用到按位与和按位或的地方便是初始化代码部分了:

上图中红框区域,大家可以这样理解:

将00000010 与00000001进行按位或操作,得到的为00000011,在寄存器中因为第七位和第八位(分别控制P6,P7引脚)变为1,则相应引脚被置高。上图红圈一行可以简化a = b | c ; ,在实际应用中,我们也会见到类似于 a |= b ( a=a | b ) 这样的式子。

按位取反便是将每一位上的数取反,1变0 0变1,

按位异或运算便是将两个数的二进制相对应的位比较,相同为0,不同为1,如下图:

左移运算符的语法如下: value << shift 其 中 ,value是要被操作的整数值,shift是要移动的位数。例如,下 面 的 代码将值13的所有位都向左移 3 位 :

13<<3 ;

腾出的位置用0填充,超出边界的位被丢弃。

也可以和赋值运算符相结合:

int x = 13 ;

int y = x<<3 ;

在STM32单片机开发时,左移右移运算符更常用于寄存器开发方式。

常用按位运算符技术

1:打开位

下面两项操作打开lottabits中对应于bit表示的位:

lottabits = lottabits | bit; lottabits |= bit ; 它们都将对应的位设为 1,而不管这一位以前的值是多少。这是因为对1和1 或者 0 和 1执行 或操作时,都将得到1。lottabits中其他所有位都保持不变,这是因为对0 和 0 做OR操作将得到 0,对1和做OR操作将生成 1。

2:切换位 下面两项操作切换lottabits中 对 应 于bit表 示 的 位 。也就是说,如果位是关闭的,则将被打 开;如果位是打开的,将被关闭 :

lottabits = lottabits A bit; lottabits A= b i t ;

3 . 关闭位 下面的操作将关闭lottabits中对应于bit表示的位 : lottabits = lot t a b i t s & - b i t ; 该语句关闭相应的位,而不管它以前的状态如何。首先,运算符〜bit将 原來为1的位设置为0, 原来为0的位设置为1。对0和任意值执行AND操作都将得到0 , 因此关闭相应的位。lottabits中其他所有位都保持不变,这是因为对 1和任意值执行AND操作时,该位的值将保持不变。下面足一种更简洁的方法:

lottabits & = - b i t ;

好啦,本文到此便结束了,仅是罗列了一些基本的知识点,而且并不全面,因为一旦篇幅过长,相信大家也将没有耐心把它们记住了,不如一点一点的来。微信公众号(行走的机械人)最近一段时间将持续更新【通信专栏】,欢迎关注哦。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Opencv视觉实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档