STM32 1-5

目录

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);//这里要显示有符号数
	}
	
}

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

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

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

相关文章

【linux】复制cp和硬连接、软连接的区别? innode 关系?

1.命令&#xff1a; cp -r [源文件或目录] [目的目录] #复制 ln -s [被链接的文件] [链接的目录/名称] #软连接 ln [被链接的文件] [链接的目录/名称] #硬连接 注&#xff1a;cp -r 会把所有source当作普通文件&#xff08;regular文件&#xff09;&#x…

代码随想录算法训练营第35天 | 860.柠檬水找零 406.根据身高重建队列 452.用最少数量的箭引爆气球

柠檬水找零 局部最优&#xff1a;收到20元时优先找零10元5元&#xff0c;不够再找零3个5元&#xff0c;因为5元可以找零20和10&#xff0c;更有用。全局最优&#xff1a;完成所有的找零。 class Solution { public:bool lemonadeChange(vector<int>& bills) {int fi…

Flink问题解决及性能调优-【Flink rocksDB读写state大对象导致背压问题调优】

RocksDB是Flink中用于持久化状态的默认后端&#xff0c;它提供了高性能和可靠的状态存储。然而&#xff0c;当处理大型状态并频繁读写时&#xff0c;可能会导致背压问题&#xff0c;因为RocksDB需要从磁盘读取和写入数据&#xff0c;而这可能成为瓶颈。 遇到的问题 Flink开发…

多线程编程3——线程的状态

一、状态是线程的状态 状态是PCB中与调度相关的属性&#xff0c;线程是CPU调度执行的基本单位。所以&#xff0c;状态是线程的属性。谈到状态&#xff0c;考虑的都是线程的状态&#xff0c;不是进程&#xff01;&#xff01;&#xff01; 二、在Java中&#xff0c;线程的状态…

作业车间调度问题:P还是NP

获取更多资讯&#xff0c;赶快关注上面的公众号吧&#xff01; 文章目录 基本概念多项式时间指数时间 P问题&#xff08;多项式问题&#xff09;NP问题&#xff08;非确定性多项式问题&#xff09;暴力穷举法动态规划 P与NP关系&#xff1a;作业车间调度问题是典型的NP难问题 …

将vite项目(vue/react)使用vite-plugin-pwa配置为pwa应用,只需要3分钟即可

将项目配置为pwa模式&#xff0c;就可以在浏览器里面看到安装应用的选项&#xff0c;并且可以将web网页像app一样添加到手机桌面或者pad桌面上&#xff0c;或者是电脑桌面上&#xff0c;这样带来的体验就像真的在一个app上运行一样。为了实现这个目的&#xff0c;我们可以为vue…

vue3-hand-mobile

当我写完手势移动事件后&#xff0c;我又通过svg的方法添加了一段文字和polygon。当我在这个蓝色的polygon上滑动手势的时候&#xff0c;会报错。 可能这个bug只是我个人的代码导致的。但是我觉得vue3-hand-mobile插件的这一段代码写的有问题。 我通过circular-json库修复了这…

vite+vue3+ts项目上线docker 配置反向代理API

这次重点的坑是反向代理。 1。项目中配置代理&#xff0c;为了跨域请求数据 项目根目录中新建vite.config.ts文件 在文件中添加配置代理 注意&#xff1a;其中 /api 和target 的地址后面没有 / 2。在项目根目录中新建Httprequest.ts文件&#xff0c;引入axios&#xff0c;并…

网诺安全文件上传总结

一、文件上传简介 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff08;木马、病毒、恶意脚本、webshell等&#xff09;&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。上传点一般出现在头像、导入数据、上传压缩包等地方&#xff0c;由于程序对用户上传…

VUE使用computed实现子父组件双向绑定数据

上面字符串文字是父级的数据&#xff0c;下面表单是父级传给子组件并实现双向绑定 // 这里是vue3写法&#xff0c;vue2 同样在computed里写 get(){} 即可 const form computed({get(){ // props.modelForm 就是父级传过来的对象const proxy new Proxy(props.modelForm,{get(t…

网络原理——传输层2

1.TCP协议 TCP协议是工作中最常用到的协议。 TCP协议格式&#xff1a; 源端口号&#xff08;16位&#xff09;&#xff1a;源端口标识发送方的应用程序。目的端口号&#xff08;16位&#xff09;&#xff1a;目的端口标识接收方的应用程序。序列号&#xff08;32位&#xf…

echarts 堆叠柱状图数据差值较大,导致显示图形差异很大

问题描述&#xff1a; echarts 堆叠柱状图数据差值较大&#xff0c;导致显示图形差异很大 如图&#xff1a; 解决方案 柱状图、折线图 给 y轴或者x轴type设置log 就可以 。饼图 设置 minAngle

kafka summary

最近整体梳理之前用到的一些东西&#xff0c;回顾Kafka的时候好多东西都忘记了&#xff0c;把一些自己记的比较模糊并且感觉有用的东西整理一遍并且记忆一遍&#xff0c;仅用于记录以备后续回顾 Kafka的哪些场景中使用了零拷贝 生产者发送消息&#xff1a;在 Kafka 生产者发送…

使用.NET6 Avalonia开发跨平台三维应用

本文介绍在Vistual Studio 2022中使用Avalonia和集成AnyCAD Rapid AvaloniaUI三维控件的过程。 0 初始化环境 安装Avalonia.Templates dotnet new install Avalonia.Templates若之前安装过可忽略此步骤。 1 创建项目 选择创建AvaloniaUI项目 选一下.NET6版本和Avalonia版…

RX-8564 LC实时时钟模块

.内置 32.768 kHz 晶体单元(频率精度调整完毕) .接口类型&#xff1a;I2C-Bus 接口 (400 kHz) .工作电压范围&#xff1a;1.8 V ~ 5.5 V .计时&#xff08;保持&#xff09;电压范围 &#xff1a;1.0 V ~ 5.5 V / -20 ˚C ~70 ˚C .低待机电流 &#xff1a;275 nA / 3.0…

基于BiLSTM-CRF对清华语料文本进行分类

安装TorchCRF !pip install TorchCRF1.0.6 构建BiLSTM-CRF # encoding:utf-8import torch import torch.nn as nn from TorchCRF import CRFfrom torch.utils.data import Dataset from sklearn.model_selection import train_test_split import numpy as npimport torch im…

python-自动化篇-运维-语音识别

文章目录 理论文本转换为语音使用 pyttsx使用 SAPI使用 SpeechLib 语音转换为文本 代码和效果01使用pyttsx实现文本_语音02使用SAPI实现文本_语音03使用SpeechLib实现文本_语音04使用PocketSphinx实现语音转换文本 理论 语音识别技术&#xff0c;也被称为自动语音识别&#xf…

Threejs 展示——点击模型指定部分添加高亮显示

文章目录 需求分析需求 如下图所示,点击模型指定部分添加高亮显示 分析 绘制一个 canvas将该 canvas 将渲染器挂载到dom<template><canvas id="three" /> </template><scr

基于C#制作一个俄罗斯方块小游戏

目录 引言游戏背景介绍游戏规则游戏设计与实现开发环境与工具游戏界面设计游戏逻辑实现游戏优化和测试性能优化测试工具和流程说明引言 俄罗斯方块是一款经典的益智游戏,深受玩家喜爱。本文将介绍如何使用C#编程语言制作一个简单的俄罗斯方块小游戏,并探讨其设计与实现过程。…

从公有云对象存储迁移到回私有化 MinIO需要了解的所有信息

我们上一篇文章《如何从 AWS S3 遣返到 MinIO》的反响非常出色 - 我们已经接到了数十个企业的电话&#xff0c;要求我们提供遣返建议。我们已将这些回复汇总到这篇新文章中&#xff0c;其中我们更深入地研究了与遣返相关的成本和节省&#xff0c;以便您更轻松地进行自己的分析。…