• Stm32_标准库_11_ADC_光敏&热敏传感器_测数值


    在测量光敏传感器数值得基础上手动将通道改成热敏传感器通道即可

    在这里插入图片描述
    由于温度传感器的测量范围是-20 ~ 105摄氏度,所以输出温度得考虑带上符号这就需要在原有输出光照强度代码的基础上新添加几个函数

    函数1:

    uint16_t AD_Getvailue(uint8_t ADC_Channel){//获取信息
    	      /*在规则组列表第一个位置,写入通道0这个通道*/
    	   ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);
    	   ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发转换
    	   while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换完成
    	   return ADC_GetConversionValue(ADC1);//读取数据
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在获取模拟电压函数最开始写入通道函数方便接入GPIO_1或GPIO_0

    函数2:

    uint8_t Length(uint16_t num){
    	  uint8_t length = 0;
    	  if(num == 0) return (uint8_t) 1;
    	  while(num > 0){
    		   num = num / 10;
    		   length = length + 1;
    	  }
    	  return length;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    求无符号数字的长度函数,方便后续清屏

    函数3:

    uint8_t SignedNum_Length(int32_t num){
    	      uint8_t length = 1;//符号位占1位
    	      if(num == 0) return (uint8_t) 1;
    	      if(num < 0) num = - num;
    	      while(num > 0){
    					   num = num / 10;
    					   length = length + 1;
    				}
    	      return length;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    求有符号数字的长度重点考虑到符号也要占一位

    函数4:

    int32_t Reality_Tmperature(uint16_t Vout){//获取实际温度
    	   double T = 0;//获取的实际温度
    	  
    	   T = -0.0423 * Vout + 105 + 0.5;//模拟电压转实际温度公式
    	   
    		 return (int32_t) T;
    		 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    获取实际温度的公式,重点讲输入的模拟电压Vout转换成日常用的摄氏度

    除此之外还将库函数输出OLED带符号位的函数也做了修改

    在这里插入图片描述
    函数:

    void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
    {
    	uint8_t i;
    	uint32_t Number1;
    	Length = Length - 1;
    	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');
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    由于此函数在写入带符号数字时是不考虑符号的额外长度的所以为了更好配合SignedNum_Length(int32_t num);函数所以我对其也进行了修改

    完整代码如下:

    #include "stm32f10x.h"    // Device header
    #include "Delay.h"
    #include "OLED.h"
    
    GPIO_InitTypeDef GPIO_InitStruct;
    ADC_InitTypeDef ADC_InitStruct;
    
    
    void AD_Init(void){//初始化AD
    	   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//开启ADC1的时钟
    	   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟
    	   RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模块工作时钟 72 / 6 = 12MHZ
    	   
    	   /*配置GPIO口*/
    	   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
    	   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
    	   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	   GPIO_Init(GPIOA, &GPIO_InitStruct);
    	   
    	   /*在规则组列表第一个位置,写入通道0这个通道*/
    	   //ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
    	
    	   /*结构体初始化ADC*/
    	   ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//单次转换
    	   ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
    	   ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发方式,不使用外部触发,即软件触发
    	   ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式为独立模式
    	   ADC_InitStruct.ADC_NbrOfChannel = 1;//通道数目
    	   ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非扫描
    	   ADC_Init(ADC1, &ADC_InitStruct);
    		 
    		 //开启ADC电源
    		 ADC_Cmd(ADC1, ENABLE);
    		 
    		 /*给ADC校准*/
    		 ADC_ResetCalibration(ADC1);//复位校准
    		 while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1复位校准状态
    		 ADC_StartCalibration(ADC1);//开始校准
    		 while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
    }
     
    uint16_t AD_Getvailue(uint8_t ADC_Channel){//获取信息
    	      /*在规则组列表第一个位置,写入通道0这个通道*/
    	   ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);
    	   ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发转换
    	   while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换完成
    	   return ADC_GetConversionValue(ADC1);//读取数据
    }
    uint8_t Length(uint16_t num){
    	  uint8_t length = 0;
    	  if(num == 0) return (uint8_t) 1;
    	  while(num > 0){
    		   num = num / 10;
    		   length = length + 1;
    	  }
    	  return length;
    }
    
    uint8_t SignedNum_Length(int32_t num){
    	      uint8_t length = 1;//符号位占1位
    	      if(num == 0) return (uint8_t) 1;
    	      if(num < 0) num = - num;
    	      while(num > 0){
    					   num = num / 10;
    					   length = length + 1;
    				}
    	      return length;
    }
    uint16_t Reality_ADLight(uint16_t ADCnum){//获取光照强度
    	  return 100 - ADCnum / 40;
    }
    
    
    int32_t Reality_Tmperature(uint16_t Vout){//获取实际温度
    	   double T = 0;//获取的实际温度
    	  
    	   T = -0.0423 * Vout + 105 + 0.5;//模拟电压转实际温度公式
    	   
    		 return (int32_t) T;
    		 
    }
    
    void OLED_Tmperature_Printf(uint8_t line, uint8_t col ,int32_t num, uint8_t length){
    	   if(num == 0){
    			 OLED_ShowNum(line, col, num, length);
    		 }
    		 else{
    			    OLED_ShowSignedNum(line, col, num, length);
    		 }
    }
    
     
    int main(void){
    	 
    	OLED_Init();//初始化OLED
    	AD_Init();
    	
    	while(1){
    		    uint16_t num  = AD_Getvailue(ADC_Channel_0);
    		    uint16_t num1 = Reality_ADLight(num); 
    		    uint16_t NUM =  AD_Getvailue(ADC_Channel_1);
    		    int32_t NUM1 =  Reality_Tmperature(NUM);
    		    
    		  
    		    OLED_ShowString(1, 1, "ADO:");
    		    OLED_ClearLocation(1, Length(num) + 3);//"ADO:"长度为3所以要加3
            OLED_ShowNum(1, 5, num, Length(num));
    		    OLED_ShowString(2, 1, "LUX:");
    		    OLED_ClearLocation(2, Length(num1) + 3);
    		    OLED_ShowNum(2, 5, num1, Length(num1));
    		
    		     
    		     OLED_ShowString(3, 1, "wendu:");
    		     OLED_ShowNum(3, 7, NUM, Length(NUM));
    		     OLED_ClearLocation(3, Length(NUM) + 6);
    		    OLED_Tmperature_Printf(4, 1, NUM1, SignedNum_Length(NUM1));
    		    OLED_ClearLocation(4, SignedNum_Length(NUM1));
    		
    		    Delay_ms(300);
    			 
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    效果:

    在这里插入图片描述

  • 相关阅读:
    实战演练 | 在 MySQL 中计算每日平均日期或时间间隔
    [vue]vuex
    中手游上半年扭亏为盈,仙剑IP魅力不减?
    Go 企业级框架 Gin 版全新发布
    FPGA在汽车领域的应用简谈
    Java 网络编程 —— 创建非阻塞的 HTTP 服务器
    【Redis】List类型
    [Android 四大组件] --- Activity
    Django之视图
    聊一聊如何使用Crank给我们的类库做基准测试
  • 原文地址:https://blog.csdn.net/xyint/article/details/133818184