STM32入门基础

news2024/9/20 1:30:29

GPIO

<1>说明

· 引脚电平:0~3.3V,部分可达到5V(参考引脚定义,带FT的就可以)

同时 GPIO有两个模式

输出模式:进行端口高低电平的输出,用于驱动LED,蜂鸣器等

输入模式:读取端口高低电平的电压/电平,用于按键输入,ADC电压采集等

<2>基本结构

 APB2外设时钟总线,所有的GPIO都是挂载再APB2上的,其中GPIO的名称是按照GPIO A/B/C来命名的,每个外设都有15个引脚,编号为0~15

<3>GPIO模式

GPIO库函数编码

(1)使用RCC开启GPIO的时钟

(2)使用GPIO_Init()初始化GPIO

(3)使用输出/输入函数控制GPIO口

一个涉及到RCC和GPIO两个外设

1.常用的RCC外设时钟控制函数 AHB/APB2/APB1(最主要就这三个,其他几乎不用)

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

2.GPIO库函数

// 参数写入GPIOX,所指定的GPIO外设就会被复位
void GPIO_DeInit(GPIO_TypeDef* GPIOx);

//可以复位AFIO外设
void GPIO_AFIODeInit(void);

//GPIO初始化函数,我们需要先定义一个结构体变量,然后赋值,最后调用这个函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

//可以把结构体变量变成一个默认值
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);

/***********下面四个为GPIO的读取函数********/
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);
//前面的参数为选择端口,最后为指定写入数据值(Bit_SET  / Bit_RESET)
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);


//剩下的这些我们现在还不会用到
//锁定GPIO配置
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

//配置AFIO的事件输出功能函数
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);

//配置引脚重映射函数
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

//EXTI GPIO开启
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

3,开启流程(GPIO初始化)

//1.开启RCC外设
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  /*uint32_t RCC_APB2Periph*/, ENABLE);

//2.开启GPIO
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //选择模式
/*AIN模式输入,IN_FLOATING浮空输入,IPD下拉输入,IPU上拉输入
OUT_OD开漏输出(低电平有驱动力,高电平没有),PUT_PP推挽输出,AF则为复用 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //选择引脚

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//选择频率

GPIO_Init(GPIOA, &GPIO_InitStructure);           //初始化

EXTI中断函数

<1>中断

中断 : 在主程序运行过程中,出现特定的中断触发条件,使得CPU暂停当前正在运行的程序,而去处理中断程序,完成后,又返回原来被暂停的位置继续工作

中断优先 : 当有多个中断开始时,CPU会根据事情的轻重响应更加紧急的中断

中断嵌套 : 一个中断正常进行,又来一个更高级的中断,会先去做刚来的高级的中断,然后依次返回

  

<2>NVIC

 68个可屏蔽中断通道,包含EXTI,TIM,ADC,USART,SPI,IIC,RTC等多个外设

NVIC:NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级

抢占优先级高的可以进行中断嵌套,响应优先级高的可以进行优先排队,抢占优先级和响应优先级均相同的按中断号排队

<3>EXTI:(Extern Interrupt)外部中断

EXTI可以检测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

支持的触发方式:上升沿/下降沿/双边沿/软件触发

支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断

通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒

触发响应方式:中断响应/事件响应

AFIO选择中断引脚,外部中断的9-5,15-10会触发同一个中断函数,再根据标志位来区分到底是哪个中断进来的

配置数据选择器,只有一个Pin接到EXTI  

<4>配置步骤:

第一步,配置RCC,把设计到的外设时钟都打开

第二步,配置GPIO,选择端口为输入模式

第三步,配置AFIO,选择使用的一路GPIO,连接到后面的EXTI

第四步,配置EXTI,选择边沿触发方式,选择触发响应方式

第五步,配置NVIC,给中断选择一个合适的优先级

<5>库函数说明

首先,EXTI本身是不需要打开什么时钟的,所以前面正常打开GPIO就可以了

AFIO也使用RCC使能

void GPIO_EXTILineConfig(GPIO_PortSourceGPIOB /*引脚所在的源*/,GPIO_PinSource14 /*第14个中断线路);

 这个函数,可以让14号引脚的电平顺利通过AFIO,进入到后级EXTI电路中

EXTI库函数:

//调用他,可以清除EXTI的配置,恢复为默认的上电状态
void EXTI_DeInit(void);

//初始化EXTI,方法与GPIO相同
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

//参数传递的结构体变量赋一个默认值
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);

//软件触发外部中断
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);


//下面为模板函数
//读写中断标志位
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
//清楚中断标志
void EXTI_ClearFlag(uint32_t EXTI_Line);
//只能读写中断标志位
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

EXTI_Init参数

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//选择中断线路
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);///选择自己的引脚相同线路就好
	
	EXTI_InitTypeDef EXTI_InitStructure;//定义外部中断结构体
	EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;//设置中断线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;//开启中断线路
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
	EXTI_Init(&EXTI_InitStructure);//写入参数

NVIC内核外设库函数

//中断分组,参数是中断分组的方式
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

// NVIC初始化函数,根据结构体参数初始化
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);


void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
//系统低功耗配置
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);

分组在整个流程中只要进行一次就可以了,如果模块化要注意选择是同一个,可以选择放在主函数里

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组

NVIC结构体初始化内容

	//我们选择了两个分组,那么我们就配置两个
    NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
	NVIC_Init(&NVIC_InitStructure);//写入参数



	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//设置中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//通道使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应优先级
	NVIC_Init(&NVIC_InitStructure);//写入参数

中断服务函数

在STM32中,每个通道的中断服务函数名字都是固定的

void EXTI0_IRQHandler(void)//线路0中断函数
void EXTI1_IRQHandler(void)//线路1中断函数

获取标志位

if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断中断挂起位

服务函数结束后清除标志位

	EXTI_ClearITPendingBit(EXTI_Line0);//清除中断挂起标志位

定时器
TIM(Timer)定时器

定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

16位计数器、预分频、自动重装寄存器的时基单元,在72M计数时钟下可以实现最大59.65s的定时

不仅具备基本的定时器中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能

根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

对72MHz计72个数就是1MHz,也就是1us的时间,计72000个数,那就是1KHz也就是1ms的时间

59.65s =65536 · 65536 · 1/72M/(中断频率倒数),

STM32的定时器支持级联的模式:一个定时器的输出当做另一个定时器的输入最大定时时间就是59.65s · 65536 · 65536

定时器资源:

而STM32F103C8T6有TIM1/2/3/4四个定时器

· 预分频器(PSC):对输入的基准频率提前进行一个分频的操作
实际分频系数 = 预分频器的值 + 1,最大可以写65535即65536分频


· 计数器(CNT):也是16位,值可以从0~65535,当计数器的值自增(自减)到目标值时,产生中断,完成定时


· 自动重装寄存器():也是16位当计数值等于自动重装值时,就是计时的时间到了,就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时,计数值等于自动重装值的中断一般叫做“更新中断”,此更新中断就会通往NVIC,再配置好NVIC的定时器通道,定时器上的更新中断就会得到CPU的响应了,对应的事件叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作

基本结构

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SimBERT剖析

SimBERT SimBERT&#xff0c;它是以Google开源的BERT模型为基础&#xff0c;基于微软的UniLM思想设计了融检索与生成于一体的任务&#xff0c;来进一步微调后得到的模型&#xff0c;所以它同时具备相似问生成和相似句检索能力。 UniLM UniLM是一个融合NLU和NLG能力的Transfo…

远程桌面控制:SmartCode VNC ViewerX ActiveX 3.10 Crack

SmartCode::ViewerX VNC 查看器 ActiveX 毫不费力地将 VNC 查看器功能添加到您的应用程序 SmartCode ViewerX VNC 查看器 ActiveX 使开发人员可以使用一组直观的 ActiveX 属性和方法完全访问 VNC 查看器功能。借助ViewerX 控件&#xff0c;开发人员可以轻松地为其应用程序提供屏…

将自己写的代码利用git 上传到码云(gitee)或者github----最简洁明了版

前置操作 注册并激活码云账号&#xff08; 注册页面地址&#xff1a;https://gitee.com/signup &#xff09; 生成并配置 SSH 公钥 官方提供的生成并配置公钥的方法点此 创建空白的码云仓库 输入仓库名称之后路径会自动生成 把本地项目上传到码云对应的空白仓库中 如果您是…

MyBatis-Plus快速开始

文章目录介绍特性框架结构传统编程模式快速开始介绍 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。只做增强不做改变的意思是&#xff1a;MP不会影响原生的 M…

[HITCON 2017]SSRFme(perl脚本中get命令执行漏洞)

目录 代码审计 思路 知识补充 PHP中$_SERVER的详细用法 pathinfo() 函数 str_replace() 函数 escapeshellarg peal函数中get命令漏洞 Perl中open命令执行&#xff08;GET&#xff09; 代码审计 <?phpif (isset($_SERVER[HTTP_X_FORWARDED_FOR])) {$http_x_headers…

GuLi商城-项目初始结构创建

GitHub账号和密码 账号&#xff1a;11360XXXXXqq.com 密码&#xff1a;ZH**SH*19**1016 新建仓库&#xff1a; gulimall 记得勾选下Add a README file&#xff0c;上面忘记勾选了&#xff0c;实际建议还是要勾选下 复制路径&#xff1a; 打开IDEA检出项目 创建商品微服务模…

flutter 作为模块引入 iOS 项目

原文 http://summerxx.com/2023/01/28/ios-use-flutter/ 前言: 上篇我讲了下 flutter 环境在 MacOs 下搭建, 今天写下如何在一个成熟的 iOS 项目内引用 flutter, Demo 会放到文章最后哈 上篇 : MacOS 下配置flutter 环境 大致如下: 在项目内创建一个 flutter 模块 新建一个 …

Unity 在URP中显示动态批处理 Dynamic Batching 选项

Unity 在URP中显示动态批处理 Dynamic Batching 选项前言步骤1. 打开 Preferences 设置2. 选择 Core Render Pipeline 选项卡3. 修改 Visibility 为 All Visible4. 打开 Project Settings5. 打开 Graphics 选项卡6. 找到 URP 设置7. 开启 Dynamic Batching鸣谢前言 使用URP时突…

计算机相关专业提升学历的解决方案(本科及以下)

文章目录1、学历与学位的区别1.1 学历与学位的概念&#xff0c;学籍的规则1.2 学历与学位的作用2、正规全日制本科2.1 高考2.2 统招专升本3、继续教育&#xff08;非全日制&#xff09;3.1 自学考试&#xff08;无学籍&#xff09;3.2 成人高考&#xff08;函授&#xff0c;业余…

详谈ORB-SLAM2的跟踪线程Tracking

ORB-SLAM2的三大线程几乎都是每个部分对应一个函数&#xff0c;非常清晰。函数名起的都十分贴切&#xff0c;望文就能生义&#xff0c;我们更应该关注的是里面的关键帧地图点这些变量是怎么流转的。 Tracking线程的流程就是&#xff1a;首先输入一帧图像&#xff0c;然后实际上…

开启前端CSS学习之路-css003

&#x1f60a;博主页面&#xff1a;鱿年年 &#x1f449;博主推荐专栏&#xff1a;《WEB前端》&#x1f448; ​&#x1f493;博主格言&#xff1a;追风赶月莫停留&#xff0c;平芜尽处是春山❤️ 目录 CSS引入方式 一、CSS的三种样式表 1.内部样式表 2.行内样式表 3.外…

用java判断闰年

闰年的判断&#xff1a; 能被400整除的年份是闰年能被4整除的但是不能被100整除的年份是闰年 import java.util.Scanner; public class leapYear{public static void main(String[] args){int year;Scanner sc new Scanner(System.in);year sc.nextInt();if((year % 400 0)…

Java中对象的比较

从大根堆说到对象的比较大小根堆对象的比较equalsComparableComparator大小根堆 大小根堆是堆相关的知识,堆这种数据结构总结起来就是:堆顶元素是最大的就是大根堆,而每个堆顶元素以下的又可以看成一个堆: 要注意的是,堆底层是用数组实现的: 但是对这种数据结构具体化之后与…

JVM OOM和CPU问题排查

目录 1、JVM调优工具 1.1、jps 1.2、jstat 1.3、jstack 1.4、jinfo 1.5、jmap 2、OOM排查过程 2.1、OOM原因 2.2、OOM发生区域 2.2.1、Java堆溢出&#xff1a;heap 2.2.2、Java栈溢出&#xff1a;stack 2.2.3、运行时常量溢出&#xff1a;constant 2.2.4、方法区…

计算机毕业设计选题推荐nodejs+vue355的网上购物商城系统

网上购物商城&#xff0c;在系统首页可以查看首页、关于我们、商品信息、新闻信息、交流论坛、留言反馈、个人中心、后台管理、在线客服等内容 前端技术&#xff1a;nodejsvueelementui 前端&#xff1a;HTML5,CSS3、JavaScript、VUE 1、 node_modules文件夹(有npn install产…

spring整合mybatis的核心思路(数据源切换)

文章目录1. 整合思路2. 最简单的整合步骤1. 导入依赖2. 准备基础类UserUserMapperuserMapper.xmlMybatisConfig3. 测试TestMybatisSpring3. 整合多个mybatis配置1. 修改MybatisConfig2. 测试TestMybatisSpring4. AbstractRoutingDataSource实现源切换1. 准备基础类PersonPerson…

JVM的栈内存

每当启动一个新线程时&#xff0c;Java虚拟机都会为它分配一个Java栈。Java栈以帧为单位保存线程的运行状态。虚拟机只会直接对Java栈执行两种操作&#xff1a;以帧为单位的压栈和出栈。 某个线程正在执行的方法被称为该线程的当前方法&#xff0c;当前方法使用的栈帧称为当前帧…

车载以太网 - SomeIP测试 - 初识 - 01

SOA,Service-Oriented Architecture,即面向服务的架构 SOA是一种面向服务的架构,定义了“服务器”和“客户端”,前者是服务、数据的提供者,后者是订阅了所需要的服务或者数据。应用程序之间是公三耦合,并通过服务总线作为中间件进行通信。SOA更像是一种框架,需要将信息从…

【JavaGuide面试总结】Java集合篇·下

【JavaGuide面试总结】Java集合篇下1.HashMap 的长度为什么是 2 的幂次方2.HashMap 有哪几种常见的遍历方式?3.HashSet 如何检查重复?4.ConcurrentHashMap 和 Hashtable 的区别5.ConcurrentHashMap 线程安全的具体实现方式/底层具体实现JDK1.8 之前JDK1.8 之后6.JDK 1.7 和 J…

从零编写linux0.11 - 第九章 文件系统(一)

从零编写linux0.11 - 第九章 文件系统&#xff08;一&#xff09; 编程环境&#xff1a;Ubuntu 20.04、gcc-9.4.0 代码仓库&#xff1a;https://gitee.com/AprilSloan/linux0.11-project linux0.11源码下载&#xff08;不能直接编译&#xff0c;需进行修改&#xff09; 本章…