STM32基础入门学习笔记:面包板 配件包扩展模块与编程

news2024/12/24 0:21:31

文章目录:

一:阵列键盘

1.阵列键盘测试程序

KEYPAD4x4.h

KEYPAD4x4.c

main.c

2.键盘中断测试程序

NVIC.h

NVIC.c

main.c

二:舵机控制

1.延时函数驱动舵机程序 

SG90.h

SG90.c

main.c

2.PWM(脉冲宽度调制 脉宽调制/占空比)驱动舵机程序

pwm.h

pwm.c

main.c

三:DHT11芯片(DHT11温湿度显示程序)

dht11.h

dht11.c

main.c

四:MPU6050(六轴加速度和陀螺仪传感器芯片)

MPU6050.h

MPU6050.c 

main.c


一:阵列键盘

 

 对跳线进行设置

第一步:把ADC输入的两个跳线断开

第二步:将模拟摇杆的三个跳线断开

第三步:将触摸按键的四个跳线断开

第四步:将旋转编码器的三个跳线断开

1.阵列键盘测试程序

按下时:红线蓝线短接 

 

 阵列键盘

新建文件夹

Hardware文件夹——>KEYPAD4x4文件夹——>KEYPAD4x4.c  KEYPAD4x4.h

KEYPAD4x4.h

#ifndef __KEYPAD4x4_H
#define __KEYPAD4x4_H	 
#include "sys.h"
#include "delay.h"


#define KEYPAD4x4PORT	GPIOA	//定义IO接口组
#define KEY1	GPIO_Pin_0	//定义IO接口
#define KEY2	GPIO_Pin_1	//定义IO接口
#define KEY3	GPIO_Pin_2	//定义IO接口
#define KEY4	GPIO_Pin_3	//定义IO接口
#define KEYa	GPIO_Pin_4	//定义IO接口
#define KEYb	GPIO_Pin_5	//定义IO接口
#define KEYc	GPIO_Pin_6	//定义IO接口
#define KEYd	GPIO_Pin_7	//定义IO接口


void KEYPAD4x4_Init(void);//初始化
void KEYPAD4x4_Init2(void);//初始化2(用于IO工作方式反转)
u8 KEYPAD4x4_Read (void);//读阵列键盘
		 				    
#endif

KEYPAD4x4.c

#include "KEYPAD4x4.h"

void KEYPAD4x4_Init(void){ //微动开关的接口初始化
	GPIO_InitTypeDef  GPIO_InitStructure; //定义GPIO的初始化枚举结构	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       
    GPIO_InitStructure.GPIO_Pin = KEYa | KEYb | KEYc | KEYd; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻       
	GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2 | KEY3 | KEY4; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 //上拉电阻  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)     
	GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);
				
}
void KEYPAD4x4_Init2(void){ //微动开关的接口初始化2(用于IO工作方式反转)
	GPIO_InitTypeDef  GPIO_InitStructure; //定义GPIO的初始化枚举结构	
    GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2 | KEY3 | KEY4; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻       
	GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = KEYa | KEYb | KEYc | KEYd; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式 //上拉电阻  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)     
	GPIO_Init(KEYPAD4x4PORT,&GPIO_InitStructure);
				
}
u8 KEYPAD4x4_Read (void){//键盘处理函数
	u8 a=0,b=0;//定义变量
	KEYPAD4x4_Init();//初始化IO
	GPIO_ResetBits(KEYPAD4x4PORT,KEY1|KEY2|KEY3|KEY4);
	GPIO_SetBits(KEYPAD4x4PORT,KEYa|KEYb|KEYc|KEYd);
	if(!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYa) ||  	//查寻键盘口的值是否变化
		!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYb) || 
		!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYc) || 
		!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYd)){
		delay_ms (20);//延时20毫秒
		if(!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYa) ||  	//查寻键盘口的值是否变化
			!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYb) || 
			!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYc) || 
			!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEYd)){
	  		a = GPIO_ReadInputData(KEYPAD4x4PORT)&0xff;//键值放入寄存器a
		}
		KEYPAD4x4_Init2();//IO工作方式反转
		GPIO_SetBits(KEYPAD4x4PORT,KEY1|KEY2|KEY3|KEY4);
		GPIO_ResetBits(KEYPAD4x4PORT,KEYa|KEYb|KEYc|KEYd);
		b = GPIO_ReadInputData(KEYPAD4x4PORT)&0xff;//将第二次取得值放入寄存器b
		a = a|b;//将两个数据相或
		switch(a){//对比数据值
			case 0xee: b = 16; break;//对比得到的键值给b一个应用数据
			case 0xed: b = 15; break;
			case 0xeb: b = 14; break;
			case 0xe7: b = 13; break;
			case 0xde: b = 12; break;
			case 0xdd: b = 11; break;
			case 0xdb: b = 10; break;
			case 0xd7: b = 9; break;
			case 0xbe: b = 8; break;
			case 0xbd: b = 7; break;
			case 0xbb: b = 6; break;
			case 0xb7: b = 5; break;
			case 0x7e: b = 4; break;
			case 0x7d: b = 3; break;
			case 0x7b: b = 2; break;
			case 0x77: b = 1; break;
			default: b = 0; break;//键值错误处理
		}
		while(!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY1) ||  	//等待按键放开
			!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY2) || 
			!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY3) || 
			!GPIO_ReadInputDataBit(KEYPAD4x4PORT,KEY4));
		delay_ms (20);//延时20毫秒
	}
return (b);//将b作为返回值
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"

#include "KEYPAD4x4.h"


int main (void){//主程序
	u8 s;
	delay_ms(500); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 
	RELAY_Init();//继电器初始化

	I2C_Configuration();//I2C初始化
	OLED0561_Init(); //OLED初始化
	OLED_DISPLAY_8x16_BUFFER(0,"   YoungTalk    "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(3," KEYPAD4x4 TEST "); //显示字符串

	KEYPAD4x4_Init();//阵列键盘初始化

	while(1){

		s=KEYPAD4x4_Read();//读出按键值

        //有按键被按下
		if(s!=0){ //如按键值不是0,也就是说有按键操作,则判断为真
			//-------------------------"----------------"
			OLED_DISPLAY_8x16_BUFFER(6," KEY NO.        "); //显示字符串
			OLED_DISPLAY_8x16(6,8*8,s/10+0x30);    //显示十位    偏移量
			OLED_DISPLAY_8x16(6,9*8,s%10+0x30);    //显示个位
		}
	}
}

2.键盘中断测试程序

嵌套:即是在进入一个中断处理程序之后,还能在中断之内再次产生中断


NVIC嵌套向量中断控制器
    cortex-m3支持256个中断,其中包含了16个内核中断,240个外部中断
    stm32只有84个中断,包括16个内核中断和68个可屏蔽中断
    stm32f103上只有60个可屏蔽中断

    优先级的设置(设置值越小,优先级越高)
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;    //抢占优先级        
        NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;           //子优先级

抢占优先级    又称:主优先级
    在嵌套时,抢占优先级较高的可以在较低的中断内嵌套中断
    同一抢占优先级不能嵌套,必须前一个中断处理完成才能进入下一个
    不同抢占优先级下,响应优先级没有意义


响应优先级    又称:子优先级/亚优先级/次优先级/副优先级
    同一抢占优先级的中断同时产生时,响应优先级较高的先处理
    同一抢占优先级不能嵌套

新建文件夹

Basic文件夹——>nvic文件夹——>NVIC.c  NVIC.h

NVIC.h

#ifndef __NVIC_H
#define __NVIC_H	 
#include "sys.h"


extern u8 INT_MARK;                //中断标志位


void KEYPAD4x4_INT_INIT (void);    //中断初始化函数

#endif

NVIC.c

#include "NVIC.h"

u8 INT_MARK;//中断标志位

void KEYPAD4x4_INT_INIT (void){	 //按键中断初始化
	NVIC_InitTypeDef  NVIC_InitStruct;	//定义结构体变量
	EXTI_InitTypeDef  EXTI_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //启动GPIO时钟 (需要与复用时钟一同启动)     
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);//配置端口中断需要启用复用时钟

//第1个中断	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4);  //定义 GPIO  中断
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line4;  //定义中断线
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;              //中断使能
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;     //中断模式为 中断
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;   //下降沿触发
	
	EXTI_Init(& EXTI_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI4_IRQn;   //中断线     
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;  //使能中断
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;  //抢占优先级 2
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;     //子优先级  2
	NVIC_Init(& NVIC_InitStruct);
	
//第2个中断	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);  //定义  GPIO 中断
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line5;  //定义中断线
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;              //中断使能
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;     //中断模式为 中断
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;   //下降沿触发
	
	EXTI_Init(& EXTI_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI9_5_IRQn;   //中断线
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;  //使能中断
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;  //抢占优先级 2
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;     //子优先级  2
	NVIC_Init(& NVIC_InitStruct);

//第3个中断	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);  //定义  GPIO 中断
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line6;  //定义中断线
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;              //中断使能
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;     //中断模式为 中断
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;   //下降沿触发
	
	EXTI_Init(& EXTI_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI9_5_IRQn;   //中断线
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;  //使能中断
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;  //抢占优先级 2
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;     //子优先级  2
	NVIC_Init(& NVIC_InitStruct);

//第4个中断	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource7);  //定义  GPIO 中断
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line7;  //定义中断线
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;              //中断使能
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;     //中断模式为 中断
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;   //下降沿触发
	
	EXTI_Init(& EXTI_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI9_5_IRQn;   //中断线
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;  //使能中断
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;  //抢占优先级 2
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;     //子优先级  2
	NVIC_Init(& NVIC_InitStruct);

}

void  EXTI4_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line4)!=RESET){//判断某个线上的中断是否发生 
		INT_MARK=1;//标志位置1,表示有按键中断
		EXTI_ClearITPendingBit(EXTI_Line4);   //清除 LINE 上的中断标志位
	}     
}
void  EXTI9_5_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line5)!=RESET){//判断某个线上的中断是否发生 
		INT_MARK=2;//标志位置1,表示有按键中断
		EXTI_ClearITPendingBit(EXTI_Line5);   //清除 LINE 上的中断标志位
	}     
	if(EXTI_GetITStatus(EXTI_Line6)!=RESET){//判断某个线上的中断是否发生 
		INT_MARK=3;//标志位置1,表示有按键中断
		EXTI_ClearITPendingBit(EXTI_Line6);   //清除 LINE 上的中断标志位
	}     
	if(EXTI_GetITStatus(EXTI_Line7)!=RESET){//判断某个线上的中断是否发生 
		INT_MARK=4;//标志位置1,表示有按键中断
		EXTI_ClearITPendingBit(EXTI_Line7);   //清除 LINE 上的中断标志位
	}     
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"

#include "KEYPAD4x4.h"
#include "NVIC.h"


int main (void){//主程序
	u8 s;
	delay_ms(500); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 
	RELAY_Init();//继电器初始化

	I2C_Configuration();//I2C初始化
	OLED0561_Init(); //OLED初始化
	OLED_DISPLAY_8x16_BUFFER(0,"   YoungTalk    "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(3," KEYPAD4x4 TEST "); //显示字符串

	INT_MARK=0;//标志位清0

	NVIC_Configuration();//设置中断优先级
	KEYPAD4x4_Init();//阵列键盘初始化
	KEYPAD4x4_INT_INIT();//阵列键盘的中断初始化

	while(1){

		//其他程序内容

		if(INT_MARK){ //中断标志位为1表示有按键中断
			INT_MARK=0;//标志位清0
			s=KEYPAD4x4_Read();//读出按键值
			if(s!=0){ //如按键值不是0,也就是说有按键操作,则判断为真
				//-------------------------"----------------"
				OLED_DISPLAY_8x16_BUFFER(6," KEY NO.        "); //显示字符串
				OLED_DISPLAY_8x16(6,8*8,s/10+0x30);//
				OLED_DISPLAY_8x16(6,9*8,s%10+0x30);//
			}
		}
	}
}

二:舵机控制

第一步:将舵机连接到开发板上(舵机接口)

第二步:将触摸按键的四个跳线帽短接

注意事项
    1.舵机上如果有负载需要更大的驱动电流
    2.必须连续不断地向PWM线发出角度波形,直到达到对应角度
    3.一般情况下,180度舵机的最大角度可达190度,甚至200度
    4.要按指定型号舵机的波形与角度对应关系做调试,不盲信理论值

新建文件夹 

Hardware文件夹——>SG90文件夹——>SG90.c  SG90.h

1.延时函数驱动舵机程序 

延时函数利用滴答计时器,虽然可以事项该功能,但实际开发中,这种效率很低 

SG90.h

#ifndef __SG90_H
#define __SG90_H	 
#include "sys.h"
#include "delay.h"

#define SE_PORT	GPIOA	//定义IO接口
#define SE_OUT	GPIO_Pin_15	//定义IO接口


void SG90_Init(void);//SG90舵机初始化
void SG90_angle(u8 a);//舵机角度设置
		 				    
#endif

SG90.c

#include "SG90.h"

void SG90_Init(void){ //舵机接口初始化
	GPIO_InitTypeDef  GPIO_InitStructure; 	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       
    GPIO_InitStructure.GPIO_Pin = SE_OUT; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)    
	GPIO_Init(SE_PORT, &GPIO_InitStructure);
	GPIO_WriteBit(SE_PORT,SE_OUT,(BitAction)(0)); //接口输出高电平1
}

void SG90_angle(u8 a){ //舵机角度控制设置(参数值0~180)对应角度0~180度
	u8 b=100;//角度校正偏移量
	GPIO_WriteBit(SE_PORT,SE_OUT,(BitAction)(1)); //接口输出高电平1
	delay_us(500+a*10+b); //延时
	GPIO_WriteBit(SE_PORT,SE_OUT,(BitAction)(0)); //接口输出高电平1
	delay_us(19500-a*10-b); //延时
} 

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "SG90.h"
#include "touch_key.h"


int main (void){//主程序
	delay_ms(500); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 
	RELAY_Init();//继电器初始化

	I2C_Configuration();//I2C初始化
	OLED0561_Init(); //OLED初始化
	OLED_DISPLAY_8x16_BUFFER(0,"   YoungTalk    "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(3,"   SG90 TEST    "); //显示字符串

	TOUCH_KEY_Init();//按键初始化
	SG90_Init();//SG90舵机初始化
	SG90_angle(0);//舵机初步为0(最小值)

	while(1){
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 0       "); //显示字符串
			SG90_angle(0);//舵机初步为0(最小值)
		}
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 45      "); //显示字符串
			SG90_angle(45);//舵机初步为0(最小值)
		}
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 90     "); //显示字符串
			SG90_angle(90);//舵机初步为0(最小值)
		}
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 180     "); //显示字符串
			SG90_angle(180);//舵机初步为0(最小值)
		}
	}
}

2.PWM(脉冲宽度调制 脉宽调制/占空比)驱动舵机程序

使用定时器产生PWM(定时器是独立工作的) 不管用户是否按键,PWM都会处在工作状态,一直输出脉冲来控制舵机(舵机会有抖动)

PWM:是利用微处理器的数字输出 来对模拟电路进行控制的一种非常有效的技术


应用:在从测量、通信到功率控制与变换的许多领域中


必须有一个完整周期(高低电平    高电平决定亮度)
改变高低电平的长度比例,从而达到调节亮度的效果


PWM的产生:可由STM32中的定时器产生,包括1个高级定时器TIM1和3个普通定时器TIM2、TIM3、TIM4

          

为了连接定时器的相关输出:在核心版上通过一条导线连接P415和PB0
    舵机连接:接P415端口
    定时器的输出:PB0端口

按A键亮度最暗....按D键亮度最亮(使LED显示占空比使亮度发生变化) 

新建文件夹

Basic文件夹——>pwm文件夹——>pwm.c  pwm.h

pwm.h

#ifndef  __PWM_H
#define  __PWM_H
#include "sys.h"

void TIM3_PWM_Init(u16 arr,u16 psc);

#endif

pwm.c

#include "pwm.h"


void TIM3_PWM_Init(u16 arr,u16 psc){  //TIM3 PWM初始化 arr重装载值 psc预分频系数
    GPIO_InitTypeDef     GPIO_InitStrue;
    TIM_OCInitTypeDef     TIM_OCInitStrue;
    TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;
    
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3和相关GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟(LED在PB0引脚)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO时钟(定时器3通道3需要重映射到BP5引脚)
    
    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_0;     // TIM_CH3
    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;    // 复用推挽
    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;    //设置最大输出速度
    GPIO_Init(GPIOB,&GPIO_InitStrue);                //GPIO端口初始化设置
    
//    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //映射,重映射只用于64、100、144脚单片机
   //当没有重映射时,TIM3的四个通道CH1,CH2,CH3,CH4分别对应PA6,PA7,PB0,PB1
   //当部分重映射时,TIM3的四个通道CH1,CH2,CH3,CH4分别对应PB4,PB5,PB0,PB1 (GPIO_PartialRemap_TIM3)
   //当完全重映射时,TIM3的四个通道CH1,CH2,CH3,CH4分别对应PC6,PC7,PC8,PC9 (GPIO_FullRemap_TIM3) 
	      
    TIM_TimeBaseInitStrue.TIM_Period=arr;    //设置自动重装载值
    TIM_TimeBaseInitStrue.TIM_Prescaler=psc;        //预分频系数
    TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;    //计数器向上溢出
    TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;        //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue);        //TIM3初始化设置(设置PWM的周期)
    
    TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM1;        // PWM模式1:CNT < CCR时输出有效电平
    TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_High;// 设置极性-有效电平为:高电平
    TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 输出使能
    TIM_OC3Init(TIM3,&TIM_OCInitStrue);        //TIM3的通道3 PWM 模式设置

    TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);        //使能预装载寄存器
    
    TIM_Cmd(TIM3,ENABLE);        //使能TIM3
    
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"
#include "SG90.h"
#include "touch_key.h"

#include "pwm.h"


int main (void){//主程序
	delay_ms(500); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 
	RELAY_Init();//继电器初始化

	I2C_Configuration();//I2C初始化
	OLED0561_Init(); //OLED初始化
	OLED_DISPLAY_8x16_BUFFER(0,"   YoungTalk    "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(3,"   SG90 TEST2   "); //显示字符串

	TOUCH_KEY_Init();//按键初始化
	TIM3_PWM_Init(59999,23); //设置频率为50Hz,公式为:溢出时间Tout(单位秒)=(arr+1)(psc+1)/Tclk	 20MS = (59999+1)*(23+1)/72000000
                          //Tclk为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72MHZ
                          //PWM时钟频率=72000000/(59999+1)*(23+1) = 50HZ (20ms),设置自动装载值60000,预分频系数24

	while(1){
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_A)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 0       "); //显示字符串
			TIM_SetCompare3(TIM3,1500);        //改变比较值TIM3->CCR2达到调节占空比的效果(1500为0度)
		}
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_B)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 45      "); //显示字符串
			TIM_SetCompare3(TIM3,3000);        //改变比较值TIM3->CCR2达到调节占空比的效果
		}
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_C)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 90     "); //显示字符串
			TIM_SetCompare3(TIM3,4500);        //改变比较值TIM3->CCR2达到调节占空比的效果
		}
		if(!GPIO_ReadInputDataBit(TOUCH_KEYPORT,TOUCH_KEY_D)){ //读触摸按键的电平
			OLED_DISPLAY_8x16_BUFFER(6,"  Angle 180     "); //显示字符串
			TIM_SetCompare3(TIM3,7500);        //改变比较值TIM3->CCR2达到调节占空比的效果
		}
	}
}

三:DHT11芯片(DHT11温湿度显示程序)

温湿度传感器         

 

引脚说明

串行接口

 通信过程

每一个波形的事件长度

 

数字0 1信号表示方法

 

 新建文件夹

Hardware文件夹——>DHT11文件夹——>dht11.c  dht11.h

通过程序对波形图的高低电平进行采样判断:有些部分需要输出,有些部分需要输入,通过while循环不断判断高低电平的开始位置,再通过延时函数判断数据位是"1"还是"0"

最终将5个字节数据读取进来进行数据校验,校验好后再放入到对应的变量当中,在主函数当中将读到的温度湿度数据以十进制数的方式进行显示,最终就达到了程序效果         

dht11.h

#ifndef __DHT11_H
#define __DHT11_H	 
#include "sys.h"
#include "delay.h"

#define DHT11PORT	GPIOA	//定义IO接口
#define DHT11_IO	GPIO_Pin_15	//定义IO接口


void DHT11_IO_OUT (void);
void DHT11_IO_IN (void);
void DHT11_RST (void);
u8 Dht11_Check(void); 	   
u8 Dht11_ReadBit(void); 
u8 Dht11_ReadByte(void); 
u8 DHT11_Init (void);
u8 DHT11_ReadData(u8 *h);
		 				    
#endif

dht11.c

#include "dht11.h"


//切换端口的工作状态(因为有输出也有输入)
void DHT11_IO_OUT (void){ //端口变为输出
	GPIO_InitTypeDef  GPIO_InitStructure; 	
    GPIO_InitStructure.GPIO_Pin = DHT11_IO; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)    
	GPIO_Init(DHT11PORT, &GPIO_InitStructure);
}

void DHT11_IO_IN (void){ //端口变为输入
	GPIO_InitTypeDef  GPIO_InitStructure; 	
    GPIO_InitStructure.GPIO_Pin = DHT11_IO; //选择端口号(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式       
	GPIO_Init(DHT11PORT, &GPIO_InitStructure);
}

void DHT11_RST (void){ //DHT11端口复位,发出起始信号(IO发送)
	DHT11_IO_OUT();
	GPIO_ResetBits(DHT11PORT,DHT11_IO); //	
	delay_ms(20); //拉低至少18ms						
	GPIO_SetBits(DHT11PORT,DHT11_IO); //							
	delay_us(30); //主机拉高20~40us
}

u8 Dht11_Check(void){ //等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)	   
    u8 retry=0;
    DHT11_IO_IN();//IO到输入状态	 
    while (GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//DHT11会拉低40~80us
        retry++;
        delay_us(1);
    }	 
    if(retry>=100)return 1; else retry=0;
    while (!GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//DHT11拉低后会再次拉高40~80us
        retry++;
        delay_us(1);
    }
    if(retry>=100)return 1;	    
    return 0;
}

u8 Dht11_ReadBit(void){ //从DHT11读取一个位 返回值:1/0
    u8 retry=0;
    while(GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//等待变为低电平
        retry++;
        delay_us(1);
    }
    retry=0;
    while(!GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO)&&retry<100){//等待变高电平
        retry++;
        delay_us(1);
    }
    delay_us(40);//等待40us	//用于判断高低电平,即数据1或0
    if(GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO))return 1; else return 0;		   
}

u8 Dht11_ReadByte(void){  //从DHT11读取一个字节  返回值:读到的数据
    u8 i,dat;
    dat=0;
    for (i=0;i<8;i++){ 
        dat<<=1; 
        dat|=Dht11_ReadBit();
    }						    
    return dat;
}

u8 DHT11_Init (void){	//DHT11初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | 
                           RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE); //APB2外设时钟使能      
	DHT11_RST();//DHT11端口复位,发出起始信号
	return Dht11_Check(); //等待DHT11回应
}

u8 DHT11_ReadData(u8 *h){ //读取一次数据//湿度值(十进制,范围:20%~90%) ,温度值(十进制,范围:0~50°),返回值:0,正常;1,失败 
    u8 buf[5];
    u8 i;
    DHT11_RST();//DHT11端口复位,发出起始信号
    if(Dht11_Check()==0){ //等待DHT11回应
        for(i=0;i<5;i++){//读取5位数据
            buf[i]=Dht11_ReadByte(); //读出数据
        }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){	//数据校验
            *h=buf[0]; //将湿度值放入指针1
			h++;
            *h=buf[2]; //将温度值放入指针2
        }
    }else return 1;
    return 0;	    
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"

#include "dht11.h"


int main (void){//主程序
	u8 b[2];
	delay_ms(1000); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 
	RELAY_Init();//继电器初始化

	I2C_Configuration();//I2C初始化
	OLED0561_Init(); //OLED初始化
	OLED_DISPLAY_8x16_BUFFER(0,"   YoungTalk    "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(2,"   DHT11 TEST   "); //显示字符串

	if(DHT11_Init()==0){ //DHT11初始化	返回0成功,1失败
		OLED_DISPLAY_8x16_BUFFER(4,"Humidity:   %   "); //显示字符串
		OLED_DISPLAY_8x16_BUFFER(6,"Temperature:   C"); //显示字符串
	}else{
		OLED_DISPLAY_8x16_BUFFER(4,"DHT11INIT ERROR!"); //显示字符串
	}
	delay_ms(1000);//DHT11初始化后必要的延时(不得小于1秒)
	while(1){
		if(DHT11_ReadData(b)==0){//读出温湿度值  指针1是湿度 20~90%,指针2是温度 0~50C,数据为十进制
			OLED_DISPLAY_8x16(4,9*8,b[0]/10 +0x30);//显示湿度值
			OLED_DISPLAY_8x16(4,10*8,b[0]%10 +0x30);//
			OLED_DISPLAY_8x16(6,12*8,b[1]/10 +0x30);//显示温度值
			OLED_DISPLAY_8x16(6,13*8,b[1]%10 +0x30);//
		}else{
			OLED_DISPLAY_8x16_BUFFER(6,"DHT11READ ERROR!"); //显示字符串
		}
		delay_ms(1000); //延时,刷新数据的频率(不得小于1秒)
	}
}

四:MPU6050(六轴加速度和陀螺仪传感器芯片

可以实现对自身位移和旋转角度的感知 

加速度传感器:检测位移

陀螺仪传感器:检测方向和旋转的运动

MPU6050原始数据显示程序

 

 

新建文件夹

Hardware文件夹——>MPU6050文件夹——>MPU6050.c  MPU6050.h

MPU6050.h

#ifndef __MPU6050_H
#define __MPU6050_H	 
#include "sys.h"
#include "i2c.h"    //i2c总线通信
#include "delay.h"


#define MPU6050_ADD	0xD0	//器件地址(AD0悬空或低电平时地址是0xD0,为高电平时为0xD2,7位地址:1101 000x)


#define MPU6050_RA_XG_OFFS_TC       0x00 
#define MPU6050_RA_YG_OFFS_TC       0x01 
#define MPU6050_RA_ZG_OFFS_TC       0x02 
#define MPU6050_RA_X_FINE_GAIN      0x03 
#define MPU6050_RA_Y_FINE_GAIN      0x04 
#define MPU6050_RA_Z_FINE_GAIN      0x05 
#define MPU6050_RA_XA_OFFS_H        0x06 
#define MPU6050_RA_XA_OFFS_L_TC     0x07
#define MPU6050_RA_YA_OFFS_H        0x08 
#define MPU6050_RA_YA_OFFS_L_TC     0x09
#define MPU6050_RA_ZA_OFFS_H        0x0A 
#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
#define MPU6050_RA_XG_OFFS_USRH     0x13 
#define MPU6050_RA_XG_OFFS_USRL     0x14
#define MPU6050_RA_YG_OFFS_USRH     0x15 
#define MPU6050_RA_YG_OFFS_USRL     0x16
#define MPU6050_RA_ZG_OFFS_USRH     0x17 
#define MPU6050_RA_ZG_OFFS_USRL     0x18
#define MPU6050_RA_SMPLRT_DIV       0x19 
#define MPU6050_RA_CONFIG           0x1A 
#define MPU6050_RA_GYRO_CONFIG      0x1B 
#define MPU6050_RA_ACCEL_CONFIG     0x1C 
#define MPU6050_RA_FF_THR           0x1D 
#define MPU6050_RA_FF_DUR           0x1E
#define MPU6050_RA_MOT_THR          0x1F
#define MPU6050_RA_MOT_DUR          0x20
#define MPU6050_RA_ZRMOT_THR        0x21
#define MPU6050_RA_ZRMOT_DUR        0x22
#define MPU6050_RA_FIFO_EN          0x23
#define MPU6050_RA_I2C_MST_CTRL     0x24
#define MPU6050_RA_I2C_SLV0_ADDR    0x25
#define MPU6050_RA_I2C_SLV0_REG     0x26
#define MPU6050_RA_I2C_SLV0_CTRL    0x27
#define MPU6050_RA_I2C_SLV1_ADDR    0x28
#define MPU6050_RA_I2C_SLV1_REG     0x29
#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
#define MPU6050_RA_I2C_SLV2_REG     0x2C
#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
#define MPU6050_RA_I2C_SLV3_REG     0x2F
#define MPU6050_RA_I2C_SLV3_CTRL    0x30
#define MPU6050_RA_I2C_SLV4_ADDR    0x31
#define MPU6050_RA_I2C_SLV4_REG     0x32
#define MPU6050_RA_I2C_SLV4_DO      0x33
#define MPU6050_RA_I2C_SLV4_CTRL    0x34
#define MPU6050_RA_I2C_SLV4_DI      0x35
#define MPU6050_RA_I2C_MST_STATUS   0x36
#define MPU6050_RA_INT_PIN_CFG      0x37
#define MPU6050_RA_INT_ENABLE       0x38
#define MPU6050_RA_DMP_INT_STATUS   0x39
#define MPU6050_RA_INT_STATUS       0x3A
#define MPU6050_RA_ACCEL_XOUT_H     0x3B
#define MPU6050_RA_ACCEL_XOUT_L     0x3C
#define MPU6050_RA_ACCEL_YOUT_H     0x3D
#define MPU6050_RA_ACCEL_YOUT_L     0x3E
#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
#define MPU6050_RA_ACCEL_ZOUT_L     0x40
#define MPU6050_RA_TEMP_OUT_H       0x41
#define MPU6050_RA_TEMP_OUT_L       0x42
#define MPU6050_RA_GYRO_XOUT_H      0x43
#define MPU6050_RA_GYRO_XOUT_L      0x44
#define MPU6050_RA_GYRO_YOUT_H      0x45
#define MPU6050_RA_GYRO_YOUT_L      0x46
#define MPU6050_RA_GYRO_ZOUT_H      0x47
#define MPU6050_RA_GYRO_ZOUT_L      0x48
#define MPU6050_RA_EXT_SENS_DATA_00 0x49
#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
#define MPU6050_RA_EXT_SENS_DATA_07 0x50
#define MPU6050_RA_EXT_SENS_DATA_08 0x51
#define MPU6050_RA_EXT_SENS_DATA_09 0x52
#define MPU6050_RA_EXT_SENS_DATA_10 0x53
#define MPU6050_RA_EXT_SENS_DATA_11 0x54
#define MPU6050_RA_EXT_SENS_DATA_12 0x55
#define MPU6050_RA_EXT_SENS_DATA_13 0x56
#define MPU6050_RA_EXT_SENS_DATA_14 0x57
#define MPU6050_RA_EXT_SENS_DATA_15 0x58
#define MPU6050_RA_EXT_SENS_DATA_16 0x59
#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
#define MPU6050_RA_EXT_SENS_DATA_23 0x60
#define MPU6050_RA_MOT_DETECT_STATUS    0x61
#define MPU6050_RA_I2C_SLV0_DO      0x63
#define MPU6050_RA_I2C_SLV1_DO      0x64
#define MPU6050_RA_I2C_SLV2_DO      0x65
#define MPU6050_RA_I2C_SLV3_DO      0x66
#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
#define MPU6050_RA_MOT_DETECT_CTRL      0x69
#define MPU6050_RA_USER_CTRL        0x6A
#define MPU6050_RA_PWR_MGMT_1       0x6B	//电源管理专用寄存器
#define MPU6050_RA_PWR_MGMT_2       0x6C
#define MPU6050_RA_BANK_SEL         0x6D
#define MPU6050_RA_MEM_START_ADDR   0x6E
#define MPU6050_RA_MEM_R_W          0x6F
#define MPU6050_RA_DMP_CFG_1        0x70
#define MPU6050_RA_DMP_CFG_2        0x71
#define MPU6050_RA_FIFO_COUNTH      0x72
#define MPU6050_RA_FIFO_COUNTL      0x73
#define MPU6050_RA_FIFO_R_W         0x74
#define MPU6050_RA_WHO_AM_I         0x75   /


void MPU6050_Init(void);
void MPU6050_READ(u16* n);   

		 				    
#endif

MPU6050.c 

#include "MPU6050.h"


void MPU6050_Init(void){  //初始化MPU6050
	I2C_SAND_BYTE(MPU6050_ADD,MPU6050_RA_PWR_MGMT_1,0x80);//解除休眠状态    最高位的数据为1,从而进入复位状态
	delay_ms(1000); //等待器件就绪
	I2C_SAND_BYTE(MPU6050_ADD,MPU6050_RA_PWR_MGMT_1,0x00);//解除休眠状态
	I2C_SAND_BYTE(MPU6050_ADD,MPU6050_RA_SMPLRT_DIV,0x07);//陀螺仪采样率
	I2C_SAND_BYTE(MPU6050_ADD,MPU6050_RA_CONFIG,0x06);	 
	I2C_SAND_BYTE(MPU6050_ADD,MPU6050_RA_ACCEL_CONFIG,0x00);//配置加速度传感器工作在16G模式
	I2C_SAND_BYTE(MPU6050_ADD,MPU6050_RA_GYRO_CONFIG,0x18);//陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
}

void MPU6050_READ(u16* n){ //读出X、Y、Z三轴加速度/陀螺仪原始数据 //n[0]是AX,n[1]是AY,n[2]是AZ,n[3]是GX,n[4]是GY,n[5]是GZ 
	u8 i;
    u8 t[14]; 
    I2C_READ_BUFFER(MPU6050_ADD, MPU6050_RA_ACCEL_XOUT_H, t, 14); //读出连续的数据地址,包括了加速度和陀螺仪共12字节
    for(i=0; i<3; i++) 	//整合加速度
      n[i]=((t[2*i] << 8) + t[2*i+1]);
    for(i=4; i<7; i++)	//整合陀螺仪
      n[i-1]=((t[2*i] << 8) + t[2*i+1]);        
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "relay.h"
#include "oled0561.h"

#include "MPU6050.h"


int main (void){//主程序
	u16 t[6]={0};
	delay_ms(500); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 
	RELAY_Init();//继电器初始化

	I2C_Configuration();//I2C初始化

	OLED0561_Init(); //OLED初始化
	OLED_DISPLAY_8x16_BUFFER(0,"  MPU6050 TEST  "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(2,"X:       X:     "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(4,"Y:       Y:     "); //显示字符串
	OLED_DISPLAY_8x16_BUFFER(6,"Z:       Z:     "); //显示字符串

	MPU6050_Init(); //MPU6050初始化

	while(1){
		MPU6050_READ(t);	//加速度
		//其中t[0~2]是加速度ACCEL,t[3~5]是陀螺仪GYRO
		OLED_DISPLAY_8x16(2,2*8,t[0]/10000 +0x30);//显示
		OLED_DISPLAY_8x16(2,3*8,t[0]%10000/1000 +0x30);//显示
		OLED_DISPLAY_8x16(2,4*8,t[0]%1000/100 +0x30);//
		OLED_DISPLAY_8x16(2,5*8,t[0]%100/10 +0x30);//
		OLED_DISPLAY_8x16(2,6*8,t[0]%10 +0x30);//
		OLED_DISPLAY_8x16(2,11*8,t[3]/10000 +0x30);//显示
		OLED_DISPLAY_8x16(2,12*8,t[3]%10000/1000 +0x30);//显示
		OLED_DISPLAY_8x16(2,13*8,t[3]%1000/100 +0x30);//
		OLED_DISPLAY_8x16(2,14*8,t[3]%100/10 +0x30);//
		OLED_DISPLAY_8x16(2,15*8,t[3]%10 +0x30);//

		OLED_DISPLAY_8x16(4,2*8,t[1]/10000 +0x30);//显示
		OLED_DISPLAY_8x16(4,3*8,t[1]%10000/1000 +0x30);//显示
		OLED_DISPLAY_8x16(4,4*8,t[1]%1000/100 +0x30);//
		OLED_DISPLAY_8x16(4,5*8,t[1]%100/10 +0x30);//
		OLED_DISPLAY_8x16(4,6*8,t[1]%10 +0x30);//
		OLED_DISPLAY_8x16(4,11*8,t[4]/10000 +0x30);//显示
		OLED_DISPLAY_8x16(4,12*8,t[4]%10000/1000 +0x30);//显示
		OLED_DISPLAY_8x16(4,13*8,t[4]%1000/100 +0x30);//
		OLED_DISPLAY_8x16(4,14*8,t[4]%100/10 +0x30);//
		OLED_DISPLAY_8x16(4,15*8,t[4]%10 +0x30);//

		OLED_DISPLAY_8x16(6,2*8,t[2]/10000 +0x30);//显示
		OLED_DISPLAY_8x16(6,3*8,t[2]%10000/1000 +0x30);//显示
		OLED_DISPLAY_8x16(6,4*8,t[2]%1000/100 +0x30);//
		OLED_DISPLAY_8x16(6,5*8,t[2]%100/10 +0x30);//
		OLED_DISPLAY_8x16(6,6*8,t[2]%10 +0x30);//
		OLED_DISPLAY_8x16(6,11*8,t[5]/10000 +0x30);//显示
		OLED_DISPLAY_8x16(6,12*8,t[5]%10000/1000 +0x30);//显示
		OLED_DISPLAY_8x16(6,13*8,t[5]%1000/100 +0x30);//
		OLED_DISPLAY_8x16(6,14*8,t[5]%100/10 +0x30);//
		OLED_DISPLAY_8x16(6,15*8,t[5]%10 +0x30);//

		delay_ms(200); //延时(决定刷新速度)
	}
}

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

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

相关文章

极海APM32F003F6P6烧写问题解决记录

工作中遇到的&#xff0c;折腾了好久&#xff0c;因为电脑重装过一遍系统&#xff0c;软件也都重新安装了&#xff0c;所以不知道之前的配置是什么&#xff0c;旧项目代码编译没问题&#xff0c;烧写时疯狂报错&#xff0c;用的是JLink。 keil版本v5.14 win10版本 JLink版本…

PHP8的表达式-PHP8知识详解

表达式是 PHP 最重要的基石。在 PHP8中&#xff0c;几乎所写的任何东西都是一个表达式。简单但却最精确的定义一个表达式的方式就是"任何有值的东西"。 最基本的表达式形式是常量和变量。当键入"$a 5"&#xff0c;即将值"5"分配给变量 $a。&quo…

RocketMQ Learning

一、RocketMQ RocketMQ的产品发展 MetaQ&#xff1a;2011年&#xff0c;阿里基于Kafka的设计使用Java完全重写并推出了MetaQ 1.0版本 。 2012年&#xff0c;阿里对MetaQ的存储进行了改进&#xff0c;推出MetaQ 2.0&#xff0c;同年阿里把Meta2.0从阿里内部开源出来&am…

【Rust】Rust学习 第四章认识所有权

第四章认识所有权 所有权&#xff08;系统&#xff09;是 Rust 最为与众不同的特性&#xff0c;它让 Rust 无需垃圾回收&#xff08;garbage collector&#xff09;即可保障内存安全。因此&#xff0c;理解 Rust 中所有权如何工作是十分重要的。 4.1 所有权 所有运行的程序都…

行业报告 | 大模型助力产业,持续推进人工智能科技创新

原创 | 文 BFT机器人 随着AI应用深入千行百业&#xff0c;大模型在多个产业领域发挥着积极的作用。英伟达、META、微软等多家公司纷纷宣布AI相关行业的合作和并购机会&#xff0c;加速研发各垂类领域AI大模型&#xff0c;算力需求有望持续向上。 英伟达&#xff1a;宣布5000万…

[oeasy]python0081_[趣味拓展]ESC键进化历史_键盘演化过程_ANSI_控制序列_转义序列_CSI

光标位置 回忆上次内容 上次了解了 新的转义模式 \033 逃逸控制字符 escape 这个字符 让字符串 退出标准输出流进行控制信息的设置 可以设置 光标输出的位置 ASR33中的ALT MODE 是 今天的ESC键吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#x1f914; 查询文档…

2023-08-06 LeetCode每日一题(24. 两两交换链表中的节点)

2023-08-06每日一题 一、题目编号 24. 两两交换链表中的节点二、题目链接 点击跳转到题目位置 三、题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0…

MySQL索引原理以及SQL优化

文章目录 一、索引1.1 索引分类1.1.1 按数据结构分类1.1.2 按物理存储分类1.1.3 按列属性分类1.1.4 按列的个数索引 1.2 索引的代价1.3 索引的使用场景1.4 不使用索引的场景 二、索引的实现原理2.1 索引存储2.2 页2.3 InnoDB中的B树2.4 InnoDB的体系结构2.5 最左匹配原则2.6 覆…

人工智能自然语言处理:抽取式文本分割(Text Segmentation)算法介绍总结,智能断句解决文本过长问题

NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等 专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型…

快速修复应用程序中的问题的利器—— Android热修复

热修复技术在Android开发中扮演着重要的角色&#xff0c;它可以帮助开发者在不需要重新发布应用程序的情况下修复已经上线的应用程序中的bug或者添加新的功能。 一、热修复是什么&#xff1f; 热修复&#xff08;HotFix&#xff09;是一种在运行时修复应用程序中的问题的技术…

2023/08/05【网络课程总结】

1. 查看git拉取记录 git reflog --dateiso|grep pull2. TCP/IP和OSI七层参考模型 3. DNS域名解析 4. 预检请求OPTIONS 5. 渲染进程的回流(reflow)和重绘(repaint) 6. V8解析JavaScript 7. CDN负载均衡的简单理解 8. 重学Ajax 重学Ajax满神 9. 对于XML的理解 大白话叙述XML是…

图像 检测 - RetinaNet: Focal Loss for Dense Object Detection (arXiv 2018)

图像 检测 - RetinaNet: Focal Loss for Dense Object Detection - 密集目标检测中的焦点损失&#xff08;arXiv 2018&#xff09; 摘要1. 引言2. 相关工作References 声明&#xff1a;此翻译仅为个人学习记录 文章信息 标题&#xff1a;RetinaNet: Focal Loss for Dense Obje…

Matlab进阶绘图第25期—三维密度散点图

三维密度散点图本质上是一种特征渲染的三维散点图&#xff0c;其颜色表示某一点所在区域的密度信息。 除了作图&#xff0c;三维密度散点图绘制的关键还在于密度的计算。 当然&#xff0c;不管是作图还是密度的计算&#xff0c;这些在《Matlab论文插图绘制模板》和《Matlab点…

小研究 - 基于 MySQL 数据库的数据安全应用设计(二)

信息系统工程领域对数据安全的要求比较高&#xff0c;MySQL 数据库管理系统普遍应用于各种信息系统应用软件的开发之中&#xff0c;而角色与权限设计不仅关乎数据库中数据保密性的性能高低&#xff0c;也关系到用户使用数据库的最低要求。在对数据库的安全性进行设计时&#xf…

学习笔记-JAVAJVM-JVM的基本结构及概念

申明&#xff1a;文章内容是本人学习极客时间课程所写&#xff0c;文字和图片基本来源于课程资料&#xff0c;在某些地方会插入一点自己的理解&#xff0c;未用于商业用途&#xff0c;侵删。 原资料地址&#xff1a;课程资料 什么是JVM 原文连接&#xff1a; 原文连接 JVM是J…

即将发布的 Kibana 版本可运行 Node.js 18

作者&#xff1a;Thomas Watson Kibana 构建在 Node.js 框架之上。 为了确保每个 Kibana 版本的稳定性和使用寿命&#xff0c;我们始终将捆绑的 Node.js 二进制文件保持为最新的最新长期支持 (LTS) 版本。 当 Node.js 版本 18 升级到 LTS 时&#xff0c;我们开始将 Kibana 升级…

【WebRTC---源码篇】(二十三)JitterBuffer

PacketBuffer packetbuffer类中重要的一些变量 // buffer_.size() and max_size_ must always be a power of two.const size_t max_size_;//能存储的最大元素个数// The fist sequence number currently in the buffer.uint16_t first_seq_num_ RTC_GUARDED_BY(crit_);//这个…

Canmv K210开发板训练自己的模型

文章目录 前言​一、为什么选择Canmv开发板&#xff1f;二、利用Maix Hub在线训练三、配置开发环境1.MaixPy IDE2.刷指定固件 四、部署在Canmv开发板上五、测试模型 前言​ 关于Canmv开发板的介绍&#xff1a; CanMV K210 AI开发板全网首发&#xff0c;项目代码完全开源&#x…

C++数据结构之平衡二叉搜索树(一)——AVL的实现(zig与zag/左右双旋/3+4重构)

本文目录 00.BBST——平衡二叉搜索树01.AVL树02.AVL的插入2.1单旋——zig 与 zag2.2插入节点后的单旋实例2.3手玩小样例2.4双旋实例2.5小结 03.AVL的删除3.1单旋删除3.2双旋删除3.3小结 04.34重构05.综合评价AVL5.1优点5.2缺点 06.代码注意插入算法删除算法完整代码&#xff1a…