7.DTH11和PWM波

目录

室内/本地温湿度检测

温湿度传感器介绍

获取手册和例程的方法

从手册中提取重要信息

传感器的分类

温度传感器类型

DHT11 的介绍

温湿度传感器的接口

温湿度传感器的时序

温湿度传感器电路介绍

IO 的配置

定时器输出 PWM 波

PWM 波介绍

PWM 波的作用:

基本定时器知识

输出 PWM 波

通用定时器输出 PWM 波

PWM 波相关的硬件

PWM 波代码实现

代码


室内/本地温湿度检测 

温湿度传感器介绍

        获取温度和湿度 -- DHT11 

获取手册和例程的方法

找厂家官网  立创商城

从手册中提取重要信息

        供电: 

                接口:常见的接口

        数字接口:串口 单总线 IIC SPI CAN 

        模拟接口:ADC 

        协议数据格式:有了物理层,如何确定能够通信上,获取数据

传感器的分类

        数字接口的传感器: 

                串口 单总线 IIC SPI CAN 这些接口一般都是数字接口的传感器 

        模拟接口的传感器: 

                电压接口或者电流接口这种叫做模拟接口传感器,采集模拟接口的传感器就需要用 ADC 

温度传感器类型

        常见的温度传感器(热敏电阻)-PT100 NTC1000

        NTC 和 PTC 一个是正温度系数,一个是负温度系数,正温度系数 温度越高,电阻越大,负温度系数,温度越高,电阻越小

DHT11 的介绍

 

温湿度传感器的接口

温湿度传感器的时序

        主从结构:主机主动发送,从机被动回复,从机不能主动发送数据 

温湿度传感器电路介绍

IO 的配置

        (1)配置成开漏输出 

                开漏只能输出低电平,通过上拉电阻实现高电平,空闲的时候(双方都不拉低的时候)就是高电平 

        (2)配置成通用推挽输出和浮空输入两种模式切换 

                主机控制部分,配置成通用推挽输出

                从机控制部分,配置成浮空输入 

定时器输出 PWM 波

PWM 波介绍

        PWM 波 -- 脉宽可调制波形 

        脉宽:指高电平持续的时间 

        占空比:一个周期内 高电平的时间占总周期的的百分比 

PWM 波的作用:

        1. 呼吸灯 

                本质上是快速的亮灭在切换,人眼有视觉暂留,区分不出来 

                相同周期内亮灭的时间不一致,人眼能察觉出来亮度不一样 

        2. 电机调速 

                和呼吸灯的原理是一样的 

                呼吸灯和电机调速都是惯性系统(不会立马停止) 

        3. 通信 -- 抗干扰能力比较强 

                电动汽车充电桩里面 和 舵机 

                27% 3.5KW 

                54% 7KW 

                舵机 不同占空比转动不同的角度 

        4. 输出 0--到 Vmax 之间的任意电压

                 面积等效原理 

                设备没有 2.5V 的电源,想实现 2.5V 的电压输出,就用上面的面积等效方法。就可以输出 0--5V 的任意电压,这个功能叫做 DAC(数字量转换模拟量)

基本定时器知识

        系统(滴答)定时器 -- systick -- 内核 ARM 公司 

        基本定时器 -- TIM6 TIM7 -- 只有基本的定时器功能

        通用定时器 -- TIM2 TIM3 TIM4 TIM5 -- 基本定时器功能+PWM+输入捕获 

        高级定时器 -- TIM1 TIM8 -- 通用定时器的基础上 + 死区 +刹车(电机使用) 

        窗口看门狗 独立看门狗 RTC --本质上都是定时器 

        看门狗防止程序跑飞 

        时基单元 

        外设时钟的频率 所有的定时器都是 F=72M 

        预分频值 PSC 

        分频之后的计数的频率(CK_CNT) f=F/PSC 

        计一次数(更新 1 次数)的时间 t=1/f 

        重装载值 ARR 

        计数的周期 T= ARR*t=ARR*PSC/F 

输出 PWM 波

        (1) 定时器 + 手动 IO 翻转 

                比较值 30 

                重装载值 99 

                向上计数 

                当计数值<比较值 IO 口输出高电平 

                当计数值>比较值 IO 口输出低电平 

                注意:自己比较,IO 配置成通用推挽输出 

        (2) 带 PWM 波功能的通用定时器 

                比较值 30 

                重装载值 99 

                向上计数 

                当计数值<比较值 IO 口输出高电平 

                当计数值>比较值 IO 口输出低电平 

                注意:通过定时器的 PWM 外设自动比较,IO 配置成复用推挽输出

通用定时器输出 PWM 波

        基本定时器:没有 PWM 输出的功能,需要手动翻转 IO 口输出 PWM 

        重装载值和预分频值决定 PWM 频率和周期

        比较值和重装载值决定占空比 

        根据上图可得,每个通用(或者高级)定时器有 4 个 PWM 的输出端口,4 个通道周期是一致的,但是比较值(占空比)可以不一致 

        TIM6 和 TIM7 只有向上计数,其他定时器可以选择,向上计数,向下计数和中央对齐模式 

 

重点关注: 

        ARR 100(TIMx_ARR) 比较值 66(TIMx_CCR ) 

        PWM 模式 (TIMx_CCMRx 位 6:4)有效电平(TIMx_CCER 位 CCxP 位 1) 

PWM1 有效电平是高电平

        向上计数 0—66 输出有效电平(高电平) 66—100 输出无效电平(低电平) 占空比 CCR/ARR 

        向下计数 100—66 输出无效电平(低电平) 66—0 输出有效电平(高电平) 占空比 CCR/ARR 

PWM1 有效电平是低电平

        向上计数 0—66 输出有效电平(低电平) 66—100 输出无效电平(高电平) 占空比 (ARR-CCR)/ARR 

        向下计数 100—66 输出无效电平(高电平) 66—0 输出有效电平(低电平) 占空比 (ARR-CCR)/ARR 

PWM2 有效电平是高电平

PWM2 有效电平是低电平

        注意: CCR/ARR 并不一定是占空比,取决于 PWM 模式和有效电平,如果想 CCR/ARR 就是占空比,应该选择 PWM1,有效电平高电平或者 PWM2,有效电平低电平 

PWM 波相关的硬件

        LED1—LED4 所接的引脚,没有 TIMx_Chy 的标识,无法使用定时器的 PWM 功能,但是可以通过手动翻转 IO 控制 LED 灯亮度 

        RGB 接的引脚标识 TIMx_Chy,所以可以使用 TIM 的 PWM 功能

PWM 波代码实现

需要配置的结构体

        GPIO 模式

TIM

        决定了 PWM 波的周期和频率 

输出 PWM 有关的结构体 

        决定了 PWM 波的占空比

代码

DHT11

void DHT11_Config(void)
{
	//1.开G端口时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
	//2.定义结构体 xxx需要传递结构体地址
	GPIO_InitTypeDef GPIO_InitStruct = {0};//3.给结构体赋值
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;//代配置引脚
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//通用开漏
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//引脚速率
	GPIO_Init(GPIOG, &GPIO_InitStruct);
	//先释放总线,因为刚开始就是高电平,不拉低
	GPIO_SetBits(GPIOG,GPIO_Pin_11);
}

uint8_t DHT11_Handle(void)
{
	uint8_t Time_out = 0;
	uint8_t i,j;
	uint8_t Buff[5]={0};
	uint8_t Data_Cs=0;//和校验
	//主机先拉低 位置1
	GPIO_ResetBits(GPIOG,GPIO_Pin_11);
	Delay_ms(18);
	//释放总线 位置2
	GPIO_SetBits(GPIOG,GPIO_Pin_11);
	//等待响应信号的低电平部分,低电平没到来之前一直是高电平
	while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)==Bit_SET)
	{//还未等到响应信号的低电平
		Time_out++;
		Delay_us(1);
		if(Time_out>=100)
		{//设备异常,响应失败,应答失败
			return 0;
		}
	}
	//等到响应信号低电平,然后时序到拉高准备输出,高电平没到来前一直是低电平 位置3
	Time_out=0;
	while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)==Bit_RESET)
	{//还未等到响应信号的高电平
		Time_out++;
		Delay_us(1);
		if(Time_out>=100)//传感器总线先拉低
		{//100us中有83us是响应信号的低电平,剩下17us等待响应信号高电平,如果17秒没等到,设备异常返回
			return 0;
		}
	}
	
	for(i=0;i<5;i++)
	{//5次
		for(j=0;j<8;j++)
		{//一次8位
			Time_out=0;
			//刚等到响应信号的高电平,等待数据位的低电平部分,数据位低电平没有到来之前,一直是高电平,位置4
			while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)==Bit_SET)
			{//还未等到响应信号的高电平
				Time_out++;
				Delay_us(1);
				if(Time_out>=100)//在拉高以 响应主机的起始信号
				{//100us中有87us是响应信号的高电平,剩下13us等待响应信号低电平,如果13秒没等到,设备异常返回
					return 0;
				}
			}
			Time_out=0;
			//刚等到数据位的低电平,等待数据位的高电平部分,数据位高电平没有到来之前,一直是低电平,位置5
			while(GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)==Bit_RESET)
			{//还未等到响应信号的高电平
				Time_out++;
				Delay_us(1);
				if(Time_out>=100)
				{//100us中有54us是响应信号的低电平,剩下46us等待响应信号高电平,如果46秒没等到,设备异常返回
					return 0;
				}
			}
			//刚等到数据位的高电平,延时30us,去区分收到的数据是0还是1,到位置6
			Delay_us(30);
			if((GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)==Bit_RESET))
			{//数据0,高位先发
				Buff[i] &= ~(0x01<<(7-j));		
			}
			else
			{//数据1,高位先发
				Buff[i] |= (0x01<<(7-j));
			}
		}
	}
	
	Data_Cs=Buff[0]+Buff[1]+Buff[2]+Buff[3];
	if(Data_Cs==Buff[4])
	{//校验正确
		if((Buff[3] & 0x80) == 0) //0001 1000
		{//正温
			Dht.Tem = (Buff[2]+(Buff[3] & 0x7F) * 0.1);
		}
		else
		{//负温
			Dht.Tem = - (Buff[2]+(Buff[3] & 0x7F) * 0.1);
		}
		Dht.Hum = Buff[0];
		printf("温度=%.1f ,湿度=%d\r\n", Dht.Tem, Dht.Hum);
		return 1;
	}
	else
	{
		printf("DHT11校验不正确\r\n");
		return 0;
	}
	return 0;
}

PWM

void PWM_Config(void)
{
	//1.开A端口时钟  
	//方法1:中文固件库手册 15.2.22  路径:授课大纲资料\1.项目分析与环境搭建\资料\芯片相关资料
	//方法2:找到对应的.h文件最下面   stm32f10x.h 693行
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//2.定义结构体  XXX_init需要传递结构体变量地址
	GPIO_InitTypeDef GPIO_InitStruct={0};
	
	//3.给结构体赋值  中文固件库手册,Table 182--Table 185
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6;//待配置的引脚
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//引脚速率
	
	//4.调用XXX_Init函数,将参数写入到寄存器中
	//void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);	
	//中文固件库手册:10.2.3
	//stm32f10x_gpio.h  351行
	GPIO_Init(GPIOA,&GPIO_InitStruct);	

	//5.开TIM3的时钟
	//void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); stm32f10x_rcc.h  693行
	//void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	
	//6.定义结构体   XXX_Init函数    void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct={0};
		
	//7.给结构体赋值
//	TIM_TimeBaseInitStruct.TIM_ClockDivision = //时钟分割 输入捕获才使用
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式,向上或者向下
	TIM_TimeBaseInitStruct.TIM_Period = TIM_ARR_Value-1;//重装载值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;//预分频值
//	TIM_TimeBaseInitStruct.TIM_RepetitionCounter	//该参数只用在高级定时器,晚上作业也不用配置

	//8.调用XXX_Init函数将参数写入到寄存器中
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);	
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);			
		
	//9.使能定时器   参考手册15.4.1  的位0置1
//void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);	 stm32f10x_tim.h 1067行
	TIM_Cmd(TIM3,ENABLE);	
	TIM_Cmd(TIM1,ENABLE);

	//10.定义PWM波相关的结构体
//具体用哪个函数,取决于CHx编号
//void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);	TIMx_CH1	 stm32f10x_tim.h 1057行 
//void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); TIMx_CH2
//void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); TIMx_CH3
//void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); TIMx_CH4
	TIM_OCInitTypeDef TIM_OCInitStruct={0};
	
	//11.给结构体赋值
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;  //PWM模式1
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //有效电平高电平
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  //输出使能
	TIM_OCInitStruct.TIM_Pulse = 66;//比较值 范围0--ARR之间
//	TIM_OCInitStruct.TIM_OCIdleState	//只用在高级定时器 TIM1 TIM8
//	TIM_OCInitStruct.TIM_OutputNState	//只用在高级定时器 TIM1 TIM8
//	TIM_OCInitStruct.TIM_OCNIdleState //只用在高级定时器 TIM1 TIM8
//	TIM_OCInitStruct.TIM_OCNPolarity	//只用在高级定时器 TIM1 TIM8
	
	//12.根据要设置的通道,调用对应的init函数,将参数写入寄存器
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);
	TIM_OC2Init(TIM3,&TIM_OCInitStruct);	
	TIM_OC1Init(TIM1,&TIM_OCInitStruct);
	
	//13.使能ARR预装载功能
//void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);	 stm32f10x_tim.h 1092行 
	TIM_ARRPreloadConfig(TIM3,ENABLE);
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	
	//14.使能比较值的预装载功能
//void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);  stm32f10x_tim.h 1096行 
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
	
	//15.高级定时器的PWM波功能加上这句话
//void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);  stm32f10x_tim.h 1068行 
	TIM_CtrlPWMOutputs(TIM1,ENABLE);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力做小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值