当前位置:   article > 正文

STM32学习笔记【江科协】【3-2】LED闪烁&LED流水灯&蜂鸣器_stm32控制led闪烁代码

stm32控制led闪烁代码

 根据接线图接线,这里采用低电平的接线方式


速通新建工程

还要新建一个System,存放系统资源

1.Start启动文件

找到固件库文件,打开启动文件 放在start的文件夹下 

这三个文件同样复制到start文件夹下

2. Library文件夹

找到标准外设驱动文件夹

3.Project文件夹

 main.c直接复制过来,就不用新建文件了

到此为止,工程文件的复制就完成了

4.System文件夹

 5.工程组里的文件添加

把默认组删掉,再新建三个组还有一个System

 

6.工程选项配置

这里是把System给加上

在调试器右端的setting里

6.main函数

加上头文件,写上主函数

  1. #include "stm32f10x.h" // Device header
  2. int main(void)
  3. {
  4. while(1)
  5. {
  6. }
  7. }

到这里工程就搭建完毕了


*小工具

 双击一下keilkill


点亮LED

操作STM32的GPIO需要三个步骤:1.使用RCC打开GPIO的时钟;2.使用GPIO_Init函数初始化GPIO;3.使用输出或输入函数来控制GPIO口

这里涉及了GPIO和RCC两个外设,可以看看这两个外设有哪些库函数

RCC库函数

RCC最常用的库函数有三个

右键点击函数名,跳转到函数定义 

 GPIO库函数

 

 void GPIO_DeInit(GPIO_TypeDef* GPIOx);

*调用这个函数,所指定的GPIO就会被复位
void GPIO_AFIODeInit(void);

*可以复位AFIO外设
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

*用结构体的参数来初始化GPIO端口,需定义一个结构体变量,然后再给GPIO赋值,最后再调用这个函数,这个函数就会自动读取结构体的值,自动把外设各个参数配好

*这种Init函数几乎在所有外设中都有,一般初始化外设都是使用Init函数来完成的
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);

*把结构体变量默认的赋一个值
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

*以上四个是GPIO的读取函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

*以上四个是GPIO的写入函数

*这些函数可以实现读取GPIO口的功能

 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

这样时钟就开启了

 第一个参数根据跳转的定义填写为GPIOA一个小细节,

GPIO_InitTypeDef GPIO_Initstructure;这个结构体是一个局部变量

 

 GPIO_Mode_AIN = 0x0,

*AIN(Analog IN)模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,

*IN_FLOATING是浮空输入
  GPIO_Mode_IPD = 0x28,

*IPD(In Pull Down)是下拉输入
  GPIO_Mode_IPU = 0x48,

*IPU(In Pull Up)是上拉输入
  GPIO_Mode_Out_OD = 0x14,

*Out_OD(Out Open Drain)是开漏输出
  GPIO_Mode_Out_PP = 0x10,

*Out_PP(Out Push Pull)是推挽输出
  GPIO_Mode_AF_OD = 0x1C,

*AF_OD(Atl Open Drain)是复用开漏
  GPIO_Mode_AF_PP = 0x18 

*AF_PP(Atl Push Pull)是复用推挽

点灯使用的是推挽输出,所以复制GPIO_Mode_Out_PP

然后再配置GPIO_Initstructure.GPIO_Pin,同样跳转定义

第三个GPIO_Initstructure.GPIO_Speed是一样的套路,选择GPIO_Speed_50MHz

注意取地址!!!

这样初始化就完成了,当GPIO_Init函数执行完,就实现以上内容

 内部的主要执行逻辑是,读取结构体参数,执行一堆判断和运算,然后再写入GPIO配置寄存器

  1. GPIO_InitTypeDef GPIO_Initstructure;
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  3. GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;
  4. GPIO_Initstructure.GPIO_Pin = GPIO_Pin_12;
  5. GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
  6. GPIO_Init(GPIOB, &GPIO_Initstructure);

这样GPIO的初始化已经完成了,这样就可以使用GPIO的输入输出函数了

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

*这个函数可以把指定端口设置为高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

*把指定端口设置为低电平
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);

*第三个参数BitVal,这个是根据第三个参数的值来设置指定的端口的
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

*这个函数可以同时对16个端口执行写入操作

首先来使用一下void GPIO_ResetBits,看一下函数的定义

 

 于是可以写为

GPIO_ResetBits(GPIOA, GPIO_Pin_0);

同样可得
 

GPIO_SetBits(GPIOA, GPIO_Pin_0);

接下来使用一下void GPIO_WriteBit

定义中写到,这个端口可以是BitAction枚举中的值,还有Bit_RESET和Bit_SET

GPIO_WriteBit(GPIOA,GPIO_Pin0, Bit_RESET);

 置低电平,灯点亮

GPIO_WriteBit(GPIOA,GPIO_Pin0, Bit_SET);

置高电平,灯熄灭


LED闪烁

为了实现闪烁功能,在逻辑上应该是在循环里,点亮LED,延时一段时间,熄灭LED,延时一段时间

把加入延时函数程序模板放在前面新建工程里了

分别是微秒延时、毫秒延时、秒延时

可以看到是使用SysTick定时器实现的延时

 

  1. #include "stm32f10x.h" // Device header
  2. #include "delay.h"
  3. int main(void)
  4. {
  5. GPIO_InitTypeDef GPIO_Initstructure;
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7. GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8. GPIO_Initstructure.GPIO_Pin = GPIO_Pin_0;
  9. GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
  10. GPIO_Init(GPIOA, &GPIO_Initstructure);
  11. while(1)
  12. {
  13. GPIO_SetBits(GPIOA, GPIO_Pin_0);
  14. Delay_ms(500);
  15. GPIO_ResetBits(GPIOA, GPIO_Pin_0);
  16. Delay_ms(500);
  17. GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
  18. Delay_ms(500);
  19. GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
  20. Delay_ms(500);
  21. GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);//强制类型转换就可以实现不用填入指定的参数,写0和1即可
  22. Delay_ms(500);
  23. GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
  24. Delay_ms(500);
  25. }
  26. }

这里讨论一下推挽输出和开漏输出驱动问题

把LED的正负极对换,这样LED是高电平点亮方式,这样可以看到,LED依旧是正常闪烁的,说明在推挽模式下,高低电平都是有驱动能力的

把端口模式换为GPIO_Mode_Out_OD,开漏输出模式,LED不亮了,现在LED还是高电平点亮方式,LED不亮,说明开漏输出没有高电平驱动能力,再调换LED正负极,可以看到LED正常闪烁,说明开漏模式下低电平是有驱动能力的

这就映证了上节推挽输出和开漏输出的特性,推挽输出高低电平均有驱动能力,开漏输出高电平相当于高阻态,没有驱动能力,低电平有驱动能力

一般输出用推挽输出就行了,开漏输出在特殊情况下使用


LED流水灯

接线图

 

 为什么可以这样操作?将各位转化为二进制是0000000000000001、0000000000000010、0000000000000100,这里每一个端口对应着一个位,按位或的操作就相当于0000000000000111

所有位都为1,相当于选中了所有的引脚

同样解释了why
ResetBits也是这样,看函数定义解释的任意组合(any combination)同样是这个意思

 

 GPIO_Write看第二个参数的定义

 

C语言不支持写二进制,只能在转换为16进制来写,这二进制的16位对应着16个端口

 

  1. #include "stm32f10x.h" // Device header
  2. #include "delay.h"
  3. int main(void)
  4. {
  5. GPIO_InitTypeDef GPIO_Initstructure;
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7. GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8. //GPIO_Initstructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; 按或取
  9. GPIO_Initstructure.GPIO_Pin = GPIO_Pin_All;
  10. GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOA, &GPIO_Initstructure);
  12. while(1)
  13. {
  14. //Q1:一开始是没有按位取反~,然后导致小灯常亮
  15. //Q2:看弹幕说可以用for循环减轻工作量
  16. GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
  17. Delay_ms(500);
  18. GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
  19. Delay_ms(500);
  20. GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
  21. Delay_ms(500);
  22. GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000
  23. Delay_ms(500);
  24. GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000
  25. Delay_ms(500);
  26. GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000
  27. Delay_ms(500);
  28. GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000
  29. Delay_ms(500);
  30. GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000
  31. Delay_ms(500);
  32. }
  33. }

蜂鸣器 

接线图

 

  1. #include "stm32f10x.h" // Device header
  2. #include "delay.h"
  3. int main(void)
  4. {
  5. GPIO_InitTypeDef GPIO_Initstructure;
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  7. GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8. GPIO_Initstructure.GPIO_Pin = GPIO_Pin_12;
  9. GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
  10. GPIO_Init(GPIOB, &GPIO_Initstructure);
  11. while(1)
  12. {
  13. GPIO_SetBits(GPIOB, GPIO_Pin_12);
  14. Delay_ms(100);
  15. GPIO_ResetBits(GPIOB, GPIO_Pin_12);
  16. Delay_ms(100);
  17. GPIO_SetBits(GPIOB, GPIO_Pin_12);
  18. Delay_ms(100);
  19. GPIO_ResetBits(GPIOB, GPIO_Pin_12);
  20. Delay_ms(700);
  21. }
  22. }

 库函数的使用方法

 

不过这个用户手册用的版本并不对应我们现在使用库函数的版本

 

*我打不开这个参考文档

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

闽ICP备14008679号