STM32 F103C8T6学习笔记2:GPIO的认识—GPIO的基本输入输出—点亮一个LED

今日继续学习使用  STM32 F103C8T6开发板 点亮一个LED灯,文章提供源码,测试工程,实验效果图,希望我的归纳总结会对大家有帮助~

目录

GPIO的认识与分类 :

引脚安排整理:

定时器的引脚例举:

串口的引脚例举:

 CAN串口通信:

SPI通信:

IIC通信:

 其余引脚:

烧录引脚:

 相关库函数:

 拉高、拉低输出:

 APB2外设RCC开启GPIO时钟:

GPIO初始化函数:

接线与GPIO的初始化:

选择引脚:

 接线与创建文件、文件路径添加:

GPIO的初始化:

所有代码贴出:

测试效果展示:​编辑

测试工程下载:


GPIO的认识与分类 :

 首先看下这张表:它定义说明了STM32C8T6上所有48个引脚

主功能、默认复用、以及重定义功能:

建议保存此表,以后备用:

引脚安排整理:

其中有许多引脚,他们是不能被贸然设计使用为通用输入输出口的(并不是说不能,而是不推荐一上来就这么设计)

我们结合学习笔记1中的开发板原理图,归纳了以下一些引脚,不推荐最先设计被占用使用为通用输入输出口,当然,VCC和VDD是电源与地,也是不能的~

首先大致认识一下,有一共37个GPIO可以被配置,但 ADC \ TIMER定时器 \  通信与串口相关 的引脚是不推荐最先设计被使用为通用输入输出口的:

内核Cortex-M3
Flash64K x 8bit
SRAM20K x 8bit
GPIO

                                                            37个GPIO

                        分别为PA0-PA15、PB0-PB15、PC13-PC15、PD0-PD1

ADC2个12bit ADC合计12路通道(外部通道:PA0到PA7+PB0到PB1,内部通道:)
Timers

                         4个16bit定时器/计数器,分别为TIM1、TIM2、TIM3、TM4

                                其中TM1带死区插入,常用于产生PWM控制电机

通信串口2 IIC,2 SPI,3 USART,1 CAN

 接下来的分类只讲主功能,复用重定义不考虑:

定时器的引脚例举:

----------CH1CH2CH3CH4ETRBKIN

TIM1

上方是CH_xN

PB13PB14PB15PA11PA12PB12
PA8PA9PA2PA3
TIM2PA0PA1PA2PA3--------------------
TIM3PA6PA7PB0PB1--------------------
TIM4PB6PB7PB8PB9--------------------

其中,需要说明的是:

TIM1 中 CH_xN与CH_x

表示两个通道互补输出,也就是,你在设置这两个通道输出的时候,要是开启了互补输出,那么这两个引脚的输出电平始终相反,也就是一个引脚输出低电平,另一个引脚自动输出高电平,反之亦然。这样的输出方式一般用于电机驱动控制。

TIM1_ETR    是外部触发输入管脚;

TIM1_BKIN   是故障信号,用来关闭TIM1的输出。

由此我们发现,定时器TIM1的引脚功能最多最强大

对于其余定时器引脚 :若是用不到这么多定时器模块,是可以考虑作为通用输入输出口使用的

串口的引脚例举:

TXRXCTSRTSCK
USART1PA9PA10PA11PA12PA8
USART2PA2PA3PA0PA1
USART3PB10PB11PB13PB14PB12

 其中,需要说明的是:

 RX和TX这两个引脚的功能,这两个引脚是USART串行通信最常见和必不可少的两个引脚。但我们在手册中会发现关于USART的其他引脚:

USART_CK、USART_RTS、USART_CTS

在ARM处理器中的USART中,基本上都具有硬件流控的功能,也就是说一般都有RTS CTS引脚(注意:功能简单一点的处理器,如51、STM8等,很少有串口硬件流控功能)。

RTS:是模块的输入端,用于MCU通知模块,MCU是否准备好,模块是否可向MCU发送信息,RTS的有效电平为低。

CTS:是模块的输出端,用于模块通知MCU,模块是否准备好,MCU是否可向模块发送信息,CTS的有效电平为低

RTS (Require ToSend,发送请求)为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。

CTS (Clear ToSend,发送允许)为输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。

1 CD ← Carrier Detect 载波检测

2 RXD ← Receive Data 接收数据

3 TXD → Transmit Data 发送数据

4 DTR → Data Terminal Ready数据终端就绪

5 GND — System Ground 系统接地

6 DSR ← Data Set Ready 数据设备就绪

7 RTS → Request To Send 请求发送

8 CTS ← Clear To Send 允许发送

9 RI → 这个好像是什么提示信号

 CAN串口通信:

RXTX
CANPA11PA12

 CAN总线通信和串口通信是两种不同的通信协议。这两种协议都是用于在不同设备之间传输数据的。虽然它们的目标相同,但它们在数据传输的方式和速度方面有很大的不同。

此处不多介绍

SPI通信:

NSSSCKMISOMOSI
SPI 1PA4PA5PA6PA7
SPI 2PB12PB13PB14PB15

  SPI包含4条总线,分别为NSS、SCK、MISO、MOSI,各信号线功能如下:

  NSS为片选信号,当NSS信号为低电平时,片选有效,开始SPI主从模式通讯。

  SCK为时钟信号线,由主通讯设备产生,不同的设备支持的时钟频率不一样,STM32的SPI时钟频率最大为fpclk/2.

  MISO和MOSI为主设备和从设备通讯数据线。MISO为从主机到从机,MOSI为从从机到主机。

IIC通信:

SCLSDASMBA1
IIC 1PB6PB7PB5
IIC 2PB10PB11PB12

主要有三个引脚,分别是SDA、SCL、SMBA

最主要的通信引脚主要是SDA、SCL引脚。

I2C的所有硬件架构都是根据SCL线和 SDA线展开的,其中SMBA我们很少用到SMBA线主要用于SMBUS的

 其余引脚:

这部分例举出的引脚是不能被使用的,

不是像上面的那样,不建议被设计为通用输入输出口,而是不能使用

PC13         单片机的侵入检测引脚(TAMPER-RTC)  

PC14        OSC32_IN      低速外部时钟的输入

PC15        OSC32_OUT  低速外部时钟的输出

(一般在单片机上都有 OSCin 和 OSCout 两个晶振接入端口 ,我们可以用无源的晶振加上起震电容可以配合单片机是晶振起震,为系统提供时钟源。

低速外部时钟:一般指外接比较精确和稳定的32.768KHz晶振电路,主要是给RTC实时时钟和看门狗提供一个低功耗且精确的时钟源。)

OSC_IN      高速外部时钟输入 用于提供芯片的时钟信号

OSC_OUT  高速外部时钟输出 用于输出芯片的时钟信号

(高速外部时钟:一般是给芯片的内核供电,倍频后作为系统时钟。)

NRST        STM32芯片的复位引脚

PB4             nJTRST 是仿真器调试时的JTAG对内核的调试复位信号,一般用于信号调试,建议不要用作他用。


PA13        SWDIO:JTAG:Test Mode State pin ;  SWD: Data I/O pin 数据线

PA14        SWCLK:JTAG: Test Clock pin ;          SWD: Clock pin 时钟线

PB2            BOOT1

BOOT0       BOOT0

(

功能:在每个STM32的芯片上都有两个管脚BOOT0和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序,见下表:BOOT1=x   BOOT0=0   从用户闪存启动,这是正常的工作模式。

BOOT1=0   BOOT0=1   从系统存储器启动,这种模式启动的程序功能由厂家设置。

BOOT1=1   BOOT0=1   从内置SRAM启动,这种模式可以用于调试。

STM32三种启动模式对应的存储介质均是芯片内置的,它们是:

1)用户闪存 = 芯片内置的Flash。

2)SRAM = 芯片内置的RAM区,就是内存。

3)系统存储器 = 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序。

这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区。

扩展资料System memory:从系统存储器启动,这种模式启动的程序功能是由厂家设置的。

)

烧录引脚:

SWD接口的烧录引脚是不能使用的(PA13 PA14)

JTAG_Jlink接口:

使用Jlink向STM32烧录程序时需要六个引脚:但由于STM32 F103 C8T6引脚资源紧张,因此不建议使用Jlink下载程序,这里建议使用CMSIS_DMA仿真器 接单片机的SWD端口下载程序

所以Jlink相关的6个引脚中,以下三个可以作为普通IO口使用了,但需要配置:

PB4/JNTRST

PB3/JTDO    

PA15/JTDI

 这三个引脚默认的是JLink的复用功能,如果程序中还有其他GPIO口的配置,那这三个引脚的GPIO初始化一定要放在其他所有GPIO配置之后,否则依然无法作为普通IO使用。

#define GPIO_Remap_SWJ_JTAGDisable  ((uint32_t)0x00300200)  
/*!< JTAG-DP Disabled and SW-DP Enabled */void GPIOInit(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);    /* Disable JLink, enable SW */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   /* Push-pill output, it can be other output types */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   /* Push-pill output, it can be other output types */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
}

 如果非要把这三个引脚的配置放在其他GPIO配置之前,那么在程序中每次使用这些引脚前,需要再添加一句 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); 例如:

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);  
GPIO_ResetBits(GPIOB, GPIO_Pin_4);  // PB4 is set to 0;

 相关库函数:

 拉高、拉低输出:

//拉高引脚输出电平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)//拉低引脚输出电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

 

 APB2外设RCC开启GPIO时钟:

 RCC(Reset and Clock Control)是STM32微控制器中的一个模块,用于控制和配置各种外设的时钟和复位信息。在初始化STM32引脚之前,需要先开启相应引脚所对应的GPIO外设的时钟。

开启GPIO外设的时钟是为了确保引脚能够正常工作。因为STM32中的GPIO引脚是通过GPIO外设来控制的,而GPIO外设需要时钟信号来运行。通过RCC开启GPIO外设的时钟后,才能正常地对引脚进行配置和操作。

函数RCC_APB2PeriphClockCmd需要传入两个参数:RCC_APB2Periph和NewState。

参数RCC_APB2Periph是一个32位的无符号整数,用于指定要配置的外设的时钟使能。

参数NewState是一个表示状态(即使能或禁用)的枚举类型(FunctionalState),用于指定要对外设进行的操作,可能的取值为ENABLE(使能)或DISABLE(禁用)。

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)

GPIO初始化函数:

这个函数用于初始化GPIO,需要传入俩个参数: GPIO端口 与GPIO初始化 的结构体

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

接线与GPIO的初始化:

 

选择引脚:

现在经过刚才的归纳总结,我们将目光锁定在PB8 PB9这俩个引脚,他们的复用功能只有TIM4的通道,在定时器资源如此丰富的条件下,他们便显得不那么重要了,于是我决定在这初始化PB9为通用输入输出口来点亮我们第一个灯~~

 

 接线与创建文件、文件路径添加:

以下为我的接线方式:

需要接俩个设备在单片机:一个是CMSIS_DAP仿真器用于下载调试,还有一个LED灯模块,这里我购买的LED灯模块是高电平点亮

首先还是新建 .c与.h文件,这个新建步骤就不多赘述了,需要注意的是魔棒添加文件路径,否则编译器找不到文件来编译:

添加头文件路径(这个路径是你新建的.c与.h文件的目录),添加完点OK

 之前将这俩文件路径放在了\Project\RVMDK(uv5)

发现KEIL编译没出错但总打红叉说我fire not found

后来将文件放在别处: \User 之后就不这样了

这里需要注意一下

GPIO的初始化:

1.开启外设时钟:

2.定义一个GPIO_InitTypeDef类型的结构体:

3.结构体选择要控制的GPIO引脚

4.结构体选择设置引脚模式为通用推挽输出

5.结构体选择设置引脚速率为50MHz

6.调用库函数,初始化GPIO

//初始化LED引脚
void GPIO_init_LED(void)
{/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure0;		/*开启LED相关的GPIO外设时钟*/RCC_APB2PeriphClockCmd( LED0_GPIO_CLK,ENABLE);/*选择要控制的GPIO引脚*/GPIO_InitStructure0.GPIO_Pin = LED0_GPIO_PIN;	/*设置引脚模式为通用推挽输出*/GPIO_InitStructure0.GPIO_Mode = GPIO_Mode_Out_PP;   /*设置引脚速率为50MHz */   GPIO_InitStructure0.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化GPIO*/GPIO_Init(LED0_GPIO_PORT, &GPIO_InitStructure0);		}

所有代码贴出:

因为本节还未学到时钟树与时钟系统的配置,因此使用最低端的循环占用延时来达成LED闪烁的目的:

#include "stm32f10x.h"//定义LED端口引脚
#define LED0_GPIO_PORT    	GPIOB		                /* GPIO端口 */
#define LED0_GPIO_CLK 	    RCC_APB2Periph_GPIOB		/* GPIO端口时钟 */
#define LED0_GPIO_PIN			  GPIO_Pin_8		          //引脚/* 使用标准的固件库控制IO*/
#define LED(a)	if (a)	\GPIO_SetBits(LED0_GPIO_PORT,LED0_GPIO_PIN);\else		\GPIO_ResetBits(LED0_GPIO_PORT,LED0_GPIO_PIN)//初始化LED引脚
void GPIO_init_LED(void)
{/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure0;		/*开启LED相关的GPIO外设时钟*/RCC_APB2PeriphClockCmd( LED0_GPIO_CLK,ENABLE);/*选择要控制的GPIO引脚*/GPIO_InitStructure0.GPIO_Pin = LED0_GPIO_PIN;	/*设置引脚模式为通用推挽输出*/GPIO_InitStructure0.GPIO_Mode = GPIO_Mode_Out_PP;   /*设置引脚速率为50MHz */   GPIO_InitStructure0.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化GPIO*/GPIO_Init(LED0_GPIO_PORT, &GPIO_InitStructure0);		}

主函数:

int main(void)
{	uint32_t t;GPIO_init_LED();while(1)                            {	   LED(0);  //开灯t=9900000;while(t!=0){t--;}LED(1);  //灭灯t=9900000;while(t!=0){t--;}}
}

测试效果展示:

测试工程下载:

 https://download.csdn.net/download/qq_64257614/88197742?spm=1001.2014.3001.5503

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/92643.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux:shell脚本 正则表达式与AWK

一、正则表达式 由一类特殊字符及文本字符所编写的模式&#xff0c;其中有些字符&#xff08;元字符&#xff09;不表示字符字面意义&#xff0c;而表示控制或通配的功能&#xff0c;类似于增强版的通配符功能&#xff0c;但与通配符不同&#xff0c;通配符功能是用来处理文件…

硬件产品经理:从入门到精通(新书发布)

目录 简介 新书 框架内容 相关课程 简介 在完成多款硬件产品从设计到推向市场的过程后。 笔者于2020年开始在产品领域平台输出硬件相关的内容。 在这个过程中经常会收到很多读者的留言&#xff0c;希望能推荐一些硬件相关的书籍或资料。 其实&#xff0c;笔者刚开始做硬…

【UE】Web Browser内嵌网页的使用

零、准备 1.在Edit菜单打开插件界面 搜索Web Browser并勾选&#xff0c;按提示重启引擎。 2.在资源窗口右键创建Widget Blueprint&#xff0c;并打开 3.搜索canvas panel 并拖拽到下方 4.在实验分类中找到Web Browser拖拽到Canvs Panel下 4.选中WebBrowser在右侧细节面板中…

pycharm,VSCode 几个好用的插件

pycharm Tabnine AI Code 可以在编写程序的时候为你提供一些快捷方式&#xff0c;增加编程速度 Chinese 对英文不好的程序员来说是个不错的选择&#xff0c;可以将英文状态下的pycharm变为中文版的 ChatGPT 可以跟ai聊天&#xff0c;ai可以解决你80%的问题 &#xff0c;也可以帮…

用对角线去遍历矩阵

声明 该系列文章仅仅展示个人的解题思路和分析过程&#xff0c;并非一定是优质题解&#xff0c;重要的是通过分析和解决问题能让我们逐渐熟练和成长&#xff0c;从新手到大佬离不开一个磨练的过程&#xff0c;加油&#xff01; 原题链接 用对角线遍历矩阵https://leetcode.c…

自动化安装系统(一)

系统安装过程 加载boot loader加载启动安装菜单加载内核和initrd文件加载根系统运行anaconda的安装向导 安装光盘中与安装相关的文件 安装autofs启动后会自动出现/misc目录。 在虚拟机设置中添加CD/DVD&#xff0c;使用系统ISO文件&#xff0c;登录系统后mount /dev/cdrom …

【UE4 RTS】07-Camera Boundaries

前言 本篇实现的效果是当CameraPawn移动到地图边缘时会被阻挡。 效果 步骤 1. 打开项目设置&#xff0c;在“引擎-碰撞”中&#xff0c;点击“新建Object通道” 新建通道命名为“MapBoundaries”&#xff0c;然后点击接受 2. 向视口中添加 阻挡体积 调整阻挡体积的缩放 向四…

Redis中的数据类型

Redis中的数据类型 Redis存储的是key-value结构的数据&#xff0c;其中key是字符串类型&#xff0c;value有5种常用的数据类型: 字符串string哈希hash列表list集合set有序集合sorted set

【vue】简洁优雅的火花线、趋势线

来由 在github发现个好看易用的vue趋势线组件&#xff0c;特此记录。 效果 趋势图生成后效果如上&#xff0c;线条为渐变色&#xff0c;可设置是否平滑。具体线条走势&#xff0c;根据数据动态生成。 使用 安装 npm i vuetrend -S 引入 import Vue from "vue"…

Triangle Area

三角形面积&#xff0c;同底等高&#xff0c;等底等高&#xff0c;等底同高&#xff0c;转换 2 3 5 7 10 15 &#xff1f; 32

Python系统学习1-9-类(一)

一、类之初印象 1、类就是空表格&#xff0c;将变量&#xff08;列名&#xff09;和函数&#xff08;行为&#xff09;结合起来 2、创建对象&#xff0c;表达具体行 3、创建类就是创建数据的模板 --操作数据时有提示 --还能再组合数据的行为 --结构更加清晰 4、类的内存分配…

LeetCode 778. Swim in Rising Water【最小瓶颈路;二分+BFS或DFS;计数排序+并查集;最小生成树】2096

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

计算机视觉五大核心研究任务全解:分类识别、检测分割、人体分析、三维视觉、视频分析

目录 一、引言1.1 计算机视觉的定义1.1.1 核心技术1.1.2 应用场景 1.2 历史背景及发展1.2.1 1960s-1980s: 初期阶段1.2.2 1990s-2000s: 机器学习时代1.2.3 2010s-现在: 深度学习的革命 1.3 应用领域概览1.3.1 工业自动化1.3.2 医疗图像分析1.3.3 自动驾驶1.3.4 虚拟现实与增强现…

java面试基础 -- ArrayList 和 LinkedList有什么区别

目录 基本介绍 有什么不同?? ArrayList的扩容机制 ArrayLIst的基本使用 基本介绍 还记得我们的java集合框架吗, 我们来复习一下, 如图: 可以看出来 ArrayList和LinkedList 都是具体类, 他们都是接口List的实现类. 但是他们底层的逻辑是不同的, 相信学过这个的应该大概有…

CI+JUnit5并发单测机制创新实践

目录 一. 现状问题 二. 分析原因 三. 采取措施 四. 实践步骤 五. 效能提升 资料获取方法 一. 现状问题 针对现如今高并发场景的业务系统&#xff0c;“并发问题” 终归是必不可少的一类&#xff08;占比接近10%&#xff09;&#xff0c;每次出现问题和事故后&#xff0c…

JVM基础了解

JVM 是java虚拟机。 作用&#xff1a;运行并管理java源码文件锁生成的Class文件&#xff1b;在不同的操作系统上安装不同的JVM&#xff0c;从而实现了跨平台的保证。一般在安装完JDK或者JRE之后&#xff0c;其中就已经内置了JVM&#xff0c;只需要将Class文件交给JVM即可 写好的…

Linux MQTT智能家居项目(LED界面的布局设置)

文章目录 前言一、LED界面布局准备工作二、LED界面布局三、逻辑实现总结 前言 上篇文章我们完成了主界面的布局设置那么这篇文章我们就来完成各个界面的布局设置吧。 一、LED界面布局准备工作 首先添加LED灯光控制的图标。 将选择好的LED图标添加进来&#xff1a; 图标可以…

SpringBoot 配置⽂件

SpringBoot 配置⽂件 1. 配置文件的作用2. .配置⽂件的格式2.1 properties2.1.1 基本语法2.1.2 读取配置⽂件 2.2 yml2.2.1 概念2.2.2 基本语法2.2.3 配置对象2.2.4 配置集合 2.3 properties 和 yml 对比 1. 配置文件的作用 整个项⽬中所有重要的数据都是在配置⽂件中配置的&a…

ubuntu安装jdk、emqx、nginx

一、安装jdk 要在Ubuntu上安装JDK 1.8&#xff0c;您可以按照以下步骤进行操作&#xff1a; 打开终端&#xff08;CtrlAltT&#xff09;。确保您的系统已更新&#xff1a; sudo apt update sudo apt upgrade安装OpenJDK 8&#xff1a; sudo apt install openjdk-8-jdk安装完成…

1.MySQL数据库的基本操作

数据库操作过程&#xff1a; 1.用户在客户端输入 SQL 2.客户端会把 SQL 通过网络发送给服务器 3.服务器执行这个 SQL,把结果返回给客户端 4.客户端收到结果,显示到界面上 数据库的操作 这里的数据库不是代表一个软件&#xff0c;而是代表一个数据集合。 显示当前的数据库 …