STM32 1-5

news2024/11/18 19:50:12

目录

STM32简介

点亮PC13LED

 GPIO

LED闪烁

LED流水灯

按键控制LED

光敏传感器控制蜂鸣器

OLED调试工具

OLED显示

EXTI外部中断

对射式红外传感器计次

旋转编码器计次


继续

STM32简介

点亮PC13LED

main.c

#include "stm32f10x.h"                  // Device header

int main(void)
{
	//方式二:
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	//配置GPIOC的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;//配置结构体
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置通用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;//配置13针脚
	GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_50MHz;//配置速度
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	//配置端口模式
	
	GPIO_SetBits(GPIOC, GPIO_Pin_13);//将其置为高电平
	//GPIO_ResetBits(GPIOC, GPIO_Pin_13);//将其置为低电平
	//配置高低电平
	
	/*****************************************/
	//方式一:
	//PC13有一个灯,这个灯低电平才会亮
	//RCC ->APB2ENR = 0x00000010;//GPIO都是APB2的外设,APB2ENR是
	//APB2时钟使能寄存器,IOPCEN为使能位,将其设置为1,打开时钟
	
	//GPIOC ->CRH = 0x00300000;//配置PC13口模式,端口配置高寄存器
	//(GPIOx_CRH),配置CNF13以及MODE13,
	
	//GPIOC ->ODR = 0x00002000;//端口输出数据寄存器GPIOx_ODR,
	//为ODR13进行配置高低电平,0x00002000灭,0x00000000亮
	
	while(1)
	{
		
	}
}

 GPIO

面包板两端横向是相通的,内部是纵向相通

LED闪烁

main.c

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

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//第一步:使用RCC开启GPIO时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	//第二步:使用GPIO_Init()初始化GPIO
	
	//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//灯亮
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);//灯灭
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//灯亮
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);//灯灭
	//第三步:使用输出或者输入的函数控制GPIO口
	while(1)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);
		Delay_ms(100);
		GPIO_SetBits(GPIOA,GPIO_Pin_0);
		Delay_ms(100);
		
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);
		Delay_ms(500);
	}
}

LED流水灯

main.c

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

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//第一步:使用RCC开启GPIO时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;//初始化所有端口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	//第二步:使用GPIO_Init()初始化GPIO
	
	//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//灯亮
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);//灯灭
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//灯亮
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);//灯灭
	//第三步:使用输出或者输入的函数控制GPIO口
	while(1)
	{
//		GPIO_Write(GPIOA,~0x0001);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0002);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0004);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0008);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0010);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0020);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0040);
//		Delay_ms(500);
//		GPIO_Write(GPIOA,~0x0080);
//		Delay_ms(500);
		
		unsigned char i ;
		
		for( i = 0 ; i < 8 ;i++)
		{
			GPIO_Write(GPIOA,~(0x0001 << i));
			Delay_ms(500);
		}
	}
	
}

蜂鸣器

main.c

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

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//第一步:使用RCC开启GPIO时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//初始化12端口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	//第二步:使用GPIO_Init()初始化GPIO
	
	//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//灯亮
	//GPIO_SetBits(GPIOA,GPIO_Pin_0);//灯灭
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//灯亮
	//GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);//灯灭
	//第三步:使用输出或者输入的函数控制GPIO口
	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);
	}
	
}

 

按键控制LED

key.c

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

/**
  * @brief  初始化位于PB1以及PB11按键
  * @param  无
  * @retval 无
  */
void Key_Init(void)//配置按键
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	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);	
}

/**
  * @brief  获取所按下的键值
  * @param  无
  * @retval KeyNum 按下的键值
  */
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 = 2;
	}
	return KeyNum;
}

LED.c

#include "stm32f10x.h"                  // Device header

/**
  * @brief  打开GPIO时钟,并进行初始化
  * @param  无
  * @retval 无
  */
void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//第一步:使用RCC开启GPIO时钟
	
	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);
	//第二步:使用GPIO_Init()初始化GPIO
	
//	GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
}

/**
  * @brief  将位于PA1端口电平置零
  * @param  无
  * @retval 无
  */
void LED1_On(void)
{
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}

/**
  * @brief  将位于PA1端口电平置一
  * @param  无
  * @retval 无
  */
void LED1_Off(void)
{
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
}

/**
  * @brief  查看PA1端口电平并将其翻转
  * @param  无
  * @retval 无
  */
void LED1_Turn(void)
{
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0)//查看当前端口输出
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_1);//将其置一
	}
	else
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);//将其置零
	}
}

/**
  * @brief  将位于PA2端口电平置零
  * @param  无
  * @retval 无
  */
void LED2_On(void)
{
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}

/**
  * @brief  将位于PA1端口电平置一
  * @param  无
  * @retval 无
  */
void LED2_Off(void)
{
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
}

/**
  * @brief  查看PA2端口电平并将其翻转
  * @param  无
  * @retval 无
  */
void LED2_Turn(void)
{
	if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0)//查看当前端口输出
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_2);//将其置一
	}
	else
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_2);//将其置零
	}
}

main.c

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

uint8_t KeyNum;

int main(void)
{
	LED_Init();
	Key_Init();
	
	while(1)
	{
		KeyNum = Key_GetNum();//获取键值
		if(KeyNum == 1)//如果键1按下,则翻转LED1电平
		{
			LED1_Turn();
		}
		if(KeyNum == 2)//如果键2按下,则翻转LED1电平
		{
			LED2_Turn();
		}
		
	}
	
}

光敏传感器控制蜂鸣器

LightSensor.c

#include "stm32f10x.h"                  // Device header

/**
  * @brief  初始化端口在PB^13光敏传感器
  * @param  无
  * @retval 无
  */
void LightSensor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//第一步:使用RCC开启GPIO时钟
	
	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_Init()初始化GPIO
}

/**
  * @brief  获得当前光敏传感器输入电平
  * @param  无
  * @retval 返回周围光线情况
  */
uint8_t LightSensor_Get(void)
{
	
	return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
	//周围暗的时候输入1;亮的时候输入0
	//周围暗的时候输出0;亮的时候输出1
}

Buzzer.c

#include "stm32f10x.h"                  // Device header

/**
  * @brief  打开GPIO时钟,并进行初始化
  * @param  无
  * @retval 无
  */
void Buzzer_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//第一步:使用RCC开启GPIO时钟
	
	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);
	//第二步:使用GPIO_Init()初始化GPIO
	
	GPIO_SetBits(GPIOB,GPIO_Pin_12);
}

/**
  * @brief  将位于PB12端口电平置零
  * @param  无
  * @retval 无
  */
void Buzzer_On(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}

/**
  * @brief  将位于PB12端口电平置一
  * @param  无
  * @retval 无
  */
void Buzzer_Off(void)
{
	GPIO_SetBits(GPIOB,GPIO_Pin_12);
}

/**
  * @brief  查看PB12端口电平并将其翻转
  * @param  无
  * @retval 无
  */
void Buzzer_Turn(void)
{
	if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12) == 0)//查看当前端口输出
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_12);//将其置一
	}
	else
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);//将其置零
	}
}

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();
		}
	}
	
}

OLED调试工具

OLED显示

OLED.c

#include "stm32f10x.h"
#include "OLED_Font.h"

/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x))
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x))

/*引脚初始化*/
void OLED_I2C_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void OLED_I2C_Start(void)
{
	OLED_W_SDA(1);
	OLED_W_SCL(1);
	OLED_W_SDA(0);
	OLED_W_SCL(0);
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void OLED_I2C_Stop(void)
{
	OLED_W_SDA(0);
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i++)
	{
		OLED_W_SDA(Byte & (0x80 >> i));
		OLED_W_SCL(1);
		OLED_W_SCL(0);
	}
	OLED_W_SCL(1);	//额外的一个时钟,不处理应答信号
	OLED_W_SCL(0);
}

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x00);		//写命令
	OLED_I2C_SendByte(Command); 
	OLED_I2C_Stop();
}

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x40);		//写数据
	OLED_I2C_SendByte(Data);
	OLED_I2C_Stop();
}

/**
  * @brief  OLED设置光标位置
  * @param  Y 以左上角为原点,向下方向的坐标,范围:0~7
  * @param  X 以左上角为原点,向右方向的坐标,范围:0~127
  * @retval 无
  */
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
	OLED_WriteCommand(0xB0 | Y);					//设置Y位置
	OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));	//设置X位置高4位
	OLED_WriteCommand(0x00 | (X & 0x0F));			//设置X位置低4位
}

/**
  * @brief  OLED清屏
  * @param  无
  * @retval 无
  */
void OLED_Clear(void)
{  
	uint8_t i, j;
	for (j = 0; j < 8; j++)
	{
		OLED_SetCursor(j, 0);
		for(i = 0; i < 128; i++)
		{
			OLED_WriteData(0x00);
		}
	}
}

/**
  * @brief  OLED显示一个字符
  * @param  Line 行位置,范围:1~4
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的一个字符,范围:ASCII可见字符
  * @retval 无
  */
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{      	
	uint8_t i;
	OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);		//设置光标位置在上半部分
	for (i = 0; i < 8; i++)
	{
		OLED_WriteData(OLED_F8x16[Char - ' '][i]);			//显示上半部分内容
	}
	OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);	//设置光标位置在下半部分
	for (i = 0; i < 8; i++)
	{
		OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);		//显示下半部分内容
	}
}

/**
  * @brief  OLED显示字符串
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串,范围:ASCII可见字符
  * @retval 无
  */
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i++)
	{
		OLED_ShowChar(Line, Column + i, String[i]);
	}
}

/**
  * @brief  OLED次方函数
  * @retval 返回值等于X的Y次方
  */
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y--)
	{
		Result *= X;
	}
	return Result;
}

/**
  * @brief  OLED显示数字(十进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~4294967295
  * @param  Length 要显示数字的长度,范围:1~10
  * @retval 无
  */
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
	}
}

/**
  * @brief  OLED显示数字(十进制,带符号数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-2147483648~2147483647
  * @param  Length 要显示数字的长度,范围:1~10
  * @retval 无
  */
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
	uint8_t i;
	uint32_t Number1;
	if (Number >= 0)
	{
		OLED_ShowChar(Line, Column, '+');
		Number1 = Number;
	}
	else
	{
		OLED_ShowChar(Line, Column, '-');
		Number1 = -Number;
	}
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
	}
}

/**
  * @brief  OLED显示数字(十六进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFFFFFF
  * @param  Length 要显示数字的长度,范围:1~8
  * @retval 无
  */
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i, SingleNumber;
	for (i = 0; i < Length; i++)							
	{
		SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
		if (SingleNumber < 10)
		{
			OLED_ShowChar(Line, Column + i, SingleNumber + '0');
		}
		else
		{
			OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
		}
	}
}

/**
  * @brief  OLED显示数字(二进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
	}
}

/**
  * @brief  OLED初始化
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
	uint32_t i, j;
	
	for (i = 0; i < 1000; i++)			//上电延时
	{
		for (j = 0; j < 1000; j++);
	}
	
	OLED_I2C_Init();			//端口初始化
	
	OLED_WriteCommand(0xAE);	//关闭显示
	
	OLED_WriteCommand(0xD5);	//设置显示时钟分频比/振荡器频率
	OLED_WriteCommand(0x80);
	
	OLED_WriteCommand(0xA8);	//设置多路复用率
	OLED_WriteCommand(0x3F);
	
	OLED_WriteCommand(0xD3);	//设置显示偏移
	OLED_WriteCommand(0x00);
	
	OLED_WriteCommand(0x40);	//设置显示开始行
	
	OLED_WriteCommand(0xA1);	//设置左右方向,0xA1正常 0xA0左右反置
	
	OLED_WriteCommand(0xC8);	//设置上下方向,0xC8正常 0xC0上下反置

	OLED_WriteCommand(0xDA);	//设置COM引脚硬件配置
	OLED_WriteCommand(0x12);
	
	OLED_WriteCommand(0x81);	//设置对比度控制
	OLED_WriteCommand(0xCF);

	OLED_WriteCommand(0xD9);	//设置预充电周期
	OLED_WriteCommand(0xF1);

	OLED_WriteCommand(0xDB);	//设置VCOMH取消选择级别
	OLED_WriteCommand(0x30);

	OLED_WriteCommand(0xA4);	//设置整个显示打开/关闭

	OLED_WriteCommand(0xA6);	//设置正常/倒转显示

	OLED_WriteCommand(0x8D);	//设置充电泵
	OLED_WriteCommand(0x14);

	OLED_WriteCommand(0xAF);	//开启显示
		
	OLED_Clear();				//OLED清屏
}

main.c

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

uint8_t KeyNum;

int main(void)
{
	OLED_Init();
	
	OLED_ShowChar(1,1,'A');
	OLED_ShowString(1,3,"Hello,world!");
	OLED_ShowNum(2,1,30,2);
	OLED_ShowSignedNum(2,4,300,3);
	OLED_ShowSignedNum(2,9,-300,3);
	OLED_ShowHexNum(3,1,0xAA55,4);
	OLED_ShowBinNum(4,1,0xAA55,16);
	
	OLED_Clear();
	
	while(1)
	{
			
	}
	
}

EXTI外部中断

对射式红外传感器计次

Encoder.c

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count;

/**
  * 函    数:计数传感器初始化
  * 参    数:无
  * 返 回 值:无
  */
void CountSensor_Init(void)//初始化
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//开启GPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	//开启AFIO时钟
	//EXTI与NVIC不需要开启时钟
	
	//GPIO配置
	GPIO_InitTypeDef GPIO_InitStructure;//外部中断一般选择浮空,上拉或者下拉
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB外设
	
	//AFIO配置
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
	
	//EXTI配置
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;//选择中断源位置
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//选择事件还是中断
	//EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发(离开后触发+1)
	//EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;//上升下降都触发
	EXTI_Init(&EXTI_InitStructure);//初始化EXTI
	
	//NVIC配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组(两位抢占,两位相应)
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//选择芯片对应通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//0-3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//0-3
	NVIC_Init(&NVIC_InitStructure);
	
}

/**
  * 函    数:获取计数传感器的计数值
  * 参    数:无
  * 返 回 值:计数值,范围:0~65535
  */
uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

/**
  * 函    数:EXTI15_10外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI15_10_IRQHandler(void)//中断函数
{
	if(EXTI_GetITStatus(EXTI_Line14) == SET)//判断是否是来自14号端口的中断
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) == 1 || GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) == 0)
			//上升沿若设置为0,则离开加一
			//下降沿若设置为1,则挡住加一
			//若上升下降都触发若设置为 0|1,则挡住加一,离开也加一
		//这里的判断是为了防止数据跳跃幅度大
		//传感器输出高电平灭,输出低电平亮
		//传感器输入高电平亮,输入低电平灭
		{
			CountSensor_Count++;
		}
		EXTI_ClearITPendingBit(EXTI_Line14);//完成中断后清除中断标志位
	}
	
}

main.c

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

uint8_t KeyNum;

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	OLED_ShowString(1,1,"Count:");
	
	
	while(1)
	{
		OLED_ShowNum(1,7,CountSensor_Get(),5);
	}
	
}

旋转编码器计次

Encoder.c

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

/**
  * 函    数:旋转编码器初始化
  * 参    数:无
  * 返 回 值:无
  */
void Encoder_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	//开启GPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	//开启AFIO时钟
	//EXTI与NVIC不需要开启时钟
	
	//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);//初始化GPIOB外设
	
	//AFIO配置
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//配置PB^1端口
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);//配置PB^0端口
	
	//EXTI配置
	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_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
	//EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;//上升下降都触发
	EXTI_Init(&EXTI_InitStructure);//初始化EXTI
	
	//NVIC配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组(两位抢占,两位相应)
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//选择芯片端口0对应通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//0-3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//0-3
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//选择芯片端口1对应通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//0-3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//0-3
	NVIC_Init(&NVIC_InitStructure);
}

/**
  * 函    数:EXTI0外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI0_IRQHandler(void)//端口0触发中断(左旋)
{
	if(EXTI_GetITStatus(EXTI_Line0) == SET)//检查EXTI是否被置位SET,如果置位则进行中断程序
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)//进行判断另一个引脚
		{
			Encoder_Count--;
		}
		EXTI_ClearITPendingBit(EXTI_Line0);//清除标志位
	}
}

/**
  * 函    数:EXTI1外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI1_IRQHandler(void)//端口1触发中断(右旋)
{
	if(EXTI_GetITStatus(EXTI_Line1) == SET)//检查EXTI是否被置位SET,如果置位则进行中断程序
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)//进行判断另一个引脚
		{
			Encoder_Count++;
		}
		EXTI_ClearITPendingBit(EXTI_Line1);//清除标志位
	}
}

/**
  * 函    数:旋转编码器获取增量值
  * 参    数:无
  * 返 回 值:自上此调用此函数后,旋转编码器的增量值
  */
int16_t EncoderCount_Get(void)
{
	int16_t Tmp;
	/*使用Tmp变量作为中继,目的是返回Encoder_Count后将其清零*/
	/*在这里,也可以直接返回Encoder_Count
	  但这样就不是获取增量值的操作方法了
	  也可以实现功能,只是思路不一样*/
	Tmp = Encoder_Count;
	Encoder_Count = 0;
	return Tmp;
}

main.c

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

int16_t Num;


int main(void)
{
	OLED_Init();
	Encoder_Init();
	
	OLED_ShowString(1,1,"Num:");
	
	
	while(1)
	{
		Num += EncoderCount_Get();//这里的函数得到的是对当前数进行操作(加或减)的增量值
		OLED_ShowSignedNum(1,5,Num,5);//这里要显示有符号数
	}
	
}

注意:中断函数中,最好不要执行耗时过长的代码;最好不要在中断函数和主函数中调用相同的函数或操作同一个硬件,尤其的硬件相关函数。尽量操作变量或者标志位,当中断返回时,再对变量进行显示和操作。减少代码间的耦合性,让各部分代码相互独立。

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

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

相关文章

Hadoop-MapReduce-YarnChild启动篇

一、源码下载 下面是hadoop官方源码下载地址&#xff0c;我下载的是hadoop-3.2.4&#xff0c;那就一起来看下吧 Index of /dist/hadoop/core 二、上下文 在上一篇<Hadoop-MapReduce-MRAppMaster启动篇>中已经将到&#xff1a;MRAppMaster的启动&#xff0c;那么运行M…

如何让wordpress首页只显示某一篇文章全部内容?在您的主页显示选择

大多数WordPress站点首页默认都是显示最新发布的文章列表&#xff0c;不过有些站点比较特殊&#xff0c;只想显示某一篇文章的全部内容&#xff0c;那么应该怎么设置呢&#xff1f; 其实&#xff0c;WordPress后台 >> 设置 >> 阅读 >> 在“您的主页显示”中…

VS+QT 配置Eigen库

1、下载Eigen库&#xff0c;如下&#xff1a; 2、解压到项目目录下&#xff0c;如下&#xff1a; 3、 在C/C中包含文件&#xff0c;如下&#xff1a; 4、在头文件中加入如下代码&#xff1a; 5、测试代码&#xff1a; //.cpp文件 #include "testEigen.h"testEigen::…

【Python】03快速上手爬虫案例三:搞定药师帮

文章目录 前言1、破解验证码2、获取数据 前言 流程&#xff1a;通过用户名、密码、搞定验证码&#xff0c;登录进药师帮网站&#xff0c;然后抓取想要的数据。 爬取数据&#xff0c;最终效果图&#xff1a; 1、破解验证码 使用药师帮测试系统&#xff1a;https://dianrc.ysb…

快速入门存内计算—助力人工智能加速深度学习模型的训练和推理

存内计算&#xff1a;提高计算性能和能效的新技术 传统的计算机架构是将数据存储在存储器中&#xff0c;然后将数据传输到计算单元进行处理。这种架构存在一个性能瓶颈&#xff0c;即数据传输延迟。存内计算通过将计算单元集成到存储器中&#xff0c;消除了数据传输延迟&#…

HiveSQL题——窗口函数(lag/lead)

目录 一、窗口函数的知识点 1.1 窗户函数的定义 1.2 窗户函数的语法 1.3 窗口函数分类 1.4 前后函数:lag/lead 二、实际案例 2.1 股票的波峰波谷 0 问题描述 1 数据准备 2 数据分析 3 小结 2.2 前后列转换&#xff08;面试题&#xff09; 0 问题描述 1 数据准备 …

kubernetes-快速部署一套k8s集群

1、前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式&#xff1a; kubeadm Kubeadm是一个K8s部署工具&#xff0c;提供kubeadm init和kubeadm join&#xff0c;用于快速部署Kubernetes集群。 二进制包 从github下载发行…

04.对象树

一、引入 1.QT实现输出"hello world" 使用QT编写"hello world"程序&#xff0c;有两种实现方式&#xff1a; &#xff08;1&#xff09;直接在生成的ui文件中&#xff0c;拖入一个label控件&#xff0c;双击控件编辑内容即可实现 &#xff08;2&#xff0…

【C++历练之路】探秘C++三大利器之一——多态

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 前言&#x1f354;: 在计算机科学的广袤领域中&#xff0c;C多态性是一门令人着迷的技术艺术&#xff0c;它赋予我们的代码更强大的灵活性和可维护性。想象一下&#xff0c;你正在构建一个程序&#xff0c;需要适应不断…

【技术分享】远程透传网关-单网口快速实现威纶通触摸屏程序远程上下载

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接触摸屏一台威纶通触摸屏及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09;…

Redis 面试题 | 19.精选Redis高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Mac安装及配置MySql及图形化工具MySQLworkbench安装

Mac下载配置MySql mysql下载及安装 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 根据自己电脑确定下载x86还是ARM版本的 如果不确定&#xff0c;可以查看自己电脑版本&#xff0c;终端输入命令 uname -a 点击Download下载&#xff0c;可跳过登录注册&…

沙龙回顾|“强标”发布在即,汽车数据安全的挑战与应对

随着智能汽车产业驶入发展快车道&#xff0c;“数据安全”的重要性也日益突出。2020年以来发现的针对整车企业、车联网信息服务提供商等相关企业的恶意攻击达到280余万次。2023年初至今&#xff0c;就发生超过20起与车企相关数据泄露事件&#xff0c;汽车数据安全的现状不容乐观…

基于Matlab无刷直流电机系统仿真建模的新方法

摘 要&#xff1a;在分析无刷直流电机&#xff08;BLDC&#xff09;数学模型的基础上&#xff0c;提出了无刷直流电机系统仿真建模的 新方法。在Matlab/Simulink 中&#xff0c;建立独立的功能模块&#xff0c;如BLDC 本体模块、电流滞环控制模块、 速度控制模块等&#xff0c;…

防御保护--智能选路

目录 就近选路 策略选路--PBR DSCP优先级 智能选路--全局路由策略 1.基于链路带宽的负载分担 2.基于链路质量进行负载分担 3.基于链路权重进行负载分担 4.基于链路优先级的主备备份 ​编辑 DNS透明代理 就近选路 我们希望在访问不同运营商服务器时&#xff0c;通过对…

IDEA安装MyBatisX插件

IDEA工具在开发人员中经常使用&#xff0c;从dao层到xml文件对应的查看很费劲&#xff0c;这时候就有相应的插件工具出现了MyBatisX。他的好处如下&#xff1a; mapper and xml can jump back and forth mybatis.xml,mapper.xml prompt mapper and xml support auto prompt lik…

多场景建模:腾讯3MN

3MN: Three Meta Networks for Multi-Scenario and Multi-Task Learning in Online Advertising Recommender Systems 背景 推荐领域的多场景多任务学习&#xff1a;维护单模型即可节省资源也可节省人力&#xff1b;各个场景的数据共享&#xff0c;理论上面学习是更加充分的 …

RK3568 Android Launcher3定制修改

1.去掉Google搜索栏 目录packages/apps/Launcher3/src_build_config/com/android/launcher3/BuildConfig.java 修改如下&#xff1a; 2.Launcher首页去掉抽屉菜单&#xff0c;所有应用都放到桌面 第一步&#xff1a;禁止上滑显示抽屉 在目录packages/apps/Launcher3/quickste…

大模型学习与实践笔记(十四)

使用 OpenCompass 评测 InternLM2-Chat-7B 模型使用 LMDeploy 0.2.0 部署后在 C-Eval 数据集上的性能 步骤1&#xff1a;下载internLM2-Chat-7B 模型,并进行挂载 以下命令将internlm2-7b模型挂载到当前目录下&#xff1a; ln -s /share/model_repos/internlm2-7b/ ./ 步骤2&…

非阿里云注册域名如何在云解析DNS设置解析?

概述 非阿里云注册域名使用云解析DNS&#xff0c;按照如下步骤&#xff1a; 添加域名。 添加解析记录。 修改DNS服务器。 DNS服务器变更全球同步&#xff0c;等待48小时。 添加解析记录 登录云解析DNS产品控制台。 在 域名解析 页面中&#xff0c;单击 添加域名 。 在 …