STM32

GPIO通用输入输出口

GPIO:8种输入输出模式

浮空输入可读取引脚电平,若引脚悬空,电平不确定
上拉输入可读取引脚电平,内部接上拉电阻,悬空时默认为高电平
下拉输入可读取引脚电平,内部接下拉电阻,悬空时默认为低电平
模拟输入GPIO无效,引脚直接接入内部ADC
开漏输出可输出引脚电平,高电平为高阻态,低电平接VSS
推挽输出可输出引脚电平,高电平接VDD,低电平接VSS
复用开漏输出由片上外设提供,高电平为高阻态,低电平接VSS
复用推挽输出由片上外设提供,高电平接VDD,低电平接VSS

GPIO:  引脚电平在0-3.3v之间,部分可以容忍5v的电平

GPIO:在输出模式下可以控制端口输出高低电平,驱动外部设备

GPIO:输入模式下可以读取端口高低电平和电压,获取外部输入的数据


GPIO:函数

复位GPIOvoid GPIO_DeInit(GPIO_TypeDef* GPIOx);
复位AFIOvoid GPIO_AFIODeInit(void);
初始化GPIOvoid GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
结构体初始化void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
获取输入数据寄存器中的一位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);
把指定的端口设置为高电平void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
GPIO 把指定的端口设置为低电平void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
GPIO写入数据位,根据第三个参数的值设置指定的端口void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
第一个参数指定端口,第二个参数可以同时对16个端口进行写入操作void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

RCC:时钟

开启AHB外设时钟控制void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
开启RCCAPB2外设时钟控制void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
开启RCCAPB1外设时钟控制void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);


GPIO外设控制


1:第一步开启RCCAPB2外设时钟控制

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //开启GPIOA的时钟

2: 初始化GPIO结构体

GPIO_InitTypeDef GPIO_InitStructure;	                //初始化GPIO结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		//GPIO模式,赋值为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				//GPIO引脚,赋值为第0号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//GPIO速度,赋值为50MHz

#if  
GPIO8种输入输出模式
typedef enum
{
  GPIO_Mode_AIN = 0x0,          // 模拟输入
  GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
  GPIO_Mode_IPD = 0x28,         //上拉输入
  GPIO_Mode_IPU = 0x48,         //下拉输入
  GPIO_Mode_Out_OD = 0x14,      //开漏输出
  GPIO_Mode_Out_PP = 0x10,      //推挽输出
  GPIO_Mode_AF_OD = 0x1C,       //复用开漏输出
  GPIO_Mode_AF_PP = 0x18        //复用推挽输出
}GPIOMode_TypeDef;

// GPIO的引脚每一个GPIO口有16个引脚
#define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
#define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */

// GPIO输入输出的频率
typedef enum
{ 
  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

#endif

3:初始化GPIO

GPIO_Init(GPIOA, &GPIO_InitStructure);	

GPIO:ResetBits控制灯的闪烁

接线图工程模版

#include "stm32f10x.h"    // Device header
#include "Delay.h"
    	     // 操作GPIO 1: 使用rcc开启gpio时钟
		     // 使用GPIO_Init函数初始化GPIO
			 // 使用输入或输出函数控制GPIO口
int main(void){
	  // 开启时钟
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	  // GPIO的结构体
	  GPIO_InitTypeDef GPIO_InitStructure;
	  // 选择输出模式为推挽输出
      // 选择输出模式为推挽输出PP表示的是推挽输出模式,OD表示开漏输出模式
	  // 推挽输出高电平和低电平均有输出能力,开漏输出自由在低电平的情况下才有驱动能力
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	  // 选择输出的引脚
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	  // 输出速度
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  // GPIO初始化结构体的地址放到GPIO——Init的第二个参数
	  GPIO_Init(GPIOA,&GPIO_InitStructure);
	  // GPIO设置A0口的灯亮,最后一个参数Bit_RESET表示的是清除端口的值为0,清除端口的值为1
	  GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);// Bit_RESET时LED灯是点亮状态,当为Bit_SET时LED灯是熄灭状态
    while(1){
        // 实现led灯光闪烁的功能需要在主循环中写上点亮led灯熄灭led灯光的操作并在while中循环
			  GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
			  Delay_ms(500);
			  // 添加延时函数进行延时
			  GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
			  Delay_ms(500);
          /*   使用GPIO点亮led灯
               GPIO_ResetBits(GPIOA,GPIO_Pin_0);
			  Delay_ms(500);
			  GPIO_SetBits(GPIOA,GPIO_Pin_0);
			  Delay_ms(500);
          */
		}

}

GPIO:控制LED灯闪烁

#include "stm32f10x.h"    // Device header
#include "Delay.h"
    	 // 操作GPIO 1: 使用rcc开启gpio时钟
		   // 使用GPIO_Init函数初始化GPIO
			 // 使用输入或输出函数控制GPIO口
int main(void){
	  // 开启时钟
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	  // GPIO的结构体
	  GPIO_InitTypeDef GPIO_InitStructure;
	  // 选择输出模式为推挽输出
      // 选择输出模式为推挽输出PP表示的是推挽输出模式,OD表示开漏输出模式
	  // 推挽输出高电平和低电平均有输出能力,开漏输出自由在低电平的情况下才有驱动能力
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	  // 选择输出的引脚
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	  // 输出速度
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  // GPIO初始化结构体的地址放到GPIO——Init的第二个参数
	  GPIO_Init(GPIOA,&GPIO_InitStructure);
	  // GPIO设置A0口的灯亮,最后一个参数Bit_RESET表示的是清除端口的值为0,清除端口的值为1
	  GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);// Bit_RESET时LED灯是点亮状态,当为Bit_SET时LED灯是熄灭状态
    while(1){
        // 实现led灯光闪烁的功能需要在主循环中写上点亮led灯熄灭led灯光的操作并在while中循环
			  GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
			  Delay_ms(500);
			  // 添加延时函数进行延时
			  GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
			  Delay_ms(500);
          /*   使用GPIO点亮led灯
               GPIO_ResetBits(GPIOA,GPIO_Pin_0);
			  Delay_ms(500);
			  GPIO_SetBits(GPIOA,GPIO_Pin_0);
			  Delay_ms(500);
          */
		}

}

GPIO:控制蜂鸣器发声

#include "stm32f10x.h"    // Device header
#include "Delay.h"
 /*
		 1: 操作GPIO 1: 使用rcc开启gpio时钟
		 2: 使用GPIO_Init函数初始化GPIO
		 3: 使用输入或输出函数控制GPIO口
 */   	 
int main(void){
	  // 开启GPIOA时钟,该程序连接的是GPIOA的端口
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	  // GPIO的结构体
	  GPIO_InitTypeDef GPIO_InitStructure;
	  // 选择输出模式为推挽输出PP表示的是推挽输出模式,OD表示开漏输出模式
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	  // 选择输出的引脚,GPIO_Pin_All将16个端口都设置为推挽输出模式
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	  // 输出速度
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  // GPIO初始化结构体的地址放到GPIO——Init的第二个参数
	  GPIO_Init(GPIOB,&GPIO_InitStructure); 
    while(1){
			GPIO_ResetBits(GPIOB,GPIO_Pin_12);
			Delay_ms(100);
			GPIO_SetBits(GPIOB,GPIO_Pin_12);
			Delay_ms(100);
			GPIO_ResetBits(GPIOB,GPIO_Pin_12);
			Delay_ms(100);
			GPIO_SetBits(GPIOB,GPIO_Pin_12);
			Delay_ms(700);
		}

}

STM32库函数使用方式

第一种方式是,打开头文件,拉到最下面,查看有哪些函数,然后查看函数的定义函数的使用方法是

第二种方式,查看库函数用户手册,所有函数的介绍个使用方法

第三种方式,最后一种方式是百度,借助别人的代码进行使用


GPIO:LED流水灯

步骤:1:开启RCCAPB2外设时钟控制

           2:初始化GPIO结构体

           3: 初始化GPIO

接线原理图

代码实现

#include "stm32f10x.h"    // Device header
#include "Delay.h"
 /*
		 1: 操作GPIO 1: 使用rcc开启gpio时钟
		 2: 使用GPIO_Init函数初始化GPIO
		 3: 使用输入或输出函数控制GPIO口
 */   

uint16_t arr[16] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080};

int main(void){
	  // 函数的声明
	  void LED_Run(void);
	  void LED_All(void);
	
	  // 开启GPIOA时钟,该程序连接的是GPIOA的端口
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	  // GPIO的结构体
	  GPIO_InitTypeDef GPIO_InitStructure;
	  // 选择输出模式为推挽输出PP表示的是推挽输出模式,OD表示开漏输出模式
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	  // 选择输出的引脚,GPIO_Pin_All将16个端口都设置为推挽输出模式
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
	  // 输出速度
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  // GPIO初始化结构体的地址放到GPIO——Init的第二个参数
	  GPIO_Init(GPIOA,&GPIO_InitStructure); 
	
    while(1){
			//LED_Run();
			LED_All();
		}

}
void LED_Run(void){
           //控制A号引脚,对引脚的位置进行按位取反
			GPIO_Write(GPIOA,~0x0001); // 0000 0000 0000 0001 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0002); // 0000 0000 0000 0010 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0004); // 0000 0000 0000 0100 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0008); // 0000 0000 0000 1000 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0010); // 0000 0000 0001 0000 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0020); // 0000 0000 0010 0000 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0040); // 0000 0000 0100 0000 二进制转换为16进制的写法
		  Delay_ms(500);
			GPIO_Write(GPIOA,~0x0080); // 0000 0000 1000 0000 二进制转换为16进制的写法
		  Delay_ms(500);
}
void LED_All(void){
      // for循环
	  int len = sizeof(arr)/sizeof(arr[0]);
	  int i = 0;
	  for(i = 0; i< len; i++){
		   	GPIO_Write(GPIOA,~arr[i]); // 0000 0000 0000 0001 二进制转换为16进制的写法
			  Delay_ms(500);
		}
}

GPIO:按键控制LED亮灭

步骤:1:创建LED.C文件和LED.H文件

           2:  创建KEY.H文件和KEY.C文件

           3:开起RCC外设时钟控制

           4: 分别初始化GPIO

           5: 编写实现功能函数

接线图

KEY.C文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void Key_Init(void)
{
	// RCCAPB2外设时钟控制,开启GPIOB的外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	//GPIO初始化
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);					
}


uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;		                                 //定义变量,默认键码值为0
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)			//读PB1输入寄存器的状态,如果为0,则代表按键1按下
	{
		
		Delay_ms(20);											//延时消抖
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);	//等待按键松手
		Delay_ms(20);											//延时消抖
		KeyNum = 1;												//置键码为1
	}
	
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)			//读PB11输入寄存器的状态,如果为0,则代表按键2按下
	{
		Delay_ms(20);											//延时消抖
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);	//等待按键松手
		Delay_ms(20);											//延时消抖
		KeyNum = 2;												//置键码为2
	}
	
	return KeyNum;			//返回键码值,如果没有按键按下,所有if都不成立,则键码为默认值0
}

KEY.H文件

#ifndef __KEY_H__
#define __KEY_H__
void Key_Init(void);
uint8_t Key_GetNum(void);

#endif

LED.C文件

#include "stm32f10x.h"                  // Device header

/**
  * 函    数:LED初始化
  * 参    数:无
  * 返 回 值:无
  */
void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);						   //将PA1和PA2引脚初始化为推挽输出
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);				 //设置PA1和PA2引脚为高电平
}

/**
  * 函    数:LED1开启
  * 参    数:无
  * 返 回 值:无
  */
void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);		//设置PA1引脚为低电平
}

/**
  * 函    数:LED1关闭
  * 参    数:无
  * 返 回 值:无
  */
void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);		//设置PA1引脚为高电平
}

/**
  * 函    数:LED1状态翻转
  * 参    数:无
  * 返 回 值:无
  */
void LED1_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)		//获取输出寄存器的状态,如果当前引脚输出低电平
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);					//则设置PA1引脚为高电平
	}
	else													//否则,即当前引脚输出高电平
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);					//则设置PA1引脚为低电平
	}
}

/**
  * 函    数:LED2开启
  * 参    数:无
  * 返 回 值:无
  */
void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);		//设置PA2引脚为低电平
}

/**
  * 函    数:LED2关闭
  * 参    数:无
  * 返 回 值:无
  */
void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);		//设置PA2引脚为高电平
}

/**
  * 函    数:LED2状态翻转
  * 参    数:无
  * 返 回 值:无
  */
void LED2_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)		//获取输出寄存器的状态,如果当前引脚输出低电平
	{                                                  
		GPIO_SetBits(GPIOA, GPIO_Pin_2);               		  //则设置PA2引脚为高电平
	}                                                  
	else                                               		//否则,即当前引脚输出高电平
	{                                                  
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);             		  //则设置PA2引脚为低电平
	}
}

LED.H文件

#ifndef __LED_H
#define __LED_H

void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED1_Turn(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED2_Turn(void);

#endif

main.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"

uint8_t KeyNum;		                    //定义用于接收按键键码的变量

int main(void)
{

	LED_Init();	                         //LED初始化
	Key_Init();		                     //按键初始化
	
	while (1)
	{
		KeyNum = Key_GetNum();		            //获取按键键码
		 
		if (KeyNum == 1)			            //按键1按下
		{
			LED1_Turn();			            //LED1翻转
		}
		
		if (KeyNum == 2)			            //按键2按下
		{
			LED2_Turn();			            //LED2翻转
		}
	}
}

GPIO:光敏传感器控制蜂鸣器

步骤:1:分别初始化蜂鸣器和光敏电阻的GPIO,并开启RCC外设手时钟控制的时钟

           2:编写函数实现在光线较暗的情况下蜂鸣器发出声音

接线图

BUZZER.C和BUZZER.H

Buzzzer.c

#include "stm32f10x.h"                  // Device header
void Buzzer_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOA的时钟
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);						//将PA1和PA2引脚初始化为推挽输出
	
	/*设置GPIO初始化后的默认电平*/
	GPIO_SetBits(GPIOB, GPIO_Pin_12);				//设置PA1和PA2引脚为高电平
}

void Buzzer_ON(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_12);		//设置PA1引脚为低电平
}


void Buzzer_OFF(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_12);		//设置PA1引脚为高电平
}


void Buzzer_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12) == 0)		//获取输出寄存器的状态,如果当前引脚输出低电平
	{
		GPIO_SetBits(GPIOB, GPIO_Pin_12);					//则设置PA1引脚为高电平
	}
	else													              //否则,即当前引脚输出高电平
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_12);					//则设置PA1引脚为低电平
	}
}



  Buzzer.h

#ifndef __BUZZER_H__
#define __BUZZER_H__

void Buzzer_Init(void);
void Buzzer_ON(void);
void Buzzer_OFF(void);
void Buzzer_Turn(void);



#endif

LightSensor.c 和 LightSensor.h

LightSensor.c

#include "stm32f10x.h"                  // Device header

void LightSensor_Init(void){
    // 初始化程序开启GPIO
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOB, &GPIO_InitStructure);						
		GPIO_SetBits(GPIOB, GPIO_Pin_13);				

}

// 编写返回端口值的函数
uint8_t LightSensor_Get(void){
			return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
	  
}

LightSensor.h

#ifndef __LIGHT_SENSOR_H__
#define __LIGHT_SENSOR_H__

void LightSensor_Init(void);
uint8_t LightSensor_Get(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"




int main(void)
{
  
	// 初始化蜂鸣器
	Buzzer_Init();
	// 初始化光敏传感器
	LightSensor_Init();
	while (1)
	{
	 if(LightSensor_Get() == 1){ // 光线比较暗的情况下
	         Buzzer_ON(); // 蜂鸣器鸣叫
	 }else{
					Buzzer_OFF();
	 }

	}
}

EXTI中断

中断的定义:


在主程序运行的过程中,出现特定的中断触发条件(也就是中断源)使CPU暂停当前正在运行的程序转而去处理中断程序,处理完成后又返回之前暂停的程序继续执行

中断的优先等级,当有多个中断源同时申请中断时,CPU会根据当前中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。

中断嵌套:当一个中断程序正在运行时,又有一个更紧急优先级更高的中断源申请中断,GPU再次暂停当前的中断程序,转而去处理新的中断程序,处理完成后依次进行返回。

中断的执行流程


EXTI:外部中断函数

重定义初始化,恢复默认状态void EXTI_DeInit(void); 
中断初始化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);

AFIO:中断引脚选择和复用功能引脚重映射

AFIO函数

复位AFIO的外设void GPIO_AFIODeInit(void);
锁定GPIO配置void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
AFIO事件输出配置(使用不多)void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
AFIO的事件输出功能,使用不多void GPIO_EventOutputCmd(FunctionalState NewState);
配置引脚重映射,第一个是重映射的方式,第二个参数是新的状态void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
配置AFIO的数据选择器,选择中断引脚void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
和以太网有关void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

1:AFIO中断引脚选择:是一个中断引脚选择器可以在前面GPIO外设的16个引脚中选择一个连接到EXTI边沿检测及控制中所以

2:相同的Pin不能同时触发中断,因为PA0,PB0,PC0通过AFIO选择后只有其中一个可以连接到EXTI的通道0上,PB1,PC1等也只有一个可以接入EXTI上

复用功能引脚重映射


NVIC:嵌套中断向量控制器->用于统一分配中断优先级和管理中断

NVIC函数:

选择中断分组,参数为中断分组的方式void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);   
根据结构体里面指定的参数初始化NVICvoid 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的基本结构

NVIC优先级

def : nvic的优先级可以由优先级寄存器的4为决定,可以对这4位进行切分,分为高N为的抢占式优先级和低n位的响应式优先级(4-n),抢占式优先级可以嵌套中断,响应式优先级高的可以优先排队,抢占式优先级和响应式优先级相同的可以按照中断号排队。

分组方式抢占式优先级响应式优先级
00 取值为04取值为0-15
11取值为0-13取值为0-7
22取值为0-32取值为0-3
33取值为0-71取值为0-1
44取值为0-150 取值为0

响应式优先级:也可以称为插队式优先级哪个优先级高优先处理哪个

抢占式优先级:优先级高的可以优先被处理,相当于CPU可以暂时中断当前处理的程序,优先处理优先级更高的程序,该程序执行完成后再执行原先没有执行完毕的程序,也可以称之为嵌入式中断优先级


EXTI:对射式红外传感器统计次数

步骤:

1: 开启RCCAPB和RCCAFIO中断引脚控制

2: 配置GPIO输入输出

3: 配置EXTI外部中断

4: 配置NVIC(嵌套中断向量控制器)

接线图:

CounterSensor.c

#include "stm32f10x.h"   

uint16_t CountSensor_Count;
void CountSensor_Init(void){
    // 开启RCC时钟
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	  // 配置AFIO中断引脚选择
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	  // 初始化GPIO
	  GPIO_InitTypeDef GPIO_InitStructure;
	  // 引出GPIO参数
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_14 ;
	  GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
	  // 初始化GPIO
	  GPIO_Init(GPIOB,&GPIO_InitStructure);
	  
	  // AFIO中断引脚选择
	  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
	  // 初始化中断引脚选择
	  EXTI_InitTypeDef EXTI_InitStructure;
	  EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
	  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	  EXTI_Init(&EXTI_InitStructure);
		
// NVIC中断分组,配置抢占式优先级和响应式优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// NVIC配置
// 初始化NVIC结构体
NVIC_InitTypeDef NVIC_InitStructure;
// 将NVIC的结构体全都引出来
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;                   // 配置NVIC中断线
    NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE ;                            //使能NVIC中断线
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1 ;                  // 配置NVIC的抢占式优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		                   // 配置NVIC的响应式优先级
}
// 获取传感器计数的值
uint16_t CountSensor_Get(void){ 
    return CountSensor_Count;
}
//编写中断函数
void EXTI15_10_IRQHandler(void){
    if(EXTI_GetITStatus(EXTI_Line14) == SET){                           // 判断是外部中断14号线发生中断
		    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) == 0){
				     CountSensor_Count ++;                              // 每次触发一次中断自动增加一次
				}
				// 清除中断标志位
				EXTI_ClearITPendingBit(EXTI_Line14);
		}
}






CounterSensor.h

#ifndef __COUNT_SENSOR_H__
#define __COUNT_SENSOR_H__
void CountSensor_Init(void);
void EXTI15_10_IRQHandler(void);
uint16_t CountSensor_Get(void);
#endif

KEY.C

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

// 按键初始化
void Key_Init(void){
   // 开启RCCAPB外设时钟控制
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	 // 初始化GPIO
	 GPIO_InitTypeDef GPIO_InitStructure;
	 //配置GPIO输入输出模式
	 GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU ;
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	 GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
	 // 初始化GPIO
	 GPIO_Init(GPIOB,&GPIO_InitStructure);
}
// 按键控制
uint8_t Key_GetNum(void){
    uint8_t KeyNum = 0;
	  if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0){
		    // 延时消除按键的抖动
			  Delay_ms(20);
			  while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);
			  Delay_ms(20);
			  KeyNum =1;
		}
	  if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0){
		     Delay_ms(20);
			   while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0);
			   Delay_ms(20);
			   KeyNum =1;
		}
		return KeyNum;
	
}

KEY.H

#ifndef __KEY_H__
#define __KEY_H__
void Key_Init(void);
uint8_t Key_GetNum(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CounterSensor.h"

int main(void)
{
	// 模块初始化
	OLED_Init();
	CountSensor_Init();
	// 显示静态字符串
	OLED_ShowString(1,1,"Count:");
	

	while (1)
	{
	  OLED_ShowNum(1,7,CountSensor_Get(),5);
	}
	
}

EXTI:外部中断旋转编码器计次

旋转编码器简介

旋转编码器原理:输出一个正交波形,两个波形之间相差的角度为90度,识别编码器是正向选装还是反向旋转。

旋转编码器的硬件电路

接线图


步骤:

1:RCC开启APB2与AFIO时钟

2:开启GPIO

3:配置外部中断EXTI

4:配置NVIC

5:使能NVIC

Encoder.c 代码

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void Encoder_Init(void){
	  // 开启GPIO和AFIO的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	  // 开启GPIO时钟
	  GPIO_InitTypeDef GPIO_InitStructure;
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1 ;
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	  // 配置中断引脚
	  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;
	  
	  // 配置NVIC中断引脚控制
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置中断分组
	  NVIC_InitTypeDef NVIC_InitStructure;
	  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);
		
		

}
// 使用中间变量对选装编码器的计次进行初始化
int16_t Encoder_Get(void){
    int16_t temp;
	  temp = Encoder_Count;
	  Encoder_Count = 0;
	  return temp;
 
}
// 第一个中断
void EXTI0_IRQHandler(void){
	//判断中断是否发生
	if(EXTI_GetITStatus(EXTI_Line0) == SET){
	   		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)		//PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
			{
				Encoder_Count --;					//此方向定义为反转,计数变量自减
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line0);			//清除外部中断0号线的中断标志位
													//中断标志位必须清除
													//否则中断将连续不断地触发,导致主程序卡死
	}
	
}
void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line1) == SET)		//判断是否是外部中断1号线触发的中断
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)		//PB1的下降沿触发中断,此时检测另一相PB0的电平,目的是判断旋转方向
			{
				Encoder_Count ++;					//此方向定义为正转,计数变量自增
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line1);			//清除外部中断1号线的中断标志位
													//中断标志位必须清除
													//否则中断将连续不断地触发,导致主程序卡死
	}
}





Encoder.h代码

#ifndef  __ENCODER_H__
#define  __ENCODER_H__
void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif

main.c代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"

int16_t Num;			//定义待被旋转编码器调节的变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	Encoder_Init();		//旋转编码器初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Num:");			//1行1列显示字符串Num:
	
	while (1)
	{
		Num += Encoder_Get();				//获取自上此调用此函数后,旋转编码器的增量值,并将增量值加到Num上
		OLED_ShowSignedNum(1, 5, Num, 5);	//显示Num
	}
}

编译后没有发生错误


TIM定时器

定时器基本概念:

定时器是计算机系统中的一种重要的计时和事件触发机制。它是一种硬件或软件组件,用于按照预定的时间间隔执行任务、触发事件或生成中断。

定时器的主要功能包括:

1. 计时功能:定时器可以通过内部或外部的时钟源来测量时间间隔。它可以提供毫秒、微秒、纳秒等不同精度的计时。

2. 事件触发功能:定时器可以设置一个固定的时间间隔,当时间间隔到达时,就会触发预先定义的事件,例如发送一个中断信号、执行特定的任务或调用一个回调函数。

3. 周期性执行任务:定时器可以反复执行同一个任务,例如定期执行一个程序或周期性地发送数据。这对于需要按固定时间间隔进行重复操作的应用程序非常有用。

4. 超时检测:定时器可以用于超时检测,例如在网络通信中,可以设置一个定时器来检测数据包是否在预定的时间内到达,如果没有到达,则可以重新发送数据包或采取其他应对措施。

5. 节能功能:在一些移动设备和嵌入式系统中,定时器可以用于管理功耗。通过定时器,设备可以在空闲或非活动状态下进入省电模式,并在预定的时间间隔后自动唤醒。

定时器可以由硬件实现,如专用的定时器芯片或计时器模块,也可以由操作系统或编程语言提供的定时器库函数进行软件实现。

总之,定时器在计算机系统中扮演着重要的角色,用于计时、事件触发、周期性执行任务和超时检测等应用。它们在各个领域中都有广泛的应用,包括操作系统、通信、网络、嵌入式系统、游戏开发等。

定时器的基本类型

基本定时器框图

基本定时器的理解

通用定时器程序框图

....

定时器的基本结构

 计数器的计数频率公式:

计数器计数频率 : ck_cnt = ck-psc /(psc + 1)

计数器溢出频率: ck-cnt_ov = ck-psc /(psc + 1) / (arr + 1)


定时器:TIM编码器接口

def:编码器接口定义

1: 编码器接口可以接收增量(正交)编码器信号,根据编码器产生的正交脉冲信号自动控制CNT自增或自减,从而指示编码器的位置,旋转方向和旋转速度。

2:每个高级定时器和通用定时器都拥有一个编码器接口

3:两个通用的引脚分别借用了输入捕获通道1和输入捕获通道二

正交编码器波形

中间相差大概90度

 正向旋转

边沿另一相状态
A相上升沿B相低电平
A相下降沿B相高电平
B相上升沿A相高电平
B相下降沿A相低电平

 反向旋转

边沿另一相状态
A相上升沿B相高电平
A相下降沿B相低电平
B相上升沿A相低电平
B相下降沿A相高电平

旋转编码器计数:正转是向上计数,反转是向下计数

编码器接口的基本结构

1:不反向根据高低电平输出波形

2:反向取反高低电平反转

配置GPIO的输入模式:

配置GPIO的输入模式是可以看接在这个引脚的外部模块输出电平,如果外部模块默认高电平就选择上拉模式,如果外部模块默认低电平就选择下拉模式,配置引脚的电平和外部的默认模式保持一致

定时器:旋转编码器计数编码

接线图

Encoder.c代码

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void Encoder_Init(void){
	  // RCC开启时钟
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	  // 开起AFIO中断引脚控制
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	  
	  // GPIO初始化
	  GPIO_InitTypeDef GPIO_InitStruce;
	  // 选择模式
	  GPIO_InitStruce.GPIO_Mode =GPIO_Mode_IPU;
	  // 选择引脚
	  GPIO_InitStruce.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1 ;
	  // 选择时钟频率
	  GPIO_InitStruce.GPIO_Speed = GPIO_Speed_50MHz;
	  // 初始化GPIO
	  GPIO_Init(GPIOB,&GPIO_InitStruce);
	  
	  // 将外部中断0号线映射到GPIOB,选择PB0作为中断引脚
	  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
	  // 将外部中断1号线映射到GPIOB,选择PB1作为中断引脚
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
	  
		/*
		   中断初始化
		*/
		// 定义结构体变量
		EXTI_InitTypeDef EXTI_InitStructure;
		// 选择外部中断0号线和1号线
		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分组
		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
		// 配置NVIC
		NVIC_InitTypeDef NVIC_InitStructure;
	  // 选择NVIC的EXTI0号线
		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);	
		
}

int16_t Encoder_Get(void){
   int16_t Temp;
	 Temp = Encoder_Count;
	 Encoder_Count = 0;
	 return Temp;
 
}

void EXTI0_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line0) == SET){
	    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0){
			  if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)		//PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
						{
							Encoder_Count --;					//此方向定义为反转,计数变量自减
						}
			}
	}
		EXTI_ClearITPendingBit(EXTI_Line0);		
	
}
void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line1) == SET)		//判断是否是外部中断1号线触发的中断
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)		//PB1的下降沿触发中断,此时检测另一相PB0的电平,目的是判断旋转方向
			{
				Encoder_Count ++;					//此方向定义为正转,计数变量自增
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line1);			//清除外部中断1号线的中断标志位
													//中断标志位必须清除
													//否则中断将连续不断地触发,导致主程序卡死
	}
}




Encoder.h

#ifndef  __ENCODER_H__
#define  __ENCODER_H__
void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif

main.c代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"

int16_t Num;			//定义待被旋转编码器调节的变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	Encoder_Init();		//旋转编码器初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Num:");			//1行1列显示字符串Num:
	
	while (1)
	{
		Num += Encoder_Get();				//获取自上此调用此函数后,旋转编码器的增量值,并将增量值加到Num上
		OLED_ShowSignedNum(1, 5, Num, 5);	//显示Num
	}
}

......

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

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

相关文章

视频编辑的瑞士军刀,MoviePy库的详解与应用示例

左手编程&#xff0c;右手年华。大家好&#xff0c;我是一点&#xff0c;关注我&#xff0c;带你走入编程的世界。 公众号&#xff1a;一点sir&#xff0c;关注领取python编程资料 在数字媒体的时代&#xff0c;视频内容的创作和编辑变得越来越重要。无论是社交媒体上的短视频&…

【数据结构】初识数据结构与复杂度总结

前言 C语言这块算是总结完了&#xff0c;那从本篇开始就是步入一个新的大章——数据结构&#xff0c;这篇我们先来认识一下数据结构有关知识&#xff0c;以及复杂度的相关知识 个人主页&#xff1a;小张同学zkf 若有问题 评论区见 感兴趣就关注一下吧 目录 1.什么是数据结构 2.…

原创【matcap材质在ue4中的实现办法】

matcap材质在ue4中的实现办法 2023-08-29 15:34 https://www.bilibili.com/video/BV1GR4y1b76n/?spm_id_from333.337.search-card.all.click&vd_sourced76b773892c830a157c0ccc97ba78411 评论(0)

PS从入门到精通视频各类教程整理全集,包含素材、作业等(8)复发

PS从入门到精通视频各类教程整理全集&#xff0c;包含素材、作业等 最新PS以及插件合集&#xff0c;可在我以往文章中找到 由于阿里云盘有分享次受限制和文件大小限制&#xff0c;今天先分享到这里&#xff0c;后续持续更新 B站-PS异闻录&#xff1a;萌新系统入门课课程视频 …

Golang学习系列1-pprof性能调优

1. pprof 简述 一位亦师亦友的话让我记忆犹新&#xff0c;他说“学习一个新事务&#xff0c;应该从三个方面入手what,why,how;且三者的重要程度应该是递减”。所以在本文的第一部分先叙述下pprof的what & why。 1.1 What&#xff1f; pprof是golang自身提供的一种性能分…

基于顺序表的学生成绩管理系统

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

【Flink技术原理构造及特性】

1、Flink简介 Flink是一个批处理和流处理结合的统一计算框架&#xff0c;其核心是一个提供了数据分发以及并行化计算的流数据处理引擎。它的最大亮点是流处理&#xff0c;是业界最顶级的开源流处理引擎。 Flink最适合的应用场景是低时延的数据处理&#xff08;Data Processin…

算法练习—day1

title: 算法练习—day1 date: 2024-04-03 21:49:55 tags: 算法 categories:LeetCode typora-root-url: 算法练习—day1 网址&#xff1a;https://red568.github.io 704. 二分查找 题目&#xff1a; 题目分析&#xff1a; 左右指针分别为[left,right]&#xff0c;每次都取中…

练习 19 Web [BJDCTF2020]Easy MD5

如果你是第一批做这个题的&#xff0c;这道题一点也不easy 打开在前端代码里面看到&#xff0c;输入框输入的内容实际是’password’ 随意输入内容&#xff0c;查看响应header中的内容有一句SQL代码&#xff0c;可知我们要让password在md5后返回值为true 然后尬住&#xff…

区间DP模型

目录 环形石子合并思路代码实现 能量项链代码实现 加分二叉树思路代码实现 凸多边形的划分代码实现 棋盘分割题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 佬的题解代码实现 环形石子合并 题目描述&#xff1a; 将 n n n 堆石子绕圆形操场排放&#xff0c;现要将…

前端(动态雪景背景+动态蝴蝶)

1.CSS样式 <style>html, body, a, div, span, table, tr, td, strong, ul, ol, li, h1, h2, h3, p, input {font-weight: inherit;font-size: inherit;list-style: none;border-spacing: 0;border: 0;border-collapse: collapse;text-decoration: none;padding: 0;margi…

C++从入门到精通——入门知识

1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的就是对标识符的名…

43.1k star, 免费开源的 markdown 编辑器 MarkText

43.1k star, 免费开源的 markdown 编辑器 MarkText 分类 开源分享 项目名: MarkText -- 简单而优雅的开源 Markdown 编辑器 Github 开源地址&#xff1a; https://github.com/marktext/marktext 官网地址&#xff1a; MarkText 支持平台&#xff1a; Linux, macOS 以及 Win…

中文Mistral模型介绍(Chinese-Mistral)——中文大语言模型

中文Mistral简介 Chinese-Mistral由清华大学地学系地球空间信息科学实验室开发。 该模型基于Mistral发布的Mistral-7B-v0.1训练得到。首先进行中文词表扩充&#xff0c;然后采用实验室提出的PREPARED训练框架&#xff08;under review&#xff09;在中英双语语料上进行增量预训…

C++Date类的实现

目录 前言&#xff1a; 1.显示日期 2.构造函数与获取某年某月的日期的函数 3.日期比较 4.日期加减天数 5.日期减日期 6.前置后置与-- 7.完整代码 8.测试 总结&#xff1a; 感谢支持&#xff01; 前言&#xff1a; 结合了前面的内容的学习&#xff0c;本篇来对之前的…

面试篇:杂乱篇

String s " "; 1. String类的常用方法有哪些&#xff1f; s.length()&#xff1a; 返回字符串长度s.substring()&#xff1a; 截取字符串s.split()&#xff1a; 分割字符串s.equlas()&#xff1a; 字符串比…

Ai智能生成图片神器,多种风格任你选,探索无限可能的视觉盛宴

在数字化浪潮中&#xff0c;图片已成为我们表达创意、传递情感、展示品牌的重要工具。然而&#xff0c;不是每个人都有专业的设计背景&#xff0c;也不是每个创作者都能轻松驾驭各种风格。这时&#xff0c;一款强大而灵活的AI智能生成图片神器应运而生&#xff0c;它将为你的创…

Vol.34 Good Men Project:一个博客网站,每月90万访问量,通过付费订阅和广告变现

今天给大家分享的案例网站是&#xff1a;Good Men Project&#xff0c;这是一个专门针对男性成长的博客网站&#xff0c;内容包括人际关系、家庭、职业发展等话题。 它的网址是&#xff1a;The Good Men Project - The Conversation No One Else Is Having 流量情况 我们先看…

【python实战】--提取所有目录下所有Excel文件指定列数据

系列文章目录 文章目录 系列文章目录前言一、问题描述二、python代码1.引入库 总结 前言 一、问题描述 需要提取指定路径下所有excel文件中指定一列数据&#xff0c;汇总到新文件&#xff0c;&#xff08;逐列汇总&#xff09; 二、python代码 1.引入库 代码如下&#xff08…

vue弹出的添加信息组件中 el-radio 单选框无法点击问题

情景描述:在弹出的添加信息的组件中的form中有一个单选框,单选框无法进行点击切换 原因如下: 单选框要求有个默认值,因为添加和更新操作复用同一个组件,所以我在初始化时对相关进行了判定,如果为空则赋初始值 结果这样虽然实现了初始值的展示,但是就是如此造成了单选框的无法切…