当前位置:   article > 正文

江协科技/江科大-STM32入门教程-5.GPIO输入、库函数必备C语言知识_gpio c语言

gpio c语言

目录

按键简介

 传感器模块简介

按键和传感器硬件电路

C语言数据类型 

C语言宏定义

C语言typedef

C语言结构体

C语言枚举

其它

0. 江协科技/江科大-STM32入门教程-各章节详细笔记-查阅传送门-STM32标准库开发_stm32江协大 csdn-CSDN博客文章浏览阅读3.4k次,点赞47次,收藏143次。江协科技/江科大-STM32标准库开发-各章节详细笔记-传送门至各个章节笔记。基本上课程讲的每句都详细记录,方便回顾。_stm32江协大 csdnhttps://blog.csdn.net/m0_61712829/article/details/132434192?spm=1001.2014.3001.5501GPIO输入模式硬件以及c语言下面知识点是库函数反复出现的东西,了解后会对库函数的执行逻辑更加清晰明了。另外还有c语言的指针,在后面文章会单独进行阐述。


按键简介

按键:常见的输入设备,按下导通,松手断开

 按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随有一连串的抖动

 传感器模块简介

传感器模块:传感器元件(传感器模块就是利用传感器元件,比如如下图的光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化(比如光线越强,光敏电阻的阻值就越小),通过与定值电阻进行串联分压即可得到模拟电压输出,再通过电压比较器进行二值化(二值化就是要么是高要么是低)即可得到数字电压输出

 如下为传感器模块的基本电路,详细介绍。

这个N1就是传感器元件所代表的可变电阻,它的阻值可以根据环境的光线、温度等模拟两进行变化

N1上面的R1,是和N1进行分压的定值电阻,R1和N1串联,一端接VCC一端接VSS,这就构成了基本的分压电路,AO电压就由R1和N1两个电阻的分压得到。

AO电压就由R1和N1两个电阻的分压得到。

N1左边的C2是一个滤波电容,它是为了给中间的电压输出进行滤波的,用来滤除一些干扰,保证输出电压波形的平滑。一般我们在电路中遇到一端接到电路中,另一端接地的电容,都可以考虑一下是不是滤波电容的作用,并不是电路的主要框架,这时候我们进行分析电路时,就可以先把这个电容抹掉,这样就可使我们的电路分析更加简单。

二值化输出是通过这个LM393芯片来完成,是一个电压比较器芯片,里面由两个独立的电压比较器电路,然后剩下的是VCC和GND供电,里面电容是一个电源供电的滤波电容,这个电压比较器其实就是一个运算放大器,当同向输入端的电压大于反向输入端的电压时,输出就会瞬间升高为最大值也就是输出接VCC;反之当同向输入端的电压小于反向输入端的电压时,输出就会瞬间降为最小值,也就是输出接GND,这样就可以对一个模拟电压进行二值化了,DO就是最后数字电压的输出。

 可以用上下拉电阻的思维分析传感器电阻的阻值变化对输出电压的影响,如下:

AO这个输出端可以把它想象成一个水平杆子(下图红色直线),R1上拉电阻相当于拴在上方的弹簧,将杆子向上拉,N1下拉电阻相当于拴在地面的弹簧,将杆子向下拉;电阻的阻值越小,弹簧的拉力就越强,杆子的高度就相当于电路中的电压,杠子向拉力强的一端偏移(取决于两个弹簧的弹力之差);如果上下弹簧拉力一致,杆子处于居中位置也就是电路输出VCC/2的电压;如果上面的阻值小,拉力强,输出电压就会变高;反之下面的阻值小,输出电压就会变低 ;如果上下拉电阻的阻值都为0,就是两个无穷大的力在对抗,在电路中呈现的就是电源短路(应该避免)。单片机电路中会常出现这种上拉下拉电阻,比如弱上拉,强上拉等(强和弱就是指电阻阻值的大小,也就是这个弹簧拉力大小) ,最终输出电压就是在弹簧拉扯下最终杆子的高低。

 

按键和传感器硬件电路

下接按键的方式如下,一般来说我们用下接按键的方式,这个原因和LED的接法类似,是电路设计习惯和规范;下左图中,按键按下时,PA0直接下拉到GND,此时读取PA0口的电压就是低电平,在这种接法下,必须要求PA0是上拉输入模式,使按键松下,还是高电平。下右图,外部接了一个上拉电阻,当按键松手时,引脚由于上拉作用,保持为高电平,此时PA0引脚就可以配置为浮空输入或者上拉输入。

上接按键的方式(仅了解)如下,左图1中,要求将PA0必须配置成下拉输入模式,松手时,引脚会回到默认值低电平。   

 

传感器模块电路如下,DO是数字输出端口,PA0用于读取数字量。

C语言数据类型 

关键字

位数

表示范围

stdint关键字

ST关键字

ST关键字

char

8

-128 ~ 127

int8_t

s8

s8

unsigned char

8

0 ~ 255

uint8_t

u8

u8

short

16

-32768 ~ 32767

int16_t

s16

s16

unsigned short

16

0 ~ 65535

uint16_t

u16

u16

int

32

-2147483648 ~ 2147483647

int32_t

s32

s32

unsigned int

32

0 ~ 4294967295

uint32_t

u32

u32

long

32

-2147483648 ~ 2147483647

unsigned long

32

0 ~ 4294967295

long long

64

-(2^64)/2 ~ (2^64)/2-1

int64_t

unsigned long long

64

0 ~ (2^64)-1

uint64_t

float

32

-3.4e38 ~ 3.4e38

double

64

-1.7e308 ~ 1.7e308

单片机中用char也就是int8_t来存放整数而不是字符等,有一定的区别需要注意。

C语言提供的stdint头文件,使用新的名字。比如int8_t就是char的新名字,表示的意思就是8位        整型的数据,右边加个_t 表示这是用typedef重新命名的变量类型。

ST关键字是老版本用的。

C语言宏定义

前为新,后为旧

关键字:#define

用途:用一个字符串代替一个数字,便于理解,防止出错;提取程序中经常出现的参数,便于快速修改

定义宏定义:     #define ABC 12345

引用宏定义:     int a = ABC;    //等效于int a = 12345;

C语言typedef

前为旧,后为新

typedef只能专门给变量类型换名字,更加安全(不是变量类型的名字是不行的);所以宏定义的改名范围更宽       

关键字:typedef

用途:将一个比较长的变量类型名换个名字,便于使用

定义typedef:     typedef unsigned char uint8_t;

引用typedef:      uint8_t a;    //等效于unsigned char a;

C语言结构体

结构体也是一种数据类型,比如char、int等是基本数据类型;数组是由许多相同基本数据类型的组合;与数组一样,但是若组合不同的数据类型就用结构体

关键字:struct

用途:数据打包,不同类型变量的集合

定义结构体变量:struct{char x; int y; float z;} StructName;

StructName是结构体变量的名字

因为结构体变量类型较长,所以通常用typedef更改变量类型名

引用结构体成员:

StructName.x = 'A';   

StructName.y = 66;  

StructName.z = 1.23;

或是用结构体指针方式,因为结构体是一种组合数据类型,在函数之间的数据传递中,通常用的是地址传递而不是值传递(看一下指针教程)

杠大于号,结构体成员名

pStructName->x = 'A';    //pStructName为结构体的地址 

pStructName->y = 66;   

pStructName->z = 1.23;

代码理解,如下

  1. struct c;
  2. //定义了一个结构体类型,名字叫c,这是不完整的,还需加一个附加声明{打包的变量},如下
  3. struct {char x; int y; float z} c;
  4. //定义一个结构体变量,名字叫c,其中包含char型的x,int型的y和float型的z三个子项
  5. c.x = 'a';
  6. c.y = 66;
  7. c.z = 1.23;
  8. //结构体的引用,需写结构体名字c,然后用运算符取索引,索引是结构体子项的名字,如结构体名称.结构体子项

 

使用typedef 解决结构体名字太长的问题

  1. struct {char x; int y; float z} c;
  2. struct {char x; int y; float z} d;
  3. // 再定义d,结构体数据类型就太长了
  4. typedef struct {char x; int y; float z} struct_t;
  5. //使用typedef 定义一个新名字叫struct_t,再定义结构体时,就用这个新名字,如下
  6. // typedef struct {char x; int y; float z} struct_t; 这个太长,写成下面这个格式
  7. typedef struct {
  8. char x;
  9. int y;
  10. float z
  11. } struct_t;
  12. //如下为结构体的数据类型
  13. struct {
  14. char x;
  15. int y;
  16. float z
  17. }
  18. //使用typedef将结构体换了个名字叫struct_t(结构体的数据类型),之后用struct_t来进行结构体的定义
  19. typedef struct {
  20. char x;
  21. int y;
  22. float z
  23. } struct_t;
  24. struct_t c; // struct_t是结构体数据类型名字,c是结构体变量的名字
  25. struct_t d;
  26. //使用typedef定义后的新名字来定义结构体,struct_t是结构体数据类型,c是结构体变量的名字
  27. c.x = 'a';
  28. //使用结构体变量的名字,然后用点,来引出结构体成员的数据,这样就可以进行数据的写入和读取了

C语言枚举

和结构体差不多,也是一个数据类型

只能在它给定的参数列表里赋值,不能赋其它的值

枚举值也不是必须赋值给枚举变量的,也可以赋值给随意一个变量。所以说枚举也是一个宏定义的集合。

关键字:enum

用途:1.定义一个取值受限制的整型变量,用于限制变量取值范围(比如我们定义一个变量用来存储星期的值,理论上这个变量只能取1到7的值,若定义的是整形变量这时可能会出现数据不合法,比如星期8的情况出现,所以这时候需要定义一个取值受限制的整形变量,这个变量就是枚举);2.宏定义的集合

定义枚举变量: 

enum{FALSE = 0, TRUE = 1} EnumName;  (需要用逗号,限制EnumName的取值范围)

因为枚举变量类型较长,所以通常用typedef更改变量类型名:

typedef  enum{FALSE = 0, TRUE = 1}  EnumName_t  

使用新的名字EnumName_t  来定义枚举变量,命名为EnumName:

EnumName_t   EnumName

只能引用下面两种:

EnumName = FALSE; // EnumName = 0

EnumName = TRUE ; // EnumName = 1

引用枚举成员:     EnumName = FALSE;     EnumName = TRUE;

其它

对于C语言来说,主要由两个功能,一个是定义数据,一个是引用数据。

数组的引用如下:

  1. int b[5];
  2. //是定义了一个5个int型数据的数组,名字叫b
  3. b[0] = 11;
  4. //数组的引用是数组名b,加上方括号取索引;数组的第0个元素等于11
  5. b[1] = 66;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/935880
推荐阅读
相关标签
  

闽ICP备14008679号