首页 > 其他分享 >STM32笔记

STM32笔记

时间:2023-08-02 23:34:09浏览次数:29  
标签:0000 CFGR 笔记 STM32 Mode GPIO uint32 RCC

STM32笔记

SWD连接开发板

什么是SWD

SWD与JTAG同属调试接口,是芯片在设计之初就预制的对芯片进行开发调试并在开发板上预留的接口,

JTAG接口

目前开发板上的接口大多是20PIN的,与此对应的关系如下:
JTAP20PIN.png

DAPLink在JTAG接口连接

只用连接3根线 SWD、SWCLK、GND。对应关系为
img
连接时要注意将接口摆放与图片一致后接线,这样不容易弄反

GPIO

通用输入输出接口

GPIO_MODE

(1)GPIO_Mode_AIN 模拟输入
模式:GPIO_Mode_AIN
   TTL肖特基触发器
(2)GPIO_Mode_IN_FLOATING 浮空输入
模式:GPIO_Mode_IN_FLOATING
   上、下拉都不启用
(3)GPIO_Mode_IPD 下拉输入
模式:GPIO_Mode_IPD默认低电平
   下拉电阻启用
(4)GPIO_Mode_IPU 上拉输入
模式:GPIO_Mode_IPU 默认高电平
   上拉电阻启用

小结
上拉输入模式:区别在于没有输入信号的时候默认输入高电平(因为有弱上拉)。下拉输入模式:区别在于没有输入信号的时候默认输入低电平(因为有弱下拉)。对于浮空输入模式顾名思义也就是输入什么信号才是什么信号,对于浮空输入要保证有明确的输入信号。

(5)GPIO_Mode_Out_OD 开漏输出
模式:GPIO_Mode_Out_OD
   开漏:有一极处于开路状态(或称为高阻态)

![img](/i/l/?n=23&i=blog/2009236/202308/2009236-20230802232940155-379449176.png) ![img](/i/l/?n=23&i=blog/2009236/202308/2009236-20230802233009349-718174921.png)![img](/i/l/?n=23&i=blog/2009236/202308/2009236-20230802233021572-152631174.png)
(6)GPIO_Mode_Out_PP 推挽输出 模式:`GPIO_Mode_Out_PP`    **推**:使用单片机电压推送高电源电压    **挽**:使用低电压把外面电流拉进来 ![img](/i/l/?n=23&i=blog/2009236/202308/2009236-20230802233038174-368367239.png)

小结:

推挽输出 开漏输出
高电平 P-MOS激活N-MOS断开,3.3V P-MOS断开N-MOS断开,外部决定
低电平 P-MOS断开N-MOS激活,0V P-MOS断开N-MOS激活,0V
优点 直接输出3.3V 配合外部电路更加灵活
缺点 只能输出3.3V 高电平是高阻态,无输出能力

(7)GPIO_Mode_AF_OD 复用开漏输出
模式:GPIO_Mode_IPD
   管脚复用状态下的开漏输出
(8)GPIO_Mode_AF_PP 复用推挽输出
模式:GPIO_Mode_IPD
   管脚复用状态下的推挽输出

GPIO库函数简单说明

  1. GPIO_DeInit 重新初始化外围设备GPIOx相关寄存器到它的默认复位值
  2. GPIO_AFIODeInit 初始化交错功能(remap, event control和 EXTI 配置) 寄存器
  3. GPIO_Init 根据GPIO_初始化结构指定的元素初始化外围设备GPIOx
  4. GPIO_StructInit 填充GPIO_初始化结构(GPIO_InitStruct)内的元素为复位值
  5. GPIO_ReadInputDataBit 读指定端口引脚输入数据
  6. GPIO_ReadInputData 读指定端口输入数据
  7. GPIO_ReadOtputDataBit 读指定端口引脚输出数据
  8. GPIO_ReadOtputData 读指定端口输出数据
  9. GPIO_SetBits 置1指定的端口引脚
  10. GPIO_ResetBits 清0指定的端口引脚
  11. GPIO_WriteBit 设置或清除选择的数据端口引脚
  12. GPIO_Write 写指定数据到GPIOx端口寄存器
  13. GPIO_ANAPinConfig 允许或禁止 GPIO 4 模拟输入模式
  14. GPIO_PinLockConfig 锁定GPIO引脚寄存器
  15. GPIO_EventOutputConfig 选择GPIO引脚作为事件输出
  16. GPIO_EventOutputCmd 允许或禁止事件输出
  17. GPIO_PinRemapConfig 改变指定引脚的影射
  18. GPIO_EMIConfig 允许或禁止GPIO 8 和 9 的EMI 模式

PNP继电器

继电器原理图如下:
img

1. 工作状态分析
当PE2管脚输出为低电压,PNP三极管发射极(2号管脚)与集电极(3号管脚)导通,PNP三极管的发射极(2号管脚)与基极(1号管脚)导通,此时继电器处于工作状态,LED被点亮。此时继电器JDQ工作(因两侧存在电压差,2号管脚高),此时电流方向为2->1、2->3。
2. 静止状态分析
当PE2管脚输出高电压时,PNP三极管发射极(2号管脚)与基极(1号管脚)不存在电压差,此时电流被断开,不存在电流。继电器关闭,LED不点亮。

上拉电阻、下拉电阻、不上拉也不下拉

1、上拉电阻: 将电路连接到外部电源,提升电压。常用于漏极开路输出
2、不上拉也不下拉: 电路无变化连接到外部电源,常用于推挽输出
3、下拉电阻: 输入低电平

继电器与按钮Demo

案例实现点击key0继电器吸合两秒后自动关闭

mian.c

#include "sys.h"	
#include "delay.h"	
#include "led.h" 
#include "jdq.h" 
#include "key.h"

 int main(void)
 {
	delay_init();	    	 //延时函数初始化	  
	LED_Init();		  	 	//初始化与LED连接的硬件接口
	JDQ_Init();         	//初始化蜂鸣器端口
	Key_Init();
	while(1)
	{	
		LED1 =0;
		JDQ = 1;
		delay_ms(100);
		if(KEY0 == 0){
			LED0 = 0;
			JDQ = 0;
			KEY0 = 1;
			delay_ms(1000);
			delay_ms(1000);
		}
		LED0 = 1;
		JDQ = 1;
	}
 }

led.c

#include "led.h"

//初始化PB5和PE5为输出口.并使能这两个口的时钟		    
//LED IO初始化
void LED_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB,PE端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);						 //PB.5 输出高

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	    		 //LED1-->PE.5 端口配置, 推挽输出
 GPIO_Init(GPIOE, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
 GPIO_SetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出高 
}

jdq.c

#include "jdq.h"


//初始化PE2为输出口.并使能这个口的时钟		    
//继电器初始化
void JDQ_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);	 //使能GPIOE端口时钟
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				 //JDQ-->PE.2 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; 		 //开漏输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	 //速度为50MHz
 GPIO_Init(GPIOE, &GPIO_InitStructure);	 //根据参数初始化GPIOE.2
 
 GPIO_ResetBits(GPIOE,GPIO_Pin_2);//设置继电器关闭

}


优化按钮捕捉,检测按钮是否被处于空状态,代码编写提示、对按钮全过程检测

#include "sys.h"	
#include "delay.h"	
#include "led.h" 
#include "jdq.h" 
#include "key.h"

int getKey0Static(void);

 int main(void)
 {
	delay_init();	    	 //延时函数初始化	  
	LED_Init();		  	 	//初始化与LED连接的硬件接口
	JDQ_Init();         	//初始化蜂鸣器端口
	Key_Init();
	LED1 =0;
	JDQ = 1;
	while(1)
	{	
			int key0Static = getKey0Static();
			if( key0Static == 1){
					JDQ=~JDQ;
			}
	}
 }

int getKey0Static(void){
	static int key_up = 1;//按钮原位置
		
		if(key_up&&KEY0 == 0){
			delay_ms(30);
			if(KEY0 ==0){
				key_up = 0;
				return 1;
			}
			return 0;
		}else if(KEY0==1){
			key_up = 1;
			return 0;
		}
		return 0;
}

C语言按位操作

>>= 右移后赋值

例如 x=0x08 x>>=3
计算步骤如下:

  1. x=0000 1000
  2. 右移3位0000 0001
  3. 赋值后为0000 0001
  4. 结果x=0x01

<<= 左移后赋值

例如 x=0x08 x<<=3

  1. x=0000 1000
  2. 左移三位 0100 0000
  3. 赋值后为 0100 0000
  4. 结果 x=0x40

&= 按位与后赋值

例如 x=0x08 x &= 0x03

  1. x = 0000 1000
  2. 0x03=0000 0011
  3. end 0000 0000
  4. 赋值后为 0000 0000
  5. x=0x00

^= 按位异或后赋值

异或:两个不一样取1,一样取0
例如 x=0x09 x ^= 0x03

  1. x = 0000 1001
  2. 0x03=0000 0011
  3. end 0000 1010
  4. 赋值后为 0000 1010
  5. 结果x=0x0A

|= 按位或后赋值

有一个1就取1,两个都为0才取0
例如 x=0x08 x |= 0x03

  1. x = 0000 1000
  2. 0x03=0000 0011
  3. end 0000 1011
  4. 赋值后为 0000 1011
  5. 结果x=0x0B

小结

  • 或等于(|=)常用于对某一位赋值,因其后给的数与原数或后原数的1保持不变,只改变其他为0的位,
  • 与等于(&=)常用来对某一位或多个位清零,引起有0就为0,只有两个1才不为0的特性。要保留1位的就赋1,清除的就赋0

时钟树

img

  1. HSE、LSE分别为高速和低速外部时钟,一般为晶振产生。高速外部时钟输入范围为4-16MHz,低速外部时钟为定频40kHz
  2. HSI、LSI分别为高速和低速内部时钟,一般为内部RC震荡电路产生受温度影响。高速内部时钟为定频8MHz,低速内部时钟为定频32.768kHz
  3. 红圈2为选择器,选择应用哪个源作为输出时钟信号
  4. 红圈3为倍频器,将信号倍频x2~x16,
  5. 红圈5为分频器,将信号分频为/1、/2、/4、/8、/16、/64、/128、/256

设置系统时钟库函数

static void SetSysClockTo72(void)
{
    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

    // ① 使能HSE,并等待HSE稳定
    RCC->CR |= ((uint32_t)RCC_CR_HSEON);

    // 等待HSE启动稳定,并做超时处理
    do {
        HSEStatus = RCC->CR & RCC_CR_HSERDY;
        StartUpCounter++;
    } while ((HSEStatus == 0)
        &&(StartUpCounter !=HSE_STARTUP_TIMEOUT));

    if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
        HSEStatus = (uint32_t)0x01;
    } else {
        HSEStatus = (uint32_t)0x00;
    }
    // HSE启动成功,则继续往下处理
    if (HSEStatus == (uint32_t)0x01) {

        //-----------------------------------------------------------
        // 使能FLASH 预存取缓冲区 */
        FLASH->ACR |= FLASH_ACR_PRFTBE;

        // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
        // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
        // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
        // 0:0 < SYSCLK <= 24M
        // 1:24< SYSCLK <= 48M
        // 2:48< SYSCLK <= 72M */
        FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
        FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
        //------------------------------------------------------------

        // ② 设置AHB、APB2、APB1预分频因子
        // HCLK = SYSCLK
        RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
        //PCLK2 = HCLK
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
        //PCLK1 = HCLK/2
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

        // ③ 设置PLL时钟来源,设置PLL倍频因子,PLLCLK = HSE * 9 = 72 MHz
        RCC->CFGR &= (uint32_t)((uint32_t)
                                ~(RCC_CFGR_PLLSRC
                                | RCC_CFGR_PLLXTPRE
                                | RCC_CFGR_PLLMULL));
        RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
                                | RCC_CFGR_PLLMULL9);

        // ④ 使能 PLL
        RCC->CR |= RCC_CR_PLLON;

        // ⑤ 等待PLL稳定
        while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
        }

        // ⑥ 选择PLL作为系统时钟来源
        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
        RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;

        // ⑦ 读取时钟切换状态位,确保PLLCLK被选为系统时钟
        while ((RCC->CFGR&(uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){
        }
    } else {// 如果HSE启动失败,用户可以在这里添加错误代码出来
    }
}

标签:0000,CFGR,笔记,STM32,Mode,GPIO,uint32,RCC
From: https://www.cnblogs.com/yuknight/p/17602112.html

相关文章

  • Linux系统笔记
    Linux系统笔记Linux环境搭建以及常用命令Linux常见目录框架dev/设备文件//linux下一切皆文件bin/系统程序sbin/管理员系统程序lib/系统程序库文件etc/系统程序和大部分应用程序的全局配置文件ust/Linux常用命令打开终端:ctrl+alt+t关闭终端:ctrl+alt+q放大:ctrl+......
  • 《流畅的Python第二版》读书笔记——文本和字节序列
    引言这是《流畅的Python第二版》抢先版的读书笔记。Python版本暂时用的是python3.8。为了使开发更简单、快捷,本文使用了JupyterLab。Python3明确区分了人类可读的字符串和原始的字节序列。新内容简介新增了对emoji表示字符的描述。字符问题字符串是个简单的概念:一个字符串是一个字......
  • C和C++进阶的学习笔记总结目录
    C语言–C语言基础知识积累记录学习教程:参考C++教程网之跟我一起学Cdo{…}while(0)的用途汇总(欢迎补充)在一些Linux内核和其它的开源代码中可见到【C语言】《带你学C带你飞》,笔记:链接––C++–一张图总结GoogleC++编程规范(GoogleC++StyleGuide)C++基础学习目录总结参考:链......
  • 《深度管理》读书笔记1
    书籍信息参考:https://book.douban.com/subject/30258984/ 一 “赢得漂亮”意味着你能长时间地维持优秀的业绩,因为你拒绝屈服于严酷而招致压力的捷径,暂时将他人当成业绩的牺牲品。你需要让精力充沛、鼓足干劲的人们共同工作。你的策略的强大取决于你的团队在第一线的执行力,要......
  • [刷题笔记] Luogu P1853 投资的最大效益
    ProblemSolution刚开始看这道题的时候不自主的想到了纪念品,但其实本题和纪念品还是有区别的。纪念品规定了每次只能买一个纪念品,而本题可以买无限个纪念品需要在原本的基础上买进卖出,钱有进有出,而本题时只有进,稳赚不赔。本题和纪念品不同的第一点决定了它时完全背包,纪念品......
  • 省选前全部笔记
    观前提醒其实也不能说是笔记,以为你看看就知道了,好多更像是日记。可以试试去调错字,因为你能挑出100个我写错的字(不带夸张)主要是分享一下我当时的精神状态,希望处在低谷的oier们也不要灰心。学术内容可以略看,因为不少是扯淡。大部分英语是chinglish,图一乐就行至于我有没有入选......
  • [刷题笔记] Luogu P5662 [CSP-J2019] 纪念品
    ProblemDescription类似于炒股票,有买进有卖出,当天可以既买进又卖出无限次,现在有若干件物品,每件物品都有一个价格,每天每件物品的价格不一致,你初始有\(m\)元钱,想要通过若干次购进卖出的操作,使得\(T\)天后你手里的钱最多。要求:\(T\)天结束你手中的股票必须全部售出。Solution乍看......
  • 微信小程序学习笔记(完结)
    本笔记是小程序学习笔记,主要记录小程序の基础知识说明本笔记为观看慕课网微信小程序入门与实战-全新版、尚硅谷2021版微信小程序开发(零基础小程序开发入门到精通)这两个教学视频、并参照官方的微信开放文档记录整理而成两个教学视频主要就是是面向初学者......
  • k8s 学习笔记之 Pod——Pod 的配置
    Pod的配置先研究pod.spec.containers属性,这也是pod配置中最为关键的一项配置。[root@k8s-master01~]#kubectlexplainpod.spec.containersKIND:PodVERSION:v1RESOURCE:containers<[]Object>#数组,代表可以有多个容器FIELDS:name<string>#容器名......
  • k8s 学习笔记之 Pod——Pod 的生命周期
    Pod生命周期我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:pod创建过程运行初始化容器(initcontainer)过程运行主容器(maincontainer)容器启动后钩子(poststart)、容器终止前钩子(prestop)容器的存活性探测(livenessprobe)、就绪性探......