打印
[STM32F4]

STM32+ LCD- - 内部温度传感器

[复制链接]
2184|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chenqiang10|  楼主 | 2017-11-25 19:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA)。该温度传感器在内部和 ADCx_IN16 输入通道相连接,此通道把传感器输出的电压转换成数字值。温度传感器模拟输入推荐采样时间是 17.1μ s。 STM32 的内部温度传感器支持的温度范围为:-40~125 度。精度比较差,为±1.5℃左右。
沙发
chenqiang10|  楼主 | 2017-11-25 19:37 | 只看该作者
STM32 内部温度传感器的使用很简单,只要设置一下内部 ADC,并激活其内部通道就差不多了。接下来我们介绍一下和温度传感器设置相关的 2 个地方。
第一个地方,我们要使用 STM32 的内部温度传感器,必须先激活 ADC 的内部通道,这里通过 ADC_CR2 的 AWDEN 位( bit23)设置。设置该位为 1 则启用内部温度传感器。
第二个地方, STM32 的内部温度传感器固定的连接在 ADC 的通道 16 上,所以,我们在设置好 ADC 之后只要读取通道 16 的值,就是温度传感器返回来的电压值了。根据这个值,我们就可以计算出当前温度。计算公式如下:
T(℃) ={( V25-Vsense) /Avg_Slope}+25

使用特权

评论回复
板凳
chenqiang10|  楼主 | 2017-11-25 19:37 | 只看该作者
上式中:V25=Vsense 在 25 度时的数值(典型值为: 1.43)。Avg_Slope阿=温度与 Vsense 曲线的平均斜率(单位为 mv/℃或 uv/℃)(典型值为4.3Mv/℃)。利用以上公式,我们就可以方便的计算出当前温度传感器的温度了。

使用特权

评论回复
地板
chenqiang10|  楼主 | 2017-11-25 19:39 | 只看该作者
内部温度传感器的操作:
因为温度传感器使用的是 STM32 内部的 ADC,所以呢,温度传感器的设置 跟 ADC 的
设置是一样的,只是一个是读取外部的电压信号,一个是读取内部的 电压信号。只是开启
通道的时候,开启的温度传感器的通道,同时要打开温度传 感器的使能。

使用特权

评论回复
5
chenqiang10|  楼主 | 2017-11-25 19:39 | 只看该作者
初始化
上面说过温度传感器的操作其实跟 ADC 的初始化操作时差不多的,但 是它也用
到了一些新的函数:
1) ADC_TempSensorVrefintCmd() 函数
这个函数是用来开启内部温度传感器的,它有一个参数,用来选择 设置的状态。
开启的时候设置为:ENABLE。
初始化代码为:
void adc_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB
2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12M 最大 14M 设置 ADC 时钟(ADCCLK)
ADC_DeInit(ADC1);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//ADC
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;  //模拟输入
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);

使用特权

评论回复
6
chenqiang10|  楼主 | 2017-11-25 19:40 | 只看该作者
//设置指定 ADC 的规则组通道,设置它们的转化顺序和采样时间
//  ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);
//内部温度传感器是在 ADC1 通道 16 的。
ADC_RegularChannelConfig(ADC1,ADC_Channel_16,1,ADC_SampleTime_239Cycles5);
ADC_TempSensorVrefintCmd(ENABLE);//打开内部温度传感器使能
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);//重置指定的 ADC 的校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//获取 ADC 重置校准寄存器的状态
ADC_StartCalibration(ADC1);//开始指定 ADC 的校准状态
while(ADC_GetCalibrationStatus(ADC1));//获取指定 ADC 的校准程序
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能或者失能指定的 ADC 的软件转换
启动功能
}

使用特权

评论回复
7
chenqiang10|  楼主 | 2017-11-25 19:41 | 只看该作者
我们从 AD 读取出来的是 AD 值,那么我们如何将它转换为温度值呢? 转换温度的公式为:温度(°C) = {(V25 - VSENSE) / Avg_Slope} + 25。这里 V25 = VSENSE 在 25°C 时的数值(典型值为:1.43) ,Avg_Slope = 温度 与 VSENSE 曲线的平均斜率(单位为mV/ °C 或 μ V/ °C) (典型值为:4.3Mv/℃) 。一般这两个值是参考数据手册的电气特性。而 VSENSE 是指当 前读取到的电压值。

使用特权

评论回复
8
chenqiang10|  楼主 | 2017-11-25 19:42 | 只看该作者
int main()
{
u32 value;
float ad;
u8 i,j,dat[7];
adc_init();  //ADC 配置内部温度初始化
LED_Init();  //端口初始化
TFT_Init();  //TFT 彩屏初始化
printf_init();  //printf 初始化
TFT_ClearScreen(BLACK);  //清屏
GUI_Show12ASCII(10,10,"This is a ADC1-Channel16-Temp Check!",YELLOW,BLACK);
GUI_Show12ASCII(10,100,"The Temp Value is:",YELLOW,BLACK);
while(1)
{
value=0;
if(j>1)
{
j=0;
GPIO_SetBits(GPIOC,GPIO_Pin_0);
}
else
{
j++;
GPIO_ResetBits(GPIOC,GPIO_Pin_0);
}
delay_ms(100);  //LED 闪烁
for(i=0;i<50;i++)  //读取 50 此 AD 检测速度后求其平均值
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//转换结束标志位
value=value+ADC_GetConversionValue(ADC1);//返回最近一次 ADCx 规则组的转
换结果
}
value/=50;
ad=(1.43-value*3.3/4096)/0.0043+25;
value=ad*100;
dat[0]=value/1000+0x30;
dat[1]=value%1000/100+0x30;
dat[2]='.';
dat[3]=value%1000%100/10+0x30;
dat[4]=value%1000%100%10+0x30;
dat[5]='C';
dat[6]='\0';
GUI_Show12ASCII(160,100,dat,YELLOW,BLACK);
}
}

使用特权

评论回复
9
chenqiang10|  楼主 | 2017-11-25 19:43 | 只看该作者
主程序的效果是,读取到的 AD 值经过转换后位芯片内部温度数据,通过 LCD 彩屏进行显示,并且 LED 指示灯闪烁表示系统正在运行。注意:使用内部温度传感器检测温度是不准确的,误差比较大。因此通常是不采用此传感器进行测温。

使用特权

评论回复
10
chenqiang10|  楼主 | 2017-11-25 19:45 | 只看该作者
ds18B20初始化
void ds18b20_init()
{
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);

        GPIO_InitStructure.GPIO_Pin=dq;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOG,&GPIO_InitStructure);
}

使用特权

评论回复
11
mmuuss586| | 2017-11-25 20:25 | 只看该作者

不错,谢楼主分享;

使用特权

评论回复
12
chenqiang10|  楼主 | 2017-11-25 22:04 | 只看该作者
void DQININT()         //输入配置
{
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin=dq;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOG,&GPIO_InitStructure);       
}

使用特权

评论回复
13
chenqiang10|  楼主 | 2017-11-25 22:05 | 只看该作者
void DQOUTINT()         //输出配置
{
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin=dq;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOG,&GPIO_InitStructure);       
}

使用特权

评论回复
14
chenqiang10|  楼主 | 2017-11-25 22:06 | 只看该作者
ds18b20初始化
void ds18b20init()
{
        DQOUTINT();
        GPIO_SetBits(GPIOG,dq);
        delay_us(10);       
        GPIO_ResetBits(GPIOG,dq);
        delay_us(600);
        GPIO_SetBits(GPIOG,dq);
        delay_us(50);
        GPIO_ResetBits(GPIOG,dq);
        delay_us(200);
        GPIO_SetBits(GPIOG,dq);
        delay_us(400);
}

使用特权

评论回复
15
chenqiang10|  楼主 | 2017-11-25 22:07 | 只看该作者
DS18b20写数据
void ds18b20wr(u8 dat)
{
        u8 i;
        DQOUTINT();
        GPIO_SetBits(GPIOG,dq);
        delay_us(10);
        for(i=0;i<8;i++)               
        {
                GPIO_ResetBits(GPIOG,dq);
                if(dat&0x01==1)
                {
                        GPIO_SetBits(GPIOG,dq);       
                }
                else
                        GPIO_ResetBits(GPIOG,dq);
                dat>>=1;
                delay_us(60);
                GPIO_SetBits(GPIOG,dq);
                delay_us(10);       
        }
        GPIO_SetBits(GPIOG,dq);
        delay_us(10);
}

使用特权

评论回复
16
chenqiang10|  楼主 | 2017-11-25 22:11 | 只看该作者
ds18b20 读数据
u8 DS18b20rd()
{
        u8 i,value=0;//一定要给value附初值否则显示会错误       
        DQOUTINT();
        GPIO_SetBits(GPIOG,dq);
        for(i=0;i<8;i++)               
        {       
                GPIO_ResetBits(GPIOG,dq);
                value>>=1;
                GPIO_SetBits(GPIOG,dq);
                DQININT();
                if(GPIO_ReadInputDataBit(GPIOG,dq)==1)
                {
                        value|=0x80;
                }
                delay_us(50);
                DQOUTINT();       
                GPIO_SetBits(GPIOG,dq);
                delay_us(1);       
        }
        GPIO_SetBits(GPIOG,dq);
        delay_us(10);
        return value;       
}

使用特权

评论回复
17
chenqiang10|  楼主 | 2017-11-25 22:12 | 只看该作者
u8 readtemp()                          //读取温度
{
        u16 temp;
        float tp;
        u8 a,b;
        double value;
        ds18b20init();                //???
        ds18b20wr(0xcc);   //????ROM??
        ds18b20wr(0x44);   //????????
        delay_ms(800);
        ds18b20init();           //???
        ds18b20wr(0xcc);   //????ROM??
        ds18b20wr(0xbe);   //???????
        a=DS18b20rd();         //??????
        b=DS18b20rd();         //??????
        temp=b;
        temp=(temp<<8)|a;
        tp=temp;
  temp=tp*0.0625*100+0.5;       
        return temp;
}

使用特权

评论回复
18
chenqiang10|  楼主 | 2017-11-25 22:15 | 只看该作者
关于TFT的
初始化TFT的IO
void TFT_GPIO_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        /* 打开时钟使能 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE  
                              | RCC_APB2Periph_GPIOG, ENABLE);

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        /* FSMC_A10(G12) 和RS(G0)*/
        GPIO_Init(GPIOG, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4
                                      | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_8
                                                                  | GPIO_Pin_9 | GPIO_Pin_10 |GPIO_Pin_11
                                                                  | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14
                                                                  | GPIO_Pin_15 );

        GPIO_Init(GPIOD, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9
                                       | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12
                                                                   | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);

        GPIO_Init(GPIOE, &GPIO_InitStructure);
}


使用特权

评论回复
19
chenqiang10|  楼主 | 2017-11-25 22:17 | 只看该作者
初始化FSMC
void TFT_FSMC_Config(void)
{
        /* 初始化函数 */
        FSMC_NORSRAMInitTypeDef        FSMC_NORSRAMInitStructure;
        FSMC_NORSRAMTimingInitTypeDef  FSMC_NORSRAMTiming;

        /* 设置读写时序,给FSMC_NORSRAMInitStructure调用 */
        /* 地址建立时间,3个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_AddressSetupTime = 0x02;

        /* 地址保持时间,1个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_AddressHoldTime = 0x00;

        /* 数据建立时间,6个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_DataSetupTime = 0x05;

        /* 数据保持时间,1个HCLK周期 */
        FSMC_NORSRAMTiming.FSMC_DataLatency = 0x00;

        /* 总线恢复时间设置 */
        FSMC_NORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00;
       
        /* 时钟分频设置 */
        FSMC_NORSRAMTiming.FSMC_CLKDivision = 0x01;

        /* 设置模式,如果在地址/数据不复用时,ABCD模式都区别不大 */
        FSMC_NORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_B;

        /*设置FSMC_NORSRAMInitStructure的数据*/
        /* FSMC有四个存储块(bank),我们使用第一个(bank1) */
        /* 同时我们使用的是bank里面的第 4个RAM区 */
        FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;

        /* 这里我们使用SRAM模式 */
        FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;

        /* 使用的数据宽度为16位 */
        FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;

        /* 设置写使能打开 */
        FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

        /* 选择拓展模式使能,即设置读和写用不同的时序 */
        FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
       
        /* 设置地址和数据复用使能不打开 */
        FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
       
        /* 设置读写时序 */
        FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTiming;
       
        /* 设置写时序 */
        FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTiming;

        /* 打开FSMC的时钟 */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
         
        FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

        /*!< Enable FSMC Bank1_SRAM Bank */
        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);       
}

使用特权

评论回复
20
chenqiang10|  楼主 | 2017-11-25 22:20 | 只看该作者
LCD写入命令
void TFT_WriteCmd(uint16_t cmd)
{
        TFT->TFT_CMD = cmd<<8 ;
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

940

帖子

1

粉丝