首页 > 其他分享 >STM32F103开发

STM32F103开发

时间:2024-11-17 16:40:24浏览次数:1  
标签:STM32F103 GPO .. 引脚 16 开发 寄存器 GPIO

本节我们将会对STM32的硬件资源进行介绍,包括如下内容:

  • 点亮LED
  • 检测按键按下和松开事件;
  • 串口;
  • 点亮128*128 TFT_LCD液晶屏;

一、点亮LED

1.1 电路原理图

LED电路原理图如下图所示:

其中:

  • LED1连接到PA8`引脚,低电平点亮;
  • LED2连接到PD2引脚,低电平点亮;

1.2 GPIO引脚介绍

STM32F103RTC6共有5组GPIO,分别为 GPIOA, GPIOB, GPIOC, GPIOD, 和 GPIOE。其中,GPIOAGPIOBGPIOCGPIOD是常用的,GPIOE只有一部分引脚在某些型号的STM32F103系列中有效。

每组GPIO通常包含16个引脚。但并非所有引脚都在所有STM32F103型号中都有效,具体取决于具体芯片封装。

  • GPIOA:16 个引脚(PA0 - PA15);
  • GPIOB:16 个引脚(PB0 - PB15
  • GPIOC:16 个引脚(PC0 - PC15
  • GPIOD:16 个引脚(PD0 - PD15);
  • GPIOE(在某些型号上有效):16个引脚(PE0 - PE15);

1.3 GPIO寄存器

STM32F103RTC6中,GPIO引脚的配置和控制是通过寄存器来实现的。每个GPIO端口(如GPIOAGPIOB 等)都有一组寄存器来控制引脚的方向、输出类型、上拉/下拉电阻、输入模式等。;

  • 两个32位配置寄存器,GPIOx_CRHGPIOx_CRL;
  • 两个32位数据寄存器,GPIOx_IDRGPIOx_ODR
  • 一个32位设置/清除寄存器,GPIOx_BSRR
  • 一个16位复位寄存器,GPIOx_BRR
  • 一个32位锁定寄存器,GPIOx_LCKR
1.3.1 端口配置低寄存器(GPIOx_CRL

GPIOx_CRL端口配置低8位寄存器(x=A~E),四位控制1个引脚,共控制8个引脚(0~7引脚);

31:28 27:24 23:20 19:16 15:12 11:8 7:4 3:0
CNF7[1:0]
MODE7[1:0]
... .... .... .... .... ..... CNF0[1:0]
MODE0[1:0]

其中:

MODE[1:0] CNF[1:0]
输入模式 0 0 0 0:模拟输入模式
0 1:浮空输入模式
1 0:上拉/下卡输入模式
1 1:保留
输出模式 0 1:最大速度10MHz
1 0:最大速度2MHz
1 1:最大速度50MHz
0 0:通用推挽输出模式
0 1:通用开漏输出模式
1 0:复用功能推挽输出模式
1 1:复用功能开漏输出模式
1.3.3 端口配置高寄存器(GPIOx_CRH

GPIOx_CRH四位控制1个引脚(x=A~E),共控制8个引脚(8~15引脚);同上不再重复介绍。

1.3.3 端口输入数据寄存器(GPIOx_IDR

GPIOx_IDR端口输入数据寄存器(x=A~E);

31~16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
保留 IDR15 .. .. .. .. .. .. .. .. .. .. .. .. .. .. IDR0

31~16位始终读0,低16位为只读,并只能以16位的形式读出。

1.3.4 端口输出数据寄存器(GPIOx_ODR

GPIOx_ODR端口输出数据寄存器(x=A~E);

31~16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
保留 ODR15 .. .. .. .. .. .. .. .. .. .. .. .. .. .. ODR0

31~16位始终读0,低16位可读可写,并只能以16位的形式操作。

1.3.5 端口设置/清除寄存器(GPIOx_BSRR

GPIOx_BSRR端口设置/清除寄存器(x=A~E);

31~16 15~0
BR15~BR0 BS15~BS0
0:对对应的ODRy位不产生影响
1:清除对应的ODRy位为0
0:对对应的ODRy位不产生影响
1:设置对应的ODRy位为1
1.3.6 端口清除寄存器(GPIOx_BRR

GPIOx_BRR端口清除寄存器(x=A~E);

31~16 15~0
保留 BR15~BR0
0:对对应的ODRy位不产生影响
1:清除对应的ODRy位为1

1.4 代码实现

1.4.1 GPIO初始化函数
 /******************************************************** ********************
* File Name          : gpio.c
* Author             : Zhengyang
* Description        : 初始化GPIO口
					   portx:端口号PORTA~E
					   pinx:引脚号PORT0~15
					   gpio_cfg:输入输出模式配置
					   bit:输出电平设置 高:HIGH  低:LOW
********************************************************************************/ 
void gpio_init(PORTx_PINx portx_pinx,GPIO_CFG gpio_cfg,BIT_ACTION bit)
{
    GPIO_TypeDef *GPIO;
	u8 portx = portx_pinx/16;                 //获取端口号
  	u8 pinx = portx_pinx%16;	        	  //获取引脚号

   	if(portx==0)
	     GPIO=GPIOA;
    else if(portx==1)
		 GPIO=GPIOB;
    else if(portx==2)
		 GPIO=GPIOC;
    else if(portx==3)
	     GPIO=GPIOD;
    else
	     GPIO=GPIOE;

	RCC->APB2ENR|=1<<(portx+2);	                   //外设时钟使能

	if(pinx<8)
	{
	     GPIO->CRL &=~(0x0F<<(pinx*4));             //该引脚模式配置四位清零
	     GPIO->CRL|=gpio_cfg<<(4*pinx);             //端口配置寄存器CRL
	}
	else if(pinx>=8)    
	{
	     GPIO->CRH &=~(0x0F<<((pinx-8)*4));             //该引脚模式配置四位清零
	     GPIO->CRH|=gpio_cfg<<(4*(pinx-8));             //端口配置寄存器CRH
	}
	if((gpio_cfg&0x03)!=0x00)             				                //输出
	{
	 		 if(pinx<8)
			    GPIO->ODR|=bit<<pinx;		        //端口数据输出寄存器ODR
		     else								
				GPIO->ODR|=bit<<pinx;	   	        //端口数据输出寄存器	 
	}
} 

这里PORTx_PINxGPIO_CFGBIT_ACTION均是枚举类型;

/************************************* 端口配置 ************************************************************/
typedef  enum   			    //宏定义端口配置
{
	//这里的值不能改!!!
    GPI                     = 0x00,                       //定义管脚输入方向    
    GPO_SpeedMax_10         = 0x01,                       //定义管脚输出方向   最大速度10MHZ
	GPO_SpeedMax_2          = 0x02,                       //定义管脚输出方向   最大速度2MHZ
    GPO_SpeedMax_50         = 0x03,                       //定义管脚输出方向   最大速度50MHZ
	//输入模式可用
    GPI_DOWN    = 0x08|GPI,                       //输入下拉        PxODR需配置为0          
    GPI_UP      = 0x08|GPI,                       //输入上拉        PxODR需配置为1       		 复用功能时一般采用
    GPI_ANALOG  = 0x00|GPI,                       //模拟输入
    GPI_FLOAT   = 0x04|GPI ,                      //浮空输入
   
   //输出模式不能用
	GPO_PUSH_PULL     = 0x00,                     //通用推挽输出
	GPO_OPEN_DRAIN    = 0x04,                     //通用开漏输出
   	GPO_MULPUSH_PULL  = 0x08,                     //复用推挽输出
	GPO_MULOPEN_DRAIN = 0x0C,                     //复用开漏输出

	//输出模式可用
	GPO_PUSH_PULL_50         =  GPO_SpeedMax_50| GPO_PUSH_PULL,                 //通用推挽输出,最大速度50MHZ   通用输出一般设置
	GPO_PUSH_PULL_10         =  GPO_SpeedMax_10| GPO_PUSH_PULL,                 //通用推挽输出,最大速度10MHZ   
	GPO_PUSH_PULL_2          =  GPO_SpeedMax_2 | GPO_PUSH_PULL,                 //通用推挽输出,最大速度2MHZ
	GPO_MULPUSH_PULL_2       =  GPO_SpeedMax_2| GPO_MULPUSH_PULL,  				//复用推挽输出,最大速度2MHZ
	GPO_MULPUSH_PULL_10      =  GPO_SpeedMax_10| GPO_MULPUSH_PULL, 				//复用推挽输出,最大速度10MHZ
	GPO_MULPUSH_PULL_50      =  GPO_SpeedMax_50| GPO_MULPUSH_PULL               //复用推挽输出,最大速度50MHZ   复用功能 输出模式一般采用这样设置
}GPIO_CFG;

/***************************************** 宏定义引脚号 *************************************************************/ 
typedef enum 
{
   PA0=0,
   PA1=1,
   PA2=2,
   PA3=3,
   PA4=4,
   PA5=5,
   ......
   PE13=77,
   PE14=78,
   PE15=79
 } PORTx_PINx;

typedef enum   					    //外部端口输出电平
{ 
  LOW  = 0,
  HIGH = 1
} BIT_ACTION;

1.4.2 PXout/PxIn

定义GPIO输入输出宏:

/********************** 位运算符优先级低于算术运算符 <<  &  | ~  所以位运算符必须加括号	 ***********************/
#define  Bit_Band(Addr,Bit_Num)     *((volatile unsigned long *)((Addr&0xF0000000)+0x02000000+((Addr&0xfffff)<<5)+(Bit_Num<<2)))


/********************************************** I/O 地址映射 **************************************************/
#define GPIOA_IDR         (GPIOA_BASE + 0x08)       //0x40010808
#define GPIOA_ODR         (GPIOA_BASE + 0x0C) 		//0x4001080C
#define GPIOB_IDR         (GPIOB_BASE + 0x08) 		//0x40010C08
#define GPIOB_ODR         (GPIOB_BASE + 0x0C)  		//0x40010C0C
#define GPIOC_IDR         (GPIOC_BASE + 0x08) 		//0x40011008
#define GPIOC_ODR         (GPIOC_BASE + 0x0C) 		//0x4001100C
#define GPIOD_IDR         (GPIOD_BASE + 0x08) 		//0x40011408
#define GPIOD_ODR         (GPIOD_BASE + 0x0C) 		//0x4001180C
#define GPIOE_IDR         (GPIOE_BASE + 0x08) 		//0x40011808
#define GPIOE_ODR         (GPIOE_BASE + 0x0C)  		//0x4001180C


/********************************************** 宏定义输入输出	 ************************************************/
#define  PAout(Bit_Num)		                    Bit_Band(GPIOA_ODR,Bit_Num)	  //输出  1位输出
#define  PAin(Bit_Num)							Bit_Band(GPIOA_IDR,Bit_Num)	  //输入
#define  PBout(Bit_Num)		                    Bit_Band(GPIOB_ODR,Bit_Num)
#define  PBin(Bit_Num)							Bit_Band(GPIOB_IDR,Bit_Num)
#define  PCout(Bit_Num)		                    Bit_Band(GPIOC_ODR,Bit_Num)
#define  PCin(Bit_Num)							Bit_Band(GPIOC_IDR,Bit_Num)
#define  PDout(Bit_Num)		                    Bit_Band(GPIOD_ODR,Bit_Num)
#define  PDin(Bit_Num)							Bit_Band(GPIOD_IDR,Bit_Num)
#define  PEout(Bit_Num)		                    Bit_Band(GPIOE_ODR,Bit_Num)
#define  PEout(Bit_Num)		                    Bit_Band(GPIOE_ODR,Bit_Num)

这里利用到了STM32的位段功能,Cortex-M3储存器包含两个位段(bit-band)区,将别名寄存器的每个字映射到位段寄存器的一个位。

映射公式(外设寄存器和SRAM可被映射):

\[bit\_word\_addr = bit\_band\_base + (byte\_offset \times 32) +(bit\_number * 4) \]

其中:

  • bit_word_addr:别名寄存器中的地址映射到某一个目标位;
  • bit_band_base:别名区的起始地址;
  • byte_offset:目标位的字节在位段的序号;
  • bit_number:目标位所在位置(0~31);

例如:SRAM中某一变量地址为0x20000300字节中的位2;

\[0x22006008 = 0x22000000 + ((0x20000300 - 0x20000000) \times 8 + 2) \times 4% \]

1.4.3 点亮LED

如需点亮LED,我们只需要在main函数添加如下代码:

gpio_init(PD2,GPO_SpeedMax_50,HIGH);	             // PD2接入LED2 
gpio_init(PA8,GPO_SpeedMax_50,HIGH);                 // PA8接入LED1 
while(1)
{	    
	PAout(8) = 0;
	PDout(2) = 1;
	delay_ms(1500);
	PAout(8) = 1;
	PDout(2) = 0;
	delay_ms(1500);
}		 

这里我们简单介绍一下PAoutPDout宏的实现;

1.4.3 烧录

编译完成后通过ISP烧录到开发版,我们可以看到LED1LED2交替点亮,时间间隔为1.5s

二、检测按键

三、串口

三、点亮TFT

四、源码下载

源码下载路径:

标签:STM32F103,GPO,..,引脚,16,开发,寄存器,GPIO
From: https://www.cnblogs.com/zyly/p/18550731

相关文章

  • H5开发类似rpx实现方法
    1、postcss-px2rem-exclude(推荐)||postcss-px2rem(不推荐);2、rem.js第一步:npminstallpostcss-px2rem-exclude--save//找到:postcss.config.js//在plugins新增'postcss-px2rem-exclude':{remUnit:37.5,//1rem等于多少px,此为转换单位(不重要)exclude:/no......
  • 使用 ESP-IDF 进行esp32-c3开发第二步:Linux 和 macOS 平台工具链的标准设置
    先上文档,后面实践Linux和macOS平台工具链的标准设置[English]详细安装步骤请根据下方详细步骤,完成安装过程。设置开发环境以下是为ESP32-C3设置ESP-IDF的具体步骤。第一步:安装准备第二步:获取ESP-IDF第三步:设置工具第四步:设置环境变量第五步:开始使用ES......
  • 代码随想录:开发商购买土地
    代码随想录:开发商购买土地纯铸币题目浪费时间,两个include记一下#include<climits>//INT_MAX#include<cmath>//min#include<iostream>#include<vector>#include<climits>#include<cmath>usingnamespacestd;intmain(){inta,b;cin>......
  • 从 AI 大模型的定义、应用场景、优势以及挑战等方面,探讨 AI 是如何重塑软件开发的各个
    随着人工智能技术的迅猛发展,特别是大规模预训练模型(大模型)的兴起,软件开发行业正经历着前所未有的变革。大模型是指那些参数量巨大、能够处理复杂任务的人工智能模型,如GPT-3、BERT等。这些模型不仅在自然语言处理领域取得了突破性进展,还在计算机视觉、语音识别等多个领域展现出......
  • Cesium初级开发教程之十五:抗锯齿和分辨率优化
    一、效果图 二、代码//抗锯齿viewer.scene.fxaa=true;viewer.scene.postProcessStages.fxaa.enabled=trueviewer._cesiumWidget._supportsImageRenderingPixelated=Cesium.FeatureDetection.supportsImageRenderingPixelated()vi......
  • STM32F103简介
    自从大学毕业之后,已经很久没有接触STM32控制器了,最近打算学习一下LVGL,控制芯片计划使用STM32,因此这里我们会简单介绍有关STM32的知识。一、STM32F103RTC6介绍1.1命名规则我从网上买了一块STM32F103RTC6开发板,STM32F103RCT6各个字段的含义:STM32(芯片系列):STM32代表ARMCortex-......
  • 如何使用uni-app在开发app中引入本地图片
    在正式开前先给小伙伴们一个引入图片万能公式importimgfrom"@/assets/image/tupian.png"//图片路径众所周知当我们在使用uni-app去开发应用时,不可避免的要去处理各平台的兼容问题,这里我们就展开小程序、H5、App如何引入本地资源展开,废话不多数,上代码!一、在Vue2中由于......
  • 参与 2024 第四季度官方 Flutter 开发者调查
    Flutter3.24和Dart3.5稳定版发布已有三月之久,今年最后一次开发者调查也如约而至!自Flutter3.24正式发布以来,团队通过一系列补丁更新不断优化平台稳定性和开发体验,最新稳定版本为v3.24.5。这些更新涵盖了性能提升、工具改进以及多平台问题修复,例如改进iOS和Android......
  • 计算机毕业设计-基于Java+Springboot架构的电影推荐系统项目开发实战(附源码+论文)
    大家好!我是职场程序猿,感谢您阅读本文,欢迎一键三连哦。......
  • 计算机毕业设计-基于Java+Springboot架构的兴顺物流管理系统项目开发实战(附源码+论文
    大家好!我是职场程序猿,感谢您阅读本文,欢迎一键三连哦。......