STM32实战之LED循环点亮

简介: STM32实战之LED循环点亮

说明

接着上一章讲。本章我们来讲一讲LED流水灯,循环点亮LED。

在LED章节有的可能没有讲到,本章会对其进行说明,尽量每个函数说一下作用。也会在最后说一下STM32的寄存器,在编程中寄存器是避免不了的东西,寄存器也是非常好理解的,就是羊肉串串成一串而已。其实对于嵌入式来说,大多数开发者都是根据官方提供的例程写的。很少只有手册让个人写的。只有做芯片底层开发的会根据,芯片的逻辑进行代码的编写。但是对于很多开发者来说,都是基于官方提供的芯片demo进行相关的底层配置与开发。

而我们要写的主要是应用层和一些模块底层的开发。而且多数的外设模块都有代码例程,即使没有文档也是较为清楚的。什么样的没有代码的,就是新出的芯片或者传感器,笔者做过恩智浦的一款新出的包括近期做一个芯驰的开发。网上资料少得可怜,只能参考官方例程。特别是芯驰的是去年10月份刚出的,他们的东西会出现各种问题,网上找不到,但是你也不要慌,他们会提供技术支持的,会告诉你怎么做。这些新出的东西,遇到了不要觉得是自己的问题,有可能是他们芯片或者demo的问题,就像近期做芯驰的开发板demo,调试,只有静置一段时间才可以(就是断电,全部断掉,等一会,这就是他们的问题),所以遇到问题不要怕。

对了,我写实战是根据F1的,和F4的本质都差不多。


1-配置

1static void Led_Cofig(void)
 2{
 3/*定义一个GPIO_InitTypeDef类型的结构体*/
 4GPIO_InitTypeDef GPIO_InitStructure;
 5/*开启LED相关的GPIO外设时钟*/
 6RCC_APB2PeriphClockCmd(LED_GPIO_CLCK, ENABLE);
 7/*选择要控制的GPIO引脚*/
 8GPIO_InitStructure.GPIO_Pin = (LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN | LED4_GPIO_PIN | LED5_GPIO_PIN | LED6_GPIO_PIN | LED7_GPIO_PIN | LED8_GPIO_PIN);
 9/*设置引脚模式为通用推挽输出*/
10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
11/*设置引脚速率为50MHz */
12GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //(指的是内部驱动电路的响应速度,速度越大越快,一般情况是有多个不同的速度,也可根据自己的需要安排)
13GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
14/* 关闭led灯    */
15GPIO_SetBits(LED_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN | LED3_GPIO_PIN | LED4_GPIO_PIN | LED5_GPIO_PIN | LED6_GPIO_PIN | LED7_GPIO_PIN | LED8_GPIO_PIN);
16}



1.1 RCC_APB2PeriphClockCmd()函数

RCC_APB2PeriphClockCmd()函数的功能是使能GPIOx对应的外设时钟,若使能GPIOC时钟,对应的代码如下:

1RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

RCC_APB2Periph_GPIOC是在stm32f10x_rcc.h头文件中定义的。RCC_APB2Periph_GPIOA~RCC_APB2Periph_GPIOG定义的代码如下:

1#define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004)
2#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008) 
3#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010) 
4#define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020) 
5#define RCC_APB2Periph_GPIOE ((uint32_t)0x00000040) 
6#define RCC_APB2Periph_GPIOF ((uint32_t)0x00000080) 
7#define RCC_APB2Periph_GPIOG ((uint32_t)0x00000100)


1.2 GPIO_Init()函数

GPIO_Init()函数的功能是初始化(配置)GPIO的模式和速度,也就是设置相应GPIO的CRL和CRH寄存器值。函数原型如下所示:

1void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
2

第一个参数是GPIO_TypeDef类型指针变量,用于确定是哪一个GPIO,GPIOx取值是GPIOA~GPIOG;第二个参数是GPIO_InitTypeDef类型指针变量,用于确定GPIOx的对应引脚以及该引脚的模式和速度等。


1.3 GPIO_ReadInputDataBit ()函数

GPIO_ReadInputDataBit ()函数的功能是读取指定I/O口的对应引脚值,也就是读取IDR(在下面会介绍)寄存器的值。函数原型是:

1uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

第一个参数同GPIO_Init()函数一样,第二个参数是读取GPIOx的对应引脚值。如读取GPIO6(即PC6)引脚代码是:

1GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6);

1.4 GPIO_ReadInputData ()函数

GPIO_ReadInputData()函数的功能是读取指定I/O口16个引脚的输入值,也是读取IDR寄存器的值。函数原型如下:

1uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

比如读取GPIOC输入端的值:

1tem=GPIO_ReadInputData(GPIOC);

但是如果采用寄存器的话就是:

1tem=GPIOC->IDR


1.5 GPIO_ReadOutputDataBit ()和GPIO_ReadOutputData ()函数对比

这两个函数从字面就能知道一个是对单独的IO进行操作,一个是对多个IO进行操作,下面就对这两个进行分析。

1//读取GPIO某个引脚的特定输出值。
2uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);


1例如:读取GPIOC中PC6的值
2GPIO_ReadOutputDataBit(GPIOC.GPIO_Pin_6);
3//读取GPIO端口指定组的值。
4uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
5比如读取GPIOC的值:
6GPIO_ReadOutputData( GPIOC);


1.6 GPIO_SetBits ()和GPIO_ResetBits ()函数

上一章已经说过了,本章不在多说。

函数GPIO_SetBits ()和GPIO_ResetBits ()的功能是用来设置指定I/O口的引脚输出高电平和低电平,也就是设置寄存器BSRR、BRR的值。

1.7 GPIO_WriteBit ()和GPIO_Write ()函数

这两个函数和1.5的类型是一样的。非别是对单个IO和一组IO控制,后面遇到这样的不在赘述,默认大家都知道。

GPIO_WriteBit ()函数的功能是向指定I/O口的引脚写0或者写1,也就是向寄存器ODR相应位写0或者写1。函数原型如下:

1void GPIO_WriteBit(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin, BitAction BitVal);

GPIO_Write()函数的功能是向指定I/O口写数据,也就是向寄存器ODR写数据。函数原型如下:

1void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
2举例:
3//向PC6写入1
4GPIO_WriteBit(GPIOC, GPIO_Pin_6, 1);
5//向GPIOC写入 0x0FFFC
6GPIO_Write(GPIOC, 0x0FFFC);



在这里需要注意一点:

GPIO_WriteBit()函数是对I/O口的一个引脚进行写操作,可以是写0或者写1;

GPIO_SetBits()函数可以对I/O口的多个引脚同时进行置位

这点大家一定要知道。

1GPIO_WriteBit(GPIOC,GPIO_Pin_8 , 0); //只能对一个引脚置0或置1
2GPIO_SetBits(GPIOC, GPIO_Pin_2 | GPIO_Pin_4); //可以同时对多个引脚置1


2 循环点亮LED

我设计的是8个流水灯,采用共阳极的接法,与PC1~7相连接。因为32不像51有移位控制语句。
先来看代码吧,这可以说是非常基础的了,为了方便大家理解。

1void LED_Cycle(void)
 2{
 3uint16_t temp, i;
 4temp = 0x01;
 5for (i = 0; i < 8; i++)
 6{
 7GPIO_Write(LED_GPIO_PORT, ~temp);
 8Delay(300);
 9temp = temp << 1;
10}
11for (i = 0; i < 8; i++)
12{
13GPIO_Write(LED_GPIO_PORT, ~temp);
14Delay(300);
15temp = temp >> 1;
16}
17}

首先我们从GPIOC0开始点亮这样一直循环下去:PC0点亮此位为0,依次类推如下:

1PC0亮:PC输出 0x0001,取反为0xFFFE,控制码就是0xFFFE
2PC1亮:PC输出 0x0002,取反为0xFFFD,控制码就是0xFFFD
3PC2亮:PC输出 0x0004,取反为0xFFFB,控制码就是0xFFFB
4PC3亮:PC输出 0x0008,取反为0xFFF7,控制码就是0xFFF7
5PC4亮:PC输出 0x0010,取反为0xFFEF,控制码就是0xFFEF
6PC5亮:PC输出 0x0020,取反为0xFFDF,控制码就是0xFFDF
7PC6亮:PC输出 0x0040,取反为0xFFBF,控制码就是0xFFBF
8PC7亮:PC输出 0x0080,取反为0xFF7F,控制码就是0xFF7F


然后重复执行。

根据上面的,只需将控制码从GPIOC输出即可。怎样输出呢,就是出事一位为高然后进行取反操作,在对其进行移位,然后进行循环操作(方法不止这一种,可尝试其他方式)。

“GPIO_Write(GPIOC,~temp);”语句将初始控制码0x0001取反(也就是0xFFFE)后,从GPIOC口输出,使得PC为低电平,点亮PC0,其他位为高电平;然后延时一段时间;让控制码移位,获得下一个控制码;然后再对控制码取反后输出到GPIOC口,就这样依次进行。

主函数

1int main()
2{
3LED_Init();
4while (1)
5{
6LED_Cycle();
7}
8}


image.png

今天太晚了,哪天腾出一章用来写各个寄存器,本来是想和库函数穿插这说的。又考虑到,有些人对寄存器不太熟悉,穿插着对其不太友好。今天就到这了,喜欢就动动手一键三连,谢谢。

相关文章
|
存储 数据安全/隐私保护
STM32实战项目—密码锁
本文完整详细地介绍了一个密码锁项目的要求,设计思路,程序实现,问题总结和成果展示内容。
252 2
STM32实战项目—密码锁
|
芯片
最详细STM32,cubeMX 按键点亮 led
最详细STM32,cubeMX 按键点亮 led
194 0
|
传感器 芯片
最详细STM32,cubeMX 点亮 led
最详细STM32,cubeMX 点亮 led
163 0
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
444 2
|
1月前
stm32学习 3-2 LED流水灯
stm32学习 3-2 LED流水灯
69 4
|
1月前
stm32学习3-1 LED闪烁
stm32学习3-1 LED闪烁
35 4
|
4月前
STM32CubeMX FreeRTOS点亮LED
STM32CubeMX FreeRTOS点亮LED
78 10
|
4月前
STM32CubeMX 按键控制LED
STM32CubeMX 按键控制LED
71 0
|
4月前
STM32CubeMX 点亮LED
STM32CubeMX 点亮LED
60 0
|
4月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
161 0