野火STM32F1开发板 IIC 0.96OLED 波形显示

2023-11-10

硬件连接

在这里插入图片描述

软件代码

MAIN.C

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "bsp_adc.h"
#include "bsp_advanced_timer.h"
#include "bsp_i2c_gpio.h"
#include "OLED_I2C.h"
#include "bsp_systick.h"
#include "bsp_led.h"
#include <math.h>



#define pi 3.1415926535
#define accur 0.015295
extern uint16_t ConvData;//ADC采样数据
extern unsigned char BMP1[];
int main()
{
	uint8_t x;
	LED_Init();

	OLED_Init();					 /* OLED初始化 */
	ADCx_Init();
	AdvancedTim_Init();
	Before_State_Update(accur*ConvData);
	OLED_CLS();
	while(1)
	{
		for(x=0;x<128;x=(x+1)%128)
		{
			OLED_DrawWave(x,accur*ConvData);
	}
}

bsp_adc.c

#include "bsp_adc.h"

uint16_t ConvData;

static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	/*开时钟*/
	RCC_APB2PeriphClockCmd(ADCx_PORT_CLK, ENABLE);
	/*配置参数*/
	GPIO_InitStruct.GPIO_Pin=ADCx_PIN;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;/*模拟输入模式*/
	/*写入寄存器*/
	GPIO_Init(ADCx_PORT, &GPIO_InitStruct);

}
static void ADCx_Config(void)
{
	ADC_InitTypeDef ADC_InitStruct;
	/*打开ADC时钟*/
	RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
	/*配置参数*/
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;/*独立模式*/
	ADC_InitStruct.ADC_ContinuousConvMode=ENABLE;/*连续转换*/
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;/*数据右对齐*/
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;/*不使用外部硬件触发*/
	ADC_InitStruct.ADC_NbrOfChannel=ADCx_CHx;/*ADC是哪个通道*/
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;/*不使用连续扫描*/
	/*将参数写入寄存器*/
	ADC_Init(ADC_x, &ADC_InitStruct);
	/*设置ADC_CLK*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	/*规则通道设置,通道,采样顺序,采样时间*/
	ADC_RegularChannelConfig(ADC_x, ADCx_CHx, 1, ADC_SampleTime_1Cycles5);
	/*ADC使能*/
	ADC_Cmd(ADC_x, ENABLE);
	/*校验ADC*/
	ADC_StartCalibration(ADC_x);
	while(ADC_GetCalibrationStatus(ADC_x)==RESET);
	/*DMA设置*/
	ADC_DMACmd(ADC_x, ENABLE);
	/*ADC软件触发,开始转换*/
	ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
}
static void ADCx_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStruct;
	/*打开DMA时钟*/
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  /*配置DMA参数*/  
  DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t)(&(ADC_x->DR));/*ADC的数据寄存器*/
  DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)(&ConvData);/*存储器地址*/
  DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC;/*外设为源*/
  DMA_InitStruct.DMA_BufferSize=1;/*数据的个数为1*/
  DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;/*外设地址不增加*/
  DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Disable;/*存储器地址不增加*/
  DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord; /*16位数据,所以是半字*/
  DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
  DMA_InitStruct.DMA_Mode=DMA_Mode_Circular;/*这里是指数据循环不停地发送*/
  DMA_InitStruct.DMA_Priority=DMA_Priority_High;/*DMA优先级设为高*/
  DMA_InitStruct.DMA_M2M=DMA_M2M_Disable;/*不使能存储器到存储器*/
	/*将参数写入寄存器*/
  DMA_Init(ADCx_DMA_CHx, &DMA_InitStruct);
	/*使能DMA*/
  DMA_Cmd(ADCx_DMA_CHx, ENABLE);
}
void ADCx_Init(void)
{
	
	ADCx_GPIO_Config();
	ADCx_DMA_Config();
	ADCx_Config();
	
}

bsp_adc.h

#ifndef _BSP_ADC_H_
#define _BSP_ADC_H_

#include "stm32f10x.h"
/*GPIO*/
#define ADCx_PORT_CLK  		RCC_APB2Periph_GPIOA
#define ADCx_PIN  				GPIO_Pin_7
#define ADCx_PORT					GPIOA

/*ADC*/
#define ADC_x							ADC1
#define ADCx_CLK  		    RCC_APB2Periph_ADC1
#define ADCx_CHx 		    	ADC_Channel_7

/*DMA*/
#define ADCx_DMA_CLK  		RCC_AHBPeriph_DMA1
#define ADCx_DMA_CHx 		  DMA1_Channel1


void ADCx_Init(void);

#endif //_BSP_ADC_H_

bsp_advanced_timer.c

#include "bsp_advanced_timer.h"

static void AdvancedTim_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	/*开时钟*/
	TIMx_CH1_GPIO_CLK_CMD(TIMx_CH1_GPIO_CLK, ENABLE);
	TIMx_CH1N_GPIO_CLK_CMD(TIMx_CH1N_GPIO_CLK, ENABLE);
	TIMx_BKIN_GPIO_CLK_CMD(TIMx_BKIN_GPIO_CLK ,ENABLE);
	/*设置参数1*/
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=TIMx_CH1_GPIO_PIN;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	/*写参数*/
	GPIO_Init(TIMx_CH1_GPIO_PORT, &GPIO_InitStruct);
	
	
	/*设置参数2*/
	GPIO_InitStruct.GPIO_Pin=TIMx_CH1N_GPIO_PIN;
	/*写参数*/
	GPIO_Init(TIMx_CH1N_GPIO_PORT, &GPIO_InitStruct);
	
	
	/*设置参数3*/
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=TIMx_BKIN_GPIO_PIN;
	/*写参数*/
	GPIO_Init(TIMx_BKIN_GPIO_PORT, &GPIO_InitStruct);
	
}

static void AdvancedTim_Config(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_BDTRInitTypeDef TIM_BDTRInitStruct;
	/*开时钟*/
	RCC_APB2PeriphClockCmd(ADVANCED_TIM_CLK, ENABLE);
	/*配置时基参数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler=ADVANCED_TIM_PSC;/*预分频因子*/
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;/*向上计数*/
	TIM_TimeBaseInitStruct.TIM_Period=ADVANCED_TIM_ARR;/*周期*/
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;/*Tdts:这里会与死区时间有关*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;/*不使用重复计数器*/
	/*写参数*/
	TIM_TimeBaseInit(ADVANCED_TIM, &TIM_TimeBaseInitStruct);
	
	/*配置输出比较的参数*/
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;/*PWM模式一*/
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;/*主通道使能*/
	TIM_OCInitStruct.TIM_OutputNState=TIM_OutputNState_Enable;/*互补通道使能*/
	TIM_OCInitStruct.TIM_Pulse=ADVANCED_TIM_CCR;/*占空比*/
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;/*主通道高电平为有效*/
	TIM_OCInitStruct.TIM_OCNPolarity=TIM_OCNPolarity_High;/*互补通道高电平为有效*/
	TIM_OCInitStruct.TIM_OCIdleState=TIM_OCIdleState_Reset;/*刹车后的输出状态*/
	TIM_OCInitStruct.TIM_OCNIdleState=TIM_OCNIdleState_Reset;
	/*写参数*/
	TIM_OC1Init(ADVANCED_TIM, &TIM_OCInitStruct);
	TIM_OC1PreloadConfig(ADVANCED_TIM, TIM_OCPreload_Enable);
	
	/*配置死区刹车寄存器*/
	TIM_BDTRInitStruct.TIM_OSSRState=TIM_OSSRState_Enable;
	TIM_BDTRInitStruct.TIM_OSSIState=TIM_OSSIState_Enable;
	TIM_BDTRInitStruct.TIM_LOCKLevel=TIM_LOCKLevel_OFF;
	TIM_BDTRInitStruct.TIM_DeadTime=7;	/*死区时间97ns*/
	TIM_BDTRInitStruct.TIM_Break=TIM_Break_Enable;/*使能刹车功能*/
	TIM_BDTRInitStruct.TIM_BreakPolarity=TIM_BreakPolarity_High;/*当刹车通道为高电平时停止输出*/
	TIM_BDTRInitStruct.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;
	TIM_BDTRConfig(ADVANCED_TIM, &TIM_BDTRInitStruct);
	
	TIM_Cmd(ADVANCED_TIM, ENABLE);
	TIM_CtrlPWMOutputs(ADVANCED_TIM, ENABLE);
}

void AdvancedTim_Init(void)
{
		AdvancedTim_GPIO_Config();
		AdvancedTim_Config();
}

bsp_advanced_timer.h

#ifndef _BSP_ADVANCED_TIMER_H_
#define _BSP_ADVANCED_TIMER_H_

#include "stm32f10x.h"
/*GPIO*/
#define TIMx_CH1_GPIO_PORT 				GPIOA
#define TIMx_CH1_GPIO_PIN 				GPIO_Pin_8
#define TIMx_CH1_GPIO_CLK     		RCC_APB2Periph_GPIOA
#define TIMx_CH1_GPIO_CLK_CMD 		RCC_APB2PeriphClockCmd

#define TIMx_CH1N_GPIO_PORT 			GPIOB
#define TIMx_CH1N_GPIO_PIN 				GPIO_Pin_13
#define TIMx_CH1N_GPIO_CLK     		RCC_APB2Periph_GPIOB
#define TIMx_CH1N_GPIO_CLK_CMD 		RCC_APB2PeriphClockCmd

#define TIMx_BKIN_GPIO_PORT 			GPIOB
#define TIMx_BKIN_GPIO_PIN 				GPIO_Pin_12
#define TIMx_BKIN_GPIO_CLK     		RCC_APB2Periph_GPIOB
#define TIMx_BKIN_GPIO_CLK_CMD 		RCC_APB2PeriphClockCmd
/*Advanced Timer*/

#define ADVANCED_TIM 							TIM1
#define ADVANCED_TIM_CLK					RCC_APB2Periph_TIM1

#define ADVANCED_TIM_PSC_SET 			36
#define ADVANCED_TIM_PSC 					(ADVANCED_TIM_PSC_SET-1)

#define ADVANCED_TIM_ARR_SET 			65536
#define ADVANCED_TIM_ARR 					(ADVANCED_TIM_ARR_SET-1)

#define ADVANCED_TIM_CCR_SET 			12000
#define ADVANCED_TIM_CCR					(ADVANCED_TIM_CCR_SET)


void AdvancedTim_Init(void);

#endif//_BSP_ADVANCED_TIMER_H_

bsp_i2c_gpio.c

/**
  ******************************************************************************
  * @file    bsp_i2c_gpio.c
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   用gpio模拟i2c总线, 适用于STM32系列CPU。该模块不包括应用层命令帧,仅包括I2C总线基本操作函数。
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火 F103-MINI STM32 开发板 
  * 论坛    :http://www.firebbs.cn
  * 淘宝    :https://fire-stm32.taobao.com
  *
  ******************************************************************************
  */ 

/*
	应用说明:
	在访问I2C设备前,请先调用 i2c_CheckDevice() 检测I2C设备是否正常

*/
#include "bsp_i2c_gpio.h"
#include "stm32f10x.h"

/*
*********************************************************************************************************
*	函 数 名: i2c_Delay
*	功能说明: I2C总线位延迟,最快400KHz
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay(void)
{
	//uint8_t i;

	/* 
	 	下面的时间是通过逻辑分析仪测试得到的。
    工作条件:CPU主频72MHz ,MDK编译环境,1级优化
  
		循环次数为10时,SCL频率 = 205KHz 
		循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 
	 	循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us 
	*/
	//for (i = 0; i < 10; i++);
}

/*
*********************************************************************************************************
*	函 数 名: i2c_Start
*	功能说明: CPU发起I2C总线启动信号
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void i2c_Start(void)
{
	/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
	OLED_I2C_SDA_1();
	OLED_I2C_SCL_1();
	i2c_Delay();
	OLED_I2C_SDA_0();
	i2c_Delay();
	OLED_I2C_SCL_0();
	i2c_Delay();
}

/*
*********************************************************************************************************
*	函 数 名: i2c_Start
*	功能说明: CPU发起I2C总线停止信号
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void i2c_Stop(void)
{
	/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
	OLED_I2C_SDA_0();
	OLED_I2C_SCL_1();
	i2c_Delay();
	OLED_I2C_SDA_1();
}

/*
*********************************************************************************************************
*	函 数 名: i2c_SendByte
*	功能说明: CPU向I2C总线设备发送8bit数据
*	形    参:_ucByte : 等待发送的字节
*	返 回 值: 无
*********************************************************************************************************
*/
void i2c_SendByte(uint8_t _ucByte)
{
	uint8_t i;

	/* 先发送字节的高位bit7 */
	for (i = 0; i < 8; i++)
	{		
		if (_ucByte & 0x80)
		{
			OLED_I2C_SDA_1();
		}
		else
		{
			OLED_I2C_SDA_0();
		}
		i2c_Delay();
		OLED_I2C_SCL_1();
		i2c_Delay();	
		OLED_I2C_SCL_0();
		if (i == 7)
		{
			 OLED_I2C_SDA_1(); // 释放总线
		}
		_ucByte <<= 1;	/* 左移一个bit */
		i2c_Delay();
	}
}

/*
*********************************************************************************************************
*	函 数 名: i2c_ReadByte
*	功能说明: CPU从I2C总线设备读取8bit数据
*	形    参:无
*	返 回 值: 读到的数据
*********************************************************************************************************
*/
uint8_t i2c_ReadByte(void)
{
	uint8_t i;
	uint8_t value;

	/* 读到第1个bit为数据的bit7 */
	value = 0;
	for (i = 0; i < 8; i++)
	{
		value <<= 1;
		OLED_I2C_SCL_1();
		i2c_Delay();
		if (OLED_I2C_SDA_READ())
		{
			value++;
		}
		OLED_I2C_SCL_0();
		i2c_Delay();
	}
	return value;
}

/*
*********************************************************************************************************
*	函 数 名: i2c_WaitAck
*	功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
*	形    参:无
*	返 回 值: 返回0表示正确应答,1表示无器件响应
*********************************************************************************************************
*/
 uint8_t i2c_WaitAck(void)
{
	uint8_t re;

	OLED_I2C_SDA_1();	/* CPU释放SDA总线 */
	i2c_Delay();
	OLED_I2C_SCL_1();	/* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
	i2c_Delay();
	if (OLED_I2C_SDA_READ())	/* CPU读取SDA口线状态 */
	{
		re = 1;
	}
	else
	{
		re = 0;
	}
	OLED_I2C_SCL_0();
	i2c_Delay();
	return re;
}

/*
*********************************************************************************************************
*	函 数 名: i2c_Ack
*	功能说明: CPU产生一个ACK信号
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
	OLED_I2C_SDA_0();	/* CPU驱动SDA = 0 */
	i2c_Delay();
	OLED_I2C_SCL_1();	/* CPU产生1个时钟 */
	i2c_Delay();
	OLED_I2C_SCL_0();
	i2c_Delay();
	OLED_I2C_SDA_1();	/* CPU释放SDA总线 */
}

/*
*********************************************************************************************************
*	函 数 名: i2c_NAck
*	功能说明: CPU产生1个NACK信号
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
	OLED_I2C_SDA_1();	/* CPU驱动SDA = 1 */
	i2c_Delay();
	OLED_I2C_SCL_1();	/* CPU产生1个时钟 */
	i2c_Delay();
	OLED_I2C_SCL_0();
	i2c_Delay();	
}

/*
*********************************************************************************************************
*	函 数 名: i2c_CfgGpio
*	功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void i2c_CfgGpio(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(OLED_RCC_I2C_PORT, ENABLE);	/* 打开GPIO时钟 */

	GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN | OLED_I2C_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  	/* 开漏输出 */
	GPIO_Init(OLED_GPIO_PORT_I2C, &GPIO_InitStructure);

	/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
	i2c_Stop();
}

bsp_i2c_gpio.h

#ifndef _BSP_I2C_GPIO_H
#define _BSP_I2C_GPIO_H

#include <inttypes.h>

#define OLED_I2C_WR	0		/* 写控制bit */
#define OLED_I2C_RD	1		/* 读控制bit */

/* 定义I2C总线连接的GPIO端口, 用户只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */
#define OLED_GPIO_PORT_I2C	GPIOB			/* GPIO端口 */
#define OLED_RCC_I2C_PORT 	RCC_APB2Periph_GPIOB		/* GPIO端口时钟 */
#define OLED_I2C_SCL_PIN		GPIO_Pin_6			/* 连接到SCL时钟线的GPIO */
#define OLED_I2C_SDA_PIN		GPIO_Pin_7			/* 连接到SDA数据线的GPIO */


/* 定义读写SCL和SDA的宏,已增加代码的可移植性和可阅读性 */
#if 0	/* 条件编译: 1 选择GPIO的库函数实现IO读写 */
	#define OLED_I2C_SCL_1()  GPIO_SetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SCL_PIN)		/* SCL = 1 */
	#define OLED_I2C_SCL_0()  GPIO_ResetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SCL_PIN)		/* SCL = 0 */
	
	#define OLED_I2C_SDA_1()  GPIO_SetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SDA_PIN)		/* SDA = 1 */
	#define OLED_I2C_SDA_0()  GPIO_ResetBits(OLED_GPIO_PORT_I2C, OLED_I2C_SDA_PIN)		/* SDA = 0 */
	
	#define OLED_I2C_SDA_READ()  GPIO_ReadInputDataBit(OLED_GPIO_PORT_I2C, OLED_I2C_SDA_PIN)	/* 读SDA口线状态 */
#else	/* 这个分支选择直接寄存器操作实现IO读写 */
    /* 注意:如下写法,在IAR最高级别优化时,会被编译器错误优化 */
	#define OLED_I2C_SCL_1()  OLED_GPIO_PORT_I2C->BSRR = OLED_I2C_SCL_PIN				/* SCL = 1 */
	#define OLED_I2C_SCL_0()  OLED_GPIO_PORT_I2C->BRR = OLED_I2C_SCL_PIN				/* SCL = 0 */
	
	#define OLED_I2C_SDA_1()  OLED_GPIO_PORT_I2C->BSRR = OLED_I2C_SDA_PIN				/* SDA = 1 */
	#define OLED_I2C_SDA_0()  OLED_GPIO_PORT_I2C->BRR = OLED_I2C_SDA_PIN				/* SDA = 0 */
	
	#define OLED_I2C_SDA_READ()  ((OLED_GPIO_PORT_I2C->IDR & OLED_I2C_SDA_PIN) != 0)	/* 读SDA口线状态 */
#endif


void i2c_Start(void);
void i2c_Stop(void);
void i2c_SendByte(uint8_t _ucByte);
uint8_t i2c_ReadByte(void);
uint8_t i2c_WaitAck(void);
void i2c_Ack(void);
void i2c_NAck(void);

void i2c_CfgGpio(void);
#endif

OLED_I2C.c

#include "OLED_I2C.h"
#include "bsp_i2c_gpio.h"
#include "bsp_systick.h"
#include "codetab.h"

uint8_t DataBuffer[8][128];
uint8_t Bef[3];//保存前一个数据的几个参数1.要写在第几页2.0x01要移动几位3.写什么数据
uint8_t Cur[3];//当前前一个数据1.要写在第几页2.0x01要移动几位3.写什么数据

/*
*********************************************************************************************************
*	函 数 名: i2c_CheckDevice
*	功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
*	形    参:_Address:设备的I2C总线地址
*	返 回 值: 返回值 0 表示正确, 返回1表示未探测到
*********************************************************************************************************
*/
uint8_t OLED_CheckDevice(uint8_t _Address)
{
	uint8_t ucAck;
	
	i2c_Start();		/* 发送启动信号 */

	i2c_SendByte(_Address|OLED_I2C_WR);/* 发送设备地址 */
	ucAck = i2c_WaitAck();	/* 检测设备的ACK应答 */

	i2c_Stop();			/* 发送停止信号 */

	return ucAck;
}


 /**
  * @brief  I2C_WriteByte,向OLED寄存器地址写一个byte的数据
  * @param  addr:寄存器地址
	*					data:要写入的数据
  * @retval 无
  */
void I2C_WriteByte(uint8_t addr,uint8_t data){
	
	i2c_Start();//开启I2C总线
	
	/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
	i2c_SendByte(OLED_ADDRESS|OLED_I2C_WR);
	
	/*等待ACK */
	if (i2c_WaitAck() != 0)
	{
		goto cmd_fail;	/* OLED器件无应答 */
	}
		
	i2c_SendByte(addr);//发送寄存器地址
	
	/*等待ACK */
	if (i2c_WaitAck() != 0)
	{
		goto cmd_fail;	/* OLED器件无应答 */
	}

	i2c_SendByte(data);//发送数据
	
	/*等待ACK */
	if (i2c_WaitAck() != 0)
	{
		goto cmd_fail;	/* OLED器件无应答 */
	}	
	
 /* 发送I2C总线停止信号 */
	i2c_Stop();

cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */
	/* 发送I2C总线停止信号 */
	i2c_Stop();

}


 /**
  * @brief  WriteCmd,向OLED写入命令
  * @param  I2C_Command:命令代码
  * @retval 无
  */
void WriteCmd(unsigned char I2C_Command)//写命令
{
	I2C_WriteByte(0x00, I2C_Command);
}


 /**
  * @brief  WriteDat,向OLED写入数据
  * @param  I2C_Data:数据
  * @retval 无
  */
void WriteDat(unsigned char I2C_Data)//写数据
{
	I2C_WriteByte(0x40, I2C_Data);
}


 /**
  * @brief  OLED_Init,初始化OLED
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
	i2c_CfgGpio();				 /*I2C总线的GPIO初始化*/
	Delay_ms(1000);		// 1s,这里的延时很重要,上电后延时,没有错误的冗余设计
	
	WriteCmd(0xAE); //display off
	WriteCmd(0x20);	//Set Memory Addressing Mode	
	WriteCmd(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
	WriteCmd(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
	WriteCmd(0xc8);	//Set COM Output Scan Direction
	WriteCmd(0x00); //---set low column address
	WriteCmd(0x10); //---set high column address
	WriteCmd(0x40); //--set start line address
	WriteCmd(0x81); //--set contrast control register
	WriteCmd(0xff); //亮度调节 0x00~0xff
	WriteCmd(0xa1); //--set segment re-map 0 to 127
	WriteCmd(0xa6); //--set normal display
	WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
	WriteCmd(0x3F); //
	WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
	WriteCmd(0xd3); //-set display offset
	WriteCmd(0x00); //-not offset
	WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
	WriteCmd(0xf0); //--set divide ratio
	WriteCmd(0xd9); //--set pre-charge period
	WriteCmd(0x22); //
	WriteCmd(0xda); //--set com pins hardware configuration
	WriteCmd(0x12);
	WriteCmd(0xdb); //--set vcomh
	WriteCmd(0x20); //0x20,0.77xVcc
	WriteCmd(0x8d); //--set DC-DC enable
	WriteCmd(0x14); //
	WriteCmd(0xaf); //--turn on oled panel
}


 /**
  * @brief  OLED_SetPos,设置光标
  * @param  x,第几页
	*					y,第几列
  * @retval 无
  */
void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{ 
	WriteCmd(0xb0+x);
	WriteCmd((y&0x0f)|0x00);//LOW
	WriteCmd(((y&0xf0)>>4)|0x10);//HIGHT
}

 /**
  * @brief  OLED_Fill,填充整个屏幕
  * @param  fill_Data:要填充的数据
	* @retval 无
  */
void OLED_Fill(void)//全屏填充
{
	uint8_t i,j;
	for(i=0;i<8;i++)
	{
		for(j=0;j<128;j++)
		{
			DataBuffer[i][j]=0xff;
		}
	}
	Write_DataBuffer();
}

 /**
  * @brief  OLED_CLS,清屏
  * @param  无
	* @retval 无
  */
void OLED_CLS(void)//清屏
{
	uint8_t i,j;
	for(i=0;i<8;i++)
	{
		for(j=0;j<128;j++)
		{
			DataBuffer[i][j]=0x00;
		}
	}
	Write_DataBuffer();
}


 /**
  * @brief  OLED_ON,将OLED从休眠中唤醒
  * @param  无
	* @retval 无
  */
void OLED_ON(void)
{
	WriteCmd(0X8D);  //设置电荷泵
	WriteCmd(0X14);  //开启电荷泵
	WriteCmd(0XAF);  //OLED唤醒
}


 /**
  * @brief  OLED_OFF,让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
  * @param  无
	* @retval 无
  */
void OLED_OFF(void)
{
	WriteCmd(0X8D);  //设置电荷泵
	WriteCmd(0X10);  //关闭电荷泵
	WriteCmd(0XAE);  //OLED休眠
}


void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
	// Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 1:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 126)
				{
					x = 0;
					y++;
				}
				//OLED_SetPos(x,y);
				OLED_SetPos(y,x);
				for(i=0;i<6;i++)
					WriteDat(F6x8[c][i]);
				x += 6;
				j++;
			}
		}break;
		case 2:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
				{
					x = 0;
					y++;
				}
				//OLED_SetPos(x,y);
				OLED_SetPos(y,x);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i]);
				//OLED_SetPos(x,y+1);
				OLED_SetPos(y+1,x);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}


void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
	// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
	// Description    : 显示codetab.h中的汉字,16*16点阵
	unsigned char wm=0;
	unsigned int  adder=32*N;
	//OLED_SetPos(x , y);
	OLED_SetPos(y,x);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
	//OLED_SetPos(x,y + 1);
	OLED_SetPos(y+1,x);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
}

void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
	// Parameters     : x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
	// Description    : 显示BMP位图
	unsigned int j=0;
	unsigned char x,y;

  if(y1%8==0)
		y = y1/8;
  else
		y = y1/8 + 1;
	for(y=y0;y<y1;y++)
	{
		//OLED_SetPos(x0,y);
		OLED_SetPos(y,x0);
    for(x=x0;x<x1;x++)
		{
			WriteDat(BMP[j++]);
		}
	}
}


void Before_State_Update(uint8_t y)//根据y的值,求出前一个数据的有关参数
{
	Bef[0]=7-y/8;
	Bef[1]=7-y%8;
	Bef[2]=1<<Bef[1];
}
void Current_State_Update(uint8_t y)//根据Y值,求出当前数据的有关参数
{
	Cur[0]=7-y/8;//数据写在第几页
	Cur[1]=7-y%8;//0x01要移动的位数
	Cur[2]=1<<Cur[1];//要写什么数据
}


/*0<=x<=127,0<=y<=63屏幕看作一个坐标轴,左下角是原点*/
void OLED_DrawPoint(uint8_t x,uint8_t y)/*这里x是横坐标,y是纵坐标,在(x,y)处画一个点*/
{
	if(x>127||y>63)
		return;
	uint8_t page,move,data;
	
	page=7-y/8;//数据写在第几页
	move=7-y%8;//0x01要移动的位数
	data=0x01<<move;//要写什么数据
	
	OLED_SetPos(page,x);
	WriteDat(data);
}
	
void OLED_DrawWave(uint8_t x,uint8_t y)
{

	int8_t page_sub;
	uint8_t page_buff,i,j;
	Current_State_Update(y);//根据Y值,求出当前数据的有关参数
	page_sub=Bef[0]-Cur[0];//当前值与前一个值的页数相比较
	//确定当前列,每一页应该写什么数据
	if(page_sub>0)
	{
		page_buff=Bef[0];
		OLED_SetPos(page_buff,x);
		WriteDat(Bef[2]-0x01);
		page_buff--;
		for(i=0;i<page_sub-1;i++)
		{
			OLED_SetPos(page_buff,x);
			WriteDat(0xff);
			page_buff--;
		}
		OLED_SetPos(page_buff,x);
		WriteDat(0xff<<Cur[1]);
	}
	else if(page_sub==0)
	{
		if(Cur[1]==Bef[1])
		{
			OLED_SetPos(Cur[0],x);
			WriteDat(Cur[2]);
		}
		else if(Cur[1]>Bef[1])
		{
			OLED_SetPos(Cur[0],x);
			WriteDat((Cur[2]-Bef[2])|Cur[2]);
		}
		else if(Cur[1]<Bef[1])
		{
			OLED_SetPos(Cur[0],x);
			WriteDat(Bef[2]-Cur[2]);
		}
	}
	else if(page_sub<0)
	{
		page_buff=Cur[0];
		OLED_SetPos(page_buff,x);
		WriteDat((Cur[2]<<1)-0x01);
		page_buff--;
		for(i=0;i<0-page_sub-1;i++)
		{
			OLED_SetPos(page_buff,x);
			WriteDat(0xff);
			page_buff--;
		}
		OLED_SetPos(page_buff,x);
		WriteDat(0xff<<(Bef[1]+1));
	}
	Before_State_Update(y);
	//把下一列,每一页的数据清除掉
	for(i=0;i<8;i++)
	{
		OLED_SetPos(i, x+1) ;
		for(j=0;j<1;j++)
			WriteDat(0x00);
	}
}

/*
*********************************************************************************************************
*	函 数 名: OLED检测测试
*	功能说明: 检测I2C总线设备,实际是对OLED_CheckDevice()的封装
*	形    参:
*	返 回 值: 返回值 0 表示没有检测到OLED,返回1表示检测到OLED
*********************************************************************************************************
*/

 uint8_t OLED_Test(void) 
{
	
  if (OLED_CheckDevice(OLED_ADDRESS) == 1)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}	

/*写 缓存数据*/
void Write_DataBuffer(void)//这个是将DataBuffer数组里面的值,全部写进屏里去
{	
	uint8_t i,j;
	for(i=0;i<8;i++)
	{
		OLED_SetPos(i,0); //设置起始点坐标
		for(j=0;j<128;j++)
		{
			WriteDat(DataBuffer[i][j]);//写数据
		}
	}
}

OLED_I2C.h

#ifndef __OLED_I2C_H
#define	__OLED_I2C_H

#include "stm32f10x.h"

#define BUFF_SIZE 10

#define OLED_ADDRESS	0x78 //通过调整0R电阻,屏可以0x78和0x7A两个地址 -- 默认0x78

uint8_t OLED_CheckDevice(uint8_t _Address);//检测I2C总线设备OLED
void I2C_WriteByte(uint8_t addr,uint8_t data);
void WriteCmd(unsigned char I2C_Command);
void WriteDat(unsigned char I2C_Data);
void OLED_Init(void);
void OLED_SetPos(unsigned char x, unsigned char y);
void OLED_Fill(void);
void OLED_CLS(void);
void OLED_ON(void);
void OLED_OFF(void);
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize);
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N);
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
uint8_t OLED_Test(void) ;//OLED检测测试
void Write_DataBuffer(void);
void OLED_DrawWave(uint8_t x,uint8_t y);
void OLED_DrawPoint(uint8_t x,uint8_t y);
void Before_State_Update(uint8_t y);

#endif

bsp_systick.c

#include "bsp_systick.h"

#if 0
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}
#endif

void Delay_ms(uint32_t ms)
{
	uint32_t i;
	SysTick_Config(72000);									/*配置为1ms中断一次*/
	for(i=0;i<ms;i++)
	{
		while(!(SysTick->CTRL & (1<<16)));		/*检测标志位(最高位)*/
	}
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;/*关闭SysTick*/
}
void Delay_us(uint32_t us)
{
	uint32_t i;
	SysTick_Config(72);
	for(i=0;i<us;i++)
	{
		while(!(SysTick->CTRL & (1<<16)));
	}
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
}

bsp_systick.h

#ifndef _BSP_SYSTICK_H
#define _BSP_SYSTICK_H

#include "stm32f10x.h"
#include "core_cm3.h"

void Delay_ms(uint32_t ms);
void Delay_us(uint32_t us);
#endif //_BSP_SYSTICK_H

bsp_usart.c

#include "bsp_usart.h"

void USARTx_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    USART_Rx_GPIO_CLK_CMD(USART_Rx_GPIO_CLK,ENABLE);
    USART_Tx_GPIO_CLK_CMD(USART_Tx_GPIO_CLK,ENABLE);
    
    GPIO_InitStruct.GPIO_Pin=USART_Rx_GPIO_PIN;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_Init(USART_Rx_GPIO_PORT, &GPIO_InitStruct);
    
    GPIO_InitStruct.GPIO_Pin=USART_Tx_GPIO_PIN;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(USART_Tx_GPIO_PORT, &GPIO_InitStruct);
    
}
void USARTx_Config(void)
{
    USART_InitTypeDef USART_InitStruct;
    USARTx_CLK_CMD(USARTx_CLK,ENABLE);
    //初始化串口相关数据
    USART_InitStruct.USART_BaudRate=USARTx_BAUD_RATE;
    USART_InitStruct.USART_WordLength=USART_WordLength_8b;
    USART_InitStruct.USART_StopBits=USART_StopBits_1;
    USART_InitStruct.USART_Parity=USART_Parity_No;
    USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
    USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_Init(USARTx, &USART_InitStruct);
    //使能串口
    USART_Cmd(USARTx, ENABLE);
    //使能串口中断
    //USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
    

}
void USARTx_NVIC_Config(void)
{
      NVIC_InitTypeDef NVIC_InitStruct;
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      NVIC_InitStruct.NVIC_IRQChannel=USARTx_IRQCHANNEL;
      NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
      NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
      NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
        
      NVIC_Init(&NVIC_InitStruct);  


}
void USARTx_Init(void)
{
    //USARTx_NVIC_Config();
    USARTx_GPIO_Config();
    USARTx_Config();
}


int fputc(int ch,FILE* f)
{
    USART_SendData(USARTx, (uint8_t)ch);
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET);
    return(ch); 
}
int fgetc(FILE* f)
{
     while(USART_GetFlagStatus(USARTx, USART_FLAG_RXNE)==RESET);
    return (int)USART_ReceiveData(USARTx);
}

bsp_usart.h

#ifndef _BSP_USART_H_
#define _BSP_USART_H_

#include "stm32f10x.h"

#include <stdio.h>


#define USARTx USART1
#define USARTx_BAUD_RATE 115200
#define USARTx_CLK  RCC_APB2Periph_USART1
#define USARTx_CLK_CMD  RCC_APB2PeriphClockCmd


#define USARTx_IRQCHANNEL USART1_IRQn
#define USARTx_IRQHANDLER USART1_IRQHandler


#define USART_Rx_GPIO_PORT  GPIOA
#define USART_Rx_GPIO_PIN   GPIO_Pin_10
#define USART_Rx_GPIO_CLK   RCC_APB2Periph_GPIOA
#define USART_Rx_GPIO_CLK_CMD  RCC_APB2PeriphClockCmd

#define USART_Tx_GPIO_PORT GPIOA
#define USART_Tx_GPIO_PIN  GPIO_Pin_9
#define USART_Tx_GPIO_CLK  RCC_APB2Periph_GPIOA
#define USART_Tx_GPIO_CLK_CMD  RCC_APB2PeriphClockCmd


void USARTx_GPIO_Config(void);
void USARTx_Config(void);
void USARTx_NVIC_Config(void);
void USARTx_Init(void);

#endif //_BSP_USART_H_
工程下载地址

https://download.csdn.net/download/weixin_43599390/12667344

效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

野火STM32F1开发板 IIC 0.96OLED 波形显示 的相关文章

  • 快速排序及sort的理解

    快速排序 快速排序的思想 1 在数据集中 选择一个元素作为 基准 2 所有小于 基准 的元素都移动到 基准 左边 所有大于 基准 的元素都移动到 基准 右边 3 对 基准 左右两边的子集 递归地重复 1 和 2 直到所有子集的长度都只有1个
  • 按位非‘~’符号的使用

    所谓的按位非就是在数字前加上 的符号 最简单的记忆方法是 a a 1 let a 1 let b a b 2 let a 2 let b a b 3 let a 1 let b a b 0 使用场景 在if判断的时候 if在0的情况下的转换
  • C3-Squid-access.log

    C3 Squid access log 拓扑 DNS 10 0 100 71 Haproxy 10 0 100 82 Squid 10 0 100 72 73 Nginx 10 0 100 75 76 NFS 10 0 100 70 DNS
  • ASP.NET 中得到网站绝对路径的几种方法

    在编写 ASP NET 应用程序的时候 有时为了更好地进行控制静态文件的路径 如在模板页或者用户控件中设置js或者css文件的路径等 采用绝对路径是难免的 下面就是几种获取绝对路径的几种方法 C 代码 VirtualPathUtility
  • SVN学习笔记 .

    转载自 http blog csdn net tengbaichuan article details 10632349 参考文档 官方文档 http www subversion org cn svnbook 包括可下载的PDF 和一页H

随机推荐

  • 浅谈npm、yarn、cnpm、pnpm(内附网址链接)

    1 npm 1 1 npm简介 npm由三个独立的部分组成 网站 网站是开发者查找包 package 设置参数以及管理npm使用体验的主要途径 注册表 registry 注册表是一个巨大的数据库 保存了每个包 package 的信息 命令行
  • Ubuntu 16.04 取消 conda 自动启动工作空间 base

    问题描述 Ubuntu 16 04 安装conda 之后它会自动启动工作空间base base的默认 Python 版本是 3 7 而Ubuntu 16 04 的默认 Python 版本是2 7 解决方案 如果不想默认启动 base工作空间
  • gcc g++ 学习

    一 编译的时候 此时main cpp头文件是 include Person h g main cpp Person Person cpp o main I Person 解析 Person Person cpp 链接main cpp的上一层
  • 工厂模式--Factory Method with Go

    Factory Method 工厂设计模式允许创建对象 而无需指定将要创建的对象的确切类型 Implementation 举个栗子 用个例子展示怎么把数据存储在不同的后端 比如 内存 磁盘 Types type 一个Store interf
  • PAT C入门题目-竖着输出字符串(Z:c语言求数组长度 sizeof()&strlen())

    7 2 I Love GPLT 5 分 这道超级简单的题目没有任何输入 你只需要把这句很重要的话 I Love GPLT 竖着输出就可以了 即每个字符占一行 包括空格 即每行只能有1个字符和回车 include
  • sketch基础教程大全,对象、图层、画板常见技巧

    sketch对象 图层 画板的使用技巧 1 通过快捷键调整图形的形状 选择图形 按住Command按键 然后通过上 下 左 右方向键按1像素调整图形形状 同时按住按钮 CommandShift方向键 可调整方向键 2 复制元素 选择一个元素
  • Python爬虫从入门到精通:(24)scrapy框架01_scrapy框架的认识、安装_Python涛哥

    scrapy框架的认识 安装 框架简介 什么是框架 所谓的框架其实就是一个被集成了很多功能且具有很强通用性的一个项目模板 怎么学习 学习的是框架中集成好的各种功能的特性是作用 进阶学习 逐步的探索框架的底层 安装scrapy 是一个专门用于
  • 数据结构和算法(二)

    ArrayList 和LinkedList原理 代码实现 性能区别 1 ArrayList 为什么查询快 数组和集合区别 动态大小 数组的长度是固定的 ArrayList 数组集合 内部使用数组实现的 自定义ArrayList 如下 pub
  • 如何理解受控和非受控件组件?

    受控组件 受控组件是React中的一种组件 其特点是输入框的值 value 由React状态 state 控制 也就是说 React中的状态变化会直接影响输入框的值 受控组件通过form的输入元素 input select等 的value属
  • 孕期做什么副业好?在家兼职挣钱的孕妇不仅能很好地抚养孩子,还能继续她们的职业生涯

    孕期做什么副业好 在家兼职挣钱的孕妇不仅能很好地抚养孩子 还能继续她们的职业生涯 许多孕妇在得知怀孕后会在家休息分娩 一旦你在家休假分娩 你会感到特别无聊 无聊 甚至沮丧 这对胎儿的发育会非常不利 所以在这个时候 那些希望在家分娩的孕妇可以
  • composer改回原来的源

    以前为了图安装快 把composer的源改成了国内的 composer config g repo packagist composer https packagist phpcomposer com 今天使用时发现还要用户名和密码登录 怕
  • CentOS7.3编译安装go1.10.1

    直接使用编译好的包 go1 10 1 linux amd64 tar gz 下载go wget https studygolang com dl golang go1 10 1 linux amd64 tar gz tar xvf go1
  • vscode中如何快速生成vue3模板-非常实用的小技巧

    vscode中如何快速生成vue3模板 在vue项目开发过程中 我们会发现我们每次新建一个vue组件文件的时候 都需要写一些重复的代码 比如下面代码
  • 运算放大器---虚短和虚断

    运算放大器 虚短和虚断 前言 运算放大器两板斧 虚短 虚断 虚短 在分析运算放大器处于线性状态时 可把两输入端视为等电位 这一特性称为虚假短路 简称虚短 当某一端接地的时候 V V 0 虚断 在分析运放处于线性状态时 可以把两输入端视为等效
  • Conda——问题解决:CondaValueError: Malformed version string ‘~’ : invalid character(s)

    报错截图 解决方法 更新conda即可 conda upgrade n base c defaults override channels conda 成功截图
  • 1-7、Lua迭代器与泛型for

    1 7 Lua迭代器与泛型for 理解为主 必选先理解闭包的概念和用法 文章目录 1 7 Lua迭代器与泛型for 理解为主 必选先理解闭包的概念和用法 1 迭代器与闭包 2 范性for的语义 3 无状态的迭代器 4 多状态的迭代器 5 真
  • C++多态

    C 多态 一 多态的概念 二 多态的定义以实现 虚函数 多态构成条件 虚函数的重写 虚函数重写的两个例外 C 11的override和final 重载 重写和重定义的对比 抽象类 概念 接口继承与实现继承 多态的原理 虚函数表 打印虚函数表
  • Android---TabLayout

    目录 TabLayout TabItem 编辑 演示效果的xml TabLayout TabLayout 在开发中一般作为选项卡使用 常与 ViewPager2 和 Fragment 结合起来使用 常用属性 app tabBackgroun
  • android常用面试题,2022年上半年最接地气的Android面经

    没有稳定的工作 只有稳定的能力 又到了万物复苏的季节 在程序猿这个行当里 作为 Android 开发出生的 在经历了八年的脱发生涯后 有了越来越多的想法和感触 趋势 随着各类移动跨平台的兴起 在 ReactNative Flutter We
  • 野火STM32F1开发板 IIC 0.96OLED 波形显示

    硬件连接 软件代码 MAIN C include sys h include delay h include usart h include bsp adc h include bsp advanced timer h include bs