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_15
    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(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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小内存嵌入式设备软件的差分升级设计(学习)

摘要 提出一种改进HDiffPatch算法并在复旦微单片机上实现小内存差分升级的方案&#xff0c;即使用单片机内的Flash空间替代算法占用的RAM空间&#xff0c;从而减少算法对单片机RAM空间的需求&#xff0c;以满足小内存微处理器的差分升级&#xff0c;同时对算法内存分配释放函数…

JDK、JRE、JVM:揭秘Java的关键三者关系

文章目录 JDK&#xff1a;Java开发工具包JRE&#xff1a;Java运行环境JVM&#xff1a;Java虚拟机关系概述 案例示例&#xff1a;Hello World结语 在Java世界中&#xff0c;你可能经常听到JDK、JRE和JVM这几个概念&#xff0c;它们分别代表了Java开发工具包、Java运行环境和Java…

多线程的同步与互斥

文章目录 线程安全问题多线程互斥互斥量mutex互斥锁的使用理解锁加锁如何做到原子性对mutex做封装 可重入与线程安全死锁 线程同步条件变量条件变量函数接口理解条件变量条件变量的使用 线程安全问题 首先来看一段代码&#xff0c;该代码是一个多线程抢票的逻辑 #include<…

Python爬虫在框架下的合规操作与风险控制

大家好&#xff01;作为一名专业的爬虫代理供应商&#xff0c;我今天要和大家分享一些关于Python爬虫在法律框架下的合规操作与风险控制的知识。随着互联网的发展&#xff0c;数据爬取在商业和研究领域扮演着重要的角色&#xff0c;但我们也必须遵守相关法律和规定&#xff0c;…

交换排序——选择排序和冒泡排序的区别是什么?

今天重温一下算法&#xff0c;其实刚开始我觉得冒泡排序和选择排序是一样的&#xff0c;因为他们排序过程中都是通过相邻的数据比较找到最小/最大的数据&#xff0c;通过不断思考和学习才明白&#xff0c;两者还是有区别的。 冒泡排序 概念 冒泡排序(Bubble Sort)&#xff0…

JVM之内存模型

1. Java内存模型 很多人将Java 内存结构与java 内存模型傻傻分不清&#xff0c;java 内存模型是 Java Memory Model&#xff08;JMM&#xff09;的意思。 简单的说&#xff0c;JMM 定义了一套在多线程读写共享数据时&#xff08;成员变量、数组&#xff09;时&#xff0c;对数据…

Grafana技术文档--基本安装-docker安装并挂载数据卷-《十分钟搭建》-附带监控服务器

阿丹&#xff1a; Prometheus技术文档--基本安装-docker安装并挂载数据卷-《十分钟搭建》_一单成的博客-CSDN博客 在正确安装了Prometheus之后开始使用并安装Grafana作为Prometheus的仪表盘。 一、拉取镜像 搜索可拉取版本 docker search Grafana拉取镜像 docker pull gra…

AI绘画(1)stable diffusion安装教程

1、引言 stable diffusion 是一款免费开源的AI绘画工具&#xff0c;它能够帮助任何人轻松地进行绘画创作。不论你是有绘画基础还是完全没有经验&#xff0c;stable diffusion 都能让你在数字画布上释放创造力。 stable diffusion 提供了丰富多样的绘画工具和选项&#xff0c;…

Centos7源码安装redis

1、下载redis Index of /releases/ 2、解压redis tar -xvf redis-6.2.9.tar.gz 3、进入解压后的目录 cd redis-6.2.9/4、指定内存分配器为 libc make MALLOClibc 5、进入src目录&#xff0c;安装 cd src && make install6、运行 ./redis-server 7、添加开机…

了解IL汇编跳转语句

il代码&#xff0c; .assembly extern mscorlib {}.assembly Test{.ver 1:0:1:0}.module test.exe.method static void main() cil managed{.maxstack 5.entrypointldstr "Enter First Number"call void [mscorlib]System.Console::WriteLine (string)call string …

《大型网站技术架构设计》第二篇 架构-性能

不同视角下的网站性能 1、用户 从用户角度&#xff0c;网站性能就是用户在浏览器上直观感受到的网站响应速度快还是慢。用户感受到的时间。 2、开发人员 开发人员关注的主要是应用程序本身及其相关子系统的性能&#xff0c;包括响应延迟、系统吞吐量、并发处理能力、系统稳定…

ElasticSearch:项目实战(2)

ElasticSearch: 项目实战 (1) 需求&#xff1a; 新增文章审核通过后同步数据到es索引库 1、文章服务中添加消息发送方法 在service层文章新增成功后&#xff0c;将数据通过kafka消息同步发送到搜索服务 Autowiredprivate KafkaTemplate<String,String> kafkaTemplate;/…

python num循环怎么从1开始

如何实现python for循环从1开始&#xff1f; range()函数的作用和用法&#xff1a; 编写一个从数值1开始的循环&#xff1a; 执行后得到的结果 其他注意事项

hutool 导出复杂表头excel

假如已这样的表头导出数据 1.把包含表头的excel添加到项目资源目录 2.编写代码读取表头所在sheet,并且加入需导出的数据 /*** 导出excel*/public static void downloadExcel(List<List<Object>> list, HttpServletResponse response) throws IOException {/*Strin…

微信小程序读取本地json

首先在项目录下新建【server】文件夹&#xff0c;新建data.js文件&#xff0c;并定义好json数据格式。如下&#xff1a; pages/index/index.ts导入data.js并请求json pages/index/index.wxml页面展示数据

权限管理之admin数据不可编辑

效果图 在线地址&#xff1a;https://codesandbox.io/s/authorizedbyrole-yzy4r2?file/src/util/directive.js 当前用户为非管理员角色 环境 vuetify2.6.6 vuex javascript 事情经过 一般的系统&#xff0c;都是采用**RBAC模型&#xff1a;基于用户-角色-权限控制** 所以在…

python+vue生成条形码码并展示

需求 最近想做一个小工具&#xff0c;大概要实现这样的效果&#xff1a;后端生成条形码后&#xff0c;不保存到服务器&#xff0c;直接返回给前端展示。 大概思路是&#xff0c;通过 python-barcode库 生成条码的字节流&#xff0c;生成字节流后直接编码成base64格式返回给前…

【Freertos基础教程】任务管理之基本使用

文章目录 前言一、freertos任务管理是什么&#xff1f;二、任务管理涉及到的一些概念1.任务状态2.优先级3.栈(Stack)4.事件驱动5.协助式调度(Co-operative Scheduling) 二、任务的基本操作1.创建任务什么是任务 2.创建任务3.任务的删除4.任务的调度3.简单示例 总结 前言 本fre…

pnpm常用命令

pnpm常用命令 下载pnpm&#xff0c;但是出现了 npm WARN notsup Unsupported engine for pnpm8.6.12: wanted: {"node":">16.14"} (current: {"node":"14.15.0","npm":"6.14.8"}) npm WARN notsup Not compa…

指针进阶大冒险:解锁C语言中的奇妙世界!

目录 引言 第一阶段&#xff1a;&#x1f50d; 独特的字符指针 什么是字符指针&#xff1f; 字符指针的用途 演示&#xff1a;使用字符指针拷贝字符串 字符指针与字符串常量 小试牛刀 第二阶段&#xff1a;&#x1f3af; 玩转指针数组 指针数组是什么&#xff1f; 指针…