GD 32中断系统实现

1.0 中断的概念

 中断:简单来说就是打断的意思,在计算机系统中CPU在执行一个操作的时候,有一个比当前任务更为紧急的任务需要执行,cpu暂停当前任务转而去执行更为紧急任务的操作,执行完更为紧急任务之后再返回来执行原来未执行完的任务:这里还涉及到任务切换的概念【以上是对于中断的理解】


2.0 中断的硬件结构


以上的结构大概是GD32单片机有7个端口,每一个端口大概有8个引脚,【同一时间只能有一个引脚接入到中断引脚选择】,中断引脚选择中可以选择触发中断的模式,有上升沿触发,下降沿触发选择完成后设置中断标志位,今个NVIC嵌入式中断向量控制器,然后进入对应的片上外设。


3.0 中断优先级

中断的优先级分为4组,每一组设置有不同的抢占式优先级和响应式优先级,可以参考以下的例子作为了解。

CPU 正在执行任务A,这个时候任务B来了 ,假设目前任务A的抢占式优先级是2 响应式优先级是3,任务B的抢占式优先级是1,响应式优先级是3 , 这是时候,GPU或展停任务A的执行转而去执行任务B的任务B任务执行完毕之后再去执行A任务。

第一种场景


抢占式优先级:如下图所示,任务a的抢占式优先级是3,响应式优先级是1,任务B的抢占式优先级是2,响应式优先级是2,然后任务B会打断抢占任务A的先执行

 以下可以类比得出结果


4.0 代码实现

相关库函数参考

项目架构

中断配置步骤

初始化GPIO时钟

以上初始化GPIO的时钟使用定义结构体的方式进行初始化,使用结构体更方便后续程序的移植与使用,也可以选择不使用结构体初始化的方式。

中断EXTI初始化

使用结构体的方式初始化中断,在使用NVIC嵌套中断向量控制器使能中断的时候,首先要清除指定的中断线路,否则可能会出现程序频繁的进入中断与中断卡死的情况。

中断函数编写

以上主要使用到3个中断线,第一个是EXTI_0的中断,第二个是EXTI_13的中断,第三个是EXTI_14的中断。


KEY.C程序源码

#include "gd32f30x.h"                   // Device header
#include <stdint.h>
#include "LED.h"

// 创建结构体数组
typedef struct{
    rcu_periph_enum rcu;
	uint32_t gpio;
	uint32_t mode;
	uint32_t speed;
	uint32_t pin;
}Exti_Gpio_t;

static Exti_Gpio_t Exti_List[] = {
    {RCU_GPIOA,GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_0},
	{RCU_GPIOG,GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_13},
	{RCU_GPIOG,GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_14},
};

#define  Max_List_Exti sizeof(Exti_List)/sizeof(Exti_List[0])
	
static void GPIO_Init(void){
		uint16_t i = 0;
	    for(i = 0; i < Max_List_Exti; i++){
			rcu_periph_clock_enable(Exti_List[i].rcu);
			gpio_init(Exti_List[i].gpio,Exti_List[i].mode,Exti_List[i].speed,Exti_List[i].pin);
		}	
}

static void EXTI_Init(void){
		// 开启中断时钟
		rcu_periph_clock_enable(RCU_AF);
	    // 开启中断引脚选择
		gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA,GPIO_PIN_SOURCE_0);
	    // 中断引脚初始化
		exti_init(EXTI_0,EXTI_INTERRUPT,EXTI_TRIG_FALLING);
		// 清除中断标志位,如果不清除单片机上电后会立即进入中断
	    exti_interrupt_flag_clear(EXTI_0);
	    // 使能中断,中断引脚选择,抢占式优先级,响应式优先级
	    nvic_irq_enable(EXTI0_IRQn,1,1);
	
	    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOG,GPIO_PIN_SOURCE_13);
		exti_init(EXTI_13,EXTI_INTERRUPT,EXTI_TRIG_FALLING);
	    exti_interrupt_flag_clear(EXTI_13);
	
	    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOG,GPIO_PIN_SOURCE_14);
		exti_init(EXTI_14,EXTI_INTERRUPT,EXTI_TRIG_FALLING);
		exti_interrupt_flag_clear(EXTI_4);
	
	    nvic_irq_enable(EXTI10_15_IRQn, 0, 1);
	  
}

void KeyDrvInit(void){
	 GPIO_Init();
	 EXTI_Init();
}

void EXTI0_IRQHandler(void){
	// 获取中断标志位
	if(exti_interrupt_flag_get(EXTI_0) != RESET){
			Toggle_Led_Turn(LED1);
		    // 清除中断线路,防止该中断被反复的处理
		    exti_interrupt_flag_clear(EXTI_0);
		    while(1);
	}
}


void EXTI10_15_IRQHandler(void){
		if(exti_interrupt_flag_get(EXTI_13) != RESET){
		      Toggle_Led_Turn(LED2);
			  exti_interrupt_flag_clear(EXTI_13);
		}
		if(exti_interrupt_flag_get(EXTI_14) != RESET){
		      Toggle_Led_Turn(LED3);
			  exti_interrupt_flag_clear(EXTI_14);
		}
}
	

KEY.H程序源码

#ifndef  __KEY_H_
#define  __KEY_H_
#include <stdint.h>

void KeyDrvInit(void);

#endif


LED.C 程序源码

#include "gd32f30x.h"                   // Device header
#include "Delay.h"
#include <stdint.h>



// 初始化结构体结构体数据类型
typedef struct Led_gpio_t{
    rcu_periph_enum rcu;
	uint32_t gpio;
	uint32_t pin;
}LED_GPIO_T;

// 定义一个静态全局变量保存GPIO口的资源信息
static LED_GPIO_T Gpio_List[] = {
     {RCU_GPIOA,GPIOA,GPIO_PIN_8},
	 {RCU_GPIOE,GPIOE,GPIO_PIN_6},
	 {RCU_GPIOF,GPIOF,GPIO_PIN_6}
};

// 宏定义确定数组的大小
#define LED_NUM_MAX (sizeof(Gpio_List) / sizeof(Gpio_List[0]))

void LED_Init_Drive(void){
	for(uint8_t i = 0; i < LED_NUM_MAX; i++){
		// 开启GPIO时钟
		rcu_periph_clock_enable(Gpio_List[i].rcu);
        // 初始化GPIO
		gpio_init(
		        Gpio_List[i].gpio,
				GPIO_MODE_OUT_PP,
				GPIO_OSPEED_10MHZ,
				Gpio_List[i].pin);
		// GPIO 初始化调用的方式
		gpio_bit_reset(Gpio_List[i].gpio,Gpio_List[i].pin);
	}
}

void Turn_LedOn(uint8_t LedNo){
		if(LedNo >= LED_NUM_MAX){
			return;
		}else{
			gpio_bit_set(Gpio_List[LedNo].gpio,Gpio_List[LedNo].pin);
		}

}

void Turn_OffLed(uint8_t LedOff){
		if(LedOff >= LED_NUM_MAX){
			return;
		}else{
			gpio_bit_reset(Gpio_List[LedOff].gpio,Gpio_List[LedOff].pin);
		}
}

// 进入中断函数之后实现LED翻转功能
void Toggle_Led_Turn(uint8_t LedToggle){
		// 设置中断标志位
	   FlagStatus bit_state;
	   // 获取输出数据寄存器的值
	   bit_state = gpio_input_bit_get(Gpio_List[LedToggle].gpio,Gpio_List[LedToggle].pin);
	   // 取反功能
	   bit_state = (FlagStatus)(1 - bit_state);
	   // 写入数据寄存器的值
	   gpio_bit_write(Gpio_List[LedToggle].gpio,Gpio_List[LedToggle].pin,bit_state);
	   
}








/*
  注:下面的这段代码可以忽略
*/


// 初始化LED灯
void LED_Init(void){
    // 使能RCU时钟
	rcu_periph_clock_enable(RCU_GPIOA);
	// 配置引脚输出频率
	gpio_init( GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
    
	// 初始化GPIOE的引脚
	rcu_periph_clock_enable(RCU_GPIOE);
	// 配置引脚输出频率
	gpio_init( GPIOE, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_6);
	
	// 初始化GPIOE的引脚
	rcu_periph_clock_enable(RCU_GPIOF);
	// 配置引脚输出频率
	gpio_init( GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_6);
}





// 实现循环流水灯的功能
void LED_Cycle(void){
	        DelayInit();
	        while(1){
				gpio_bit_set(GPIOA, GPIO_PIN_8); 
				DelayNms(1000);
				gpio_bit_reset(GPIOA, GPIO_PIN_8);
				DelayNms(1000);
				
				gpio_bit_set(GPIOE, GPIO_PIN_6); 
				DelayNms(1000);
				gpio_bit_reset(GPIOE, GPIO_PIN_6);
				DelayNms(1000);
				
				gpio_bit_set(GPIOF, GPIO_PIN_6); 
				DelayNms(1000);
				gpio_bit_reset(GPIOF, GPIO_PIN_6);
				DelayNms(1000);
			}


}



LED.H程序源码

#ifndef _LED_H_
#define _LED_H_
#include <stdint.h>

//宏定义LED灯的引脚
#define LED1   0
#define LED2   1
#define LED3   2


void LED_Init(void);

void LED_Cycle(void);

void LED_Init_Drive(void);

void Turn_LedOn(uint8_t LedNo);

void Turn_OffLed(uint8_t LedOff);

void Toggle_Led_Turn(uint8_t LedToggle);

#endif

MAIN.C程序源码

#include <stdio.h>
#include "gd32f30x.h"
#include "Delay.h"
#include "LED.h"
#include "Key.h"


int main(void)
{    
	// 初始化LED
	LED_Init();
	KeyDrvInit();
	while(1){

	} 
	
}



注:以上程序实现的效果是由KEY1,KEY2,KEY3,控制三个LED灯分别为LED1,LED2,LED3当第一个按键按下时LED1点亮,同时控制LED1的按键优先级低于控制KEY2,KEY3按键的优先级这个时候LED1灯会被抢占,也就是点亮LED1后可能无法再次被熄灭。【抢占式优先级】。


下面的内容是关于STM32的可以不看【------用于类比学习---------】

5.0 STM32外部中断

初始化外部中断的步骤

1: RCC 开启外部中断的时钟【中断引脚选择时钟AFIO选择哪一组引脚进入中断】

2: RCC 开启GPIO时钟

3:EXTI 中断引脚选择与中断的触发方式

4:NVIC 嵌套中断向量控制器【配置中断优先级分组和中断的优先级同时使能中断】

5:编写中断函数执行中断操作

中断按照这个步骤一一打通即可

外部中断实现旋转编码器计算次数的功能

CountSensor.c 代码

#include "stm32f10x.h"                  // Device header
#include <stdint.h>

uint16_t g_CountSensor_Count;	
/*
   *****************************************
   * @brief : 初始化旋转编码器计算次数,使能rcc时钟
   * @param : 无参数
   * @param : 无参数
   * @retval: 无返回值  
   *****************************************
*/
void CountSensor_Init(void)
{
	// 时钟初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	// GPIO初始化
	GPIO_InitTypeDef GPIO_InitStructre;
	GPIO_InitStructre.GPIO_Mode   = GPIO_Mode_IPU;
	GPIO_InitStructre.GPIO_Speed  = GPIO_Pin_14;
	GPIO_InitStructre.GPIO_Pin    = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructre);
	// 中断引脚选择与配置方式
	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_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	 // 使能中断
	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 = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
	NVIC_Init(&NVIC_InitStructure); 
}

uint16_t CountSensor_Cet(void)
{
		return g_CountSensor_Count;
}

void EXTI15_10_IRQHandler(void)
{
		if(EXTI_GetITStatus(EXTI_Line14) == SET)
		{
			if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) == 0)
			{
				g_CountSensor_Count ++;
			}
			// 进一次中断清除一次中断标志位
			EXTI_ClearITPendingBit(EXTI_Line14);
		}

}



CountSensor.h

#ifndef  __COUNTSENSOR_H_
#define  __COUNTSENSOR_H_
#include <stdint.h>

void CountSensor_Init(void);
uint16_t CountSensor_Cet(void);


#endif

MAIN.C

#include "stm32f10x.h"                
#include <stdint.h>
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
#include "CountSensor.h"
#include "OLED.h"


int main(void)
{
	OLED_Init();
	CountSensor_Init();
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Count:");	//1行1列显示字符串Count:
	while (1)
	{
		OLED_ShowNum(1, 7, CountSensor_Cet(), 5);
	}
	
}

OLED.H文件

#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清屏
}

OLED.H

#ifndef __OLED_H
#define __OLED_H
#include <stdint.h>

void OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值