sky-Hawk where 发表于 2012-10-1 18:46:08

PSoC3 FirstTouc Starter Kit 例子源代码之ThermistorTemperatureSense

本帖最后由 wangku001wei 于 2012-10-1 18:56 编辑

首先看原理图红色代表模拟引脚 绿色代表数字引脚
电路原理图

新使用了一个模拟复用器和8位的电压模数转换器,对应端口为VRefPort——P5——T_POWERVSignalPort——P5——T_SENSE
模拟复用端口采用了3个通路
采用这种方式的原因是为了降低热敏电阻上采集到的电压误差
根据电流相等,得到公式1                  公式1由公式1,推导,得到公式2,热敏电阻阻值公式:                   公式2注意,我们这个例子中 电压值V2为0aPort_YAxia 和三轴加速度的一个引脚向量dPort_AcclControl和三轴加速度的三个控制引脚相连,用于向加速度传感器写入命令dPort由8个IO口组成,且由于在POSC的端口设置中如果端口的位宽大于1,则在实际分配引脚时,这些端口必须是同一个Px口上的相邻IO口,因此dPort分为了高低各四位的dPort_LSB和dPort_MSBPdPort_LSB 对应P2口的P2控制dPort_MSB 对应P4口的P4控制同样的,反向是因为电路设计为低电平点亮LED,高电平熄灭LEDADC转换器选择了11位精度,连续转换方式,由软件开启ADC转换,时钟为内部804kHz 以上设置可以在引脚分配视图上看出


主函数代码分析/******************************************************************************************** 主函数的功能:* 1: 初始化所有的变量* 2: 关闭LED的灯* 3: 初始化加速度传感器* 4: 启动AD转换,读取加速度Y轴方向上的数据* 5: 测量温度并转换为字符串* 6: 将字符串转换为光栅像素数组* 7: 等待摇动.* 8: 以一定速度更新光栅数据********************************************************************************/void main(){
    uint8 RasterCount;             /*光栅像素数组的索引*/uint8 RasterLength;             /*当前字符串转换为光栅像素数据后的数组长度*/// 按键的状态    uint8 ButtonPressFlag;
/*初始化硬件*/    CYGlobalIntEnable;             /*使能全局中断*/LEDControlReg_Write(0);       /*熄灭LED灯*//*控制加速度传感器 ENABLE=1, MODE=1, ST/MODE=LOW */// #define ACCL_SET_CONTROL    ((uint8) 0x06)dPort_AcclControl_Write(ACCL_SET_CONTROL);AMux_1_Start();                /* 使能模拟复用器 */    AcclADC_Start();                /* 使能AD转换 */VDAC8_1_Start();                /* 使能电压模数转换器 */// 设置模数转换器的范围VDAC8_1_SetRange(VDAC8_1_RANGE_1V);// 设置模数转换器的值    VDAC8_1_SetValue(200 );

    while(1)    {      /* 读取按键的状态,当按键状态改变后,改变现实温度的格式,摄氏度或者华氏度 */      /* 栅格化的延时用于放置按键抖动. */      if(SwitchPort_Read() == 1)      {            if(ButtonPressFlag == 0)            {                TemperatureModeFlag = TemperatureModeFlag ^ 0x01;                ButtonPressFlag = 1;            }      }      else      {            ButtonPressFlag = 0;      }
      /* 计算当前温度 */      Thermistor_TemperatureCompute();
      /* 将当前温度转换为栅格化像素数组 */      RasterLength = LED_StringProcess(DisplayString);
      AMux_1_Select(2);      AcclADC_Stop();      AcclADC_Start();       /* 等待挥动开始 */      do      {      AcclADC_StartConvert();            AcclADC_IsEndConversion(AcclADC_WAIT_FOR_RESULT);      }while(AcclADC_GetResult16() > ACCEL_TRIGGER);
       /* 在LED 开始显示和开始挥动之间进行延时*/      LED_Delay(INITIAL_DELAY);
      /* 将每列光栅数据输送到8位LED上,同时每列光栅数据间进行延时 */      
for(RasterCount = 0; RasterCount < RasterLength; RasterCount++)      {            LED_Delay(RASTER_DELAY);            LEDControlReg_Write(DisplayRasterTable);      }
       /* 等待这次挥动结束 */      do      {            AcclADC_StartConvert();            AcclADC_IsEndConversion(AcclADC_WAIT_FOR_RESULT);      }while(AcclADC_GetResult16() < (255 - ACCEL_TRIGGER));    }}


关于得到测量温度的函数 Thermistor.c 文件中的void Thermistor_TemperatureCompute(void)函数
使用了查找表 表中记录了从-40到125摄氏度每隔1摄氏度对应的ADC采样值 整摄氏度之间的值采用线性插值的方法算出插值计算过程:TempTable_UpperLimit 对应的是表中索引小,温度低而实际值大的TempTable_LowerLimit 对应的是表中索引大,温度高而实际值小的ThermistorResistance ADC转换出来的值Thermistor_Temperature 是最终得到的温度数值,由于要保留1位小数,结果乘以了10TempTable_Decimal 计算过程中间临时保留的值,或者说是小数部分插值公式3                           公式3注1由于表是从-40度开始制作的,所以要减去40 由于是从较低的温度开始的,所以要减去1
代码分析void Thermistor_TemperatureCompute(void){   
    int32 ThermistorResistance;    /* 计算得到的热敏电阻上的电压数据 */    int16 Thermistor_Temperature;   /*计算得到的温度值,由于要保留1位小数,结果乘以了10 */    int Count=0;    uint16 ADC_VRef, ADC_VThermistor, ADC_VRefLow = 0;   /* ADC采样得到的值 */    long TempTable_UpperLimit, TempTable_LowerLimit;/* 线性插值变量 */    float TempTable_Decimal;                  /* 计算出的温度值的小数部分 */

   /* 启用模拟复用器通道0,并AD采集参考电阻上电压值 */    AMux_1_Select(0);    AcclADC_Stop();    AcclADC_Start();    AcclADC_StartConvert();    AcclADC_IsEndConversion(AcclADC_WAIT_FOR_RESULT);    ADC_VRef = AcclADC_GetResult16();
    /*启用模拟复用器通道1,并AD采集热敏电阻上电压值*/    AMux_1_Select(1);    AcclADC_Stop();    AcclADC_Start();    AcclADC_StartConvert();    AcclADC_IsEndConversion(AcclADC_WAIT_FOR_RESULT);    ADC_VThermistor = AcclADC_GetResult16();
    /* 根据公式2计算得到热敏电阻的阻值 */    ThermistorResistance= (((int32)(ADC_VThermistor - ADC_VRefLow) * (int32)THERM_RREF) / ((int32)(ADC_VRef - ADC_VThermistor)));
    /* 得到计算得到的阻值在查找表中的位置*/    for(Count = 0; Thermistor_TempTable >= ThermistorResistance; Count++);
/* 根据公式3插值计算温度值 */    TempTable_Decimal = 0;                    TempTable_LowerLimit = Thermistor_TempTable;    TempTable_UpperLimit = Thermistor_TempTable;
    TempTable_Decimal = ((TempTable_UpperLimit - ThermistorResistance) * 10) / (TempTable_UpperLimit - TempTable_LowerLimit);    Thermistor_Temperature = (Count - 40 - 1) * 10 + (TempTable_Decimal);
    /* 将整数温度值转换为字符型字符串 */    ThermistorTempToString(Thermistor_Temperature);}


关于将温度数值转换为能够显示的字符串的函数Thermistor.c 文件中的void ThermistorTempToString(int32 Temperature)函数

代码分析void ThermistorTempToString(int32 Temperature){    // 分别对应百位 十位 个位 十分位    const uint16 DigitPower[] = {1000, 100, 10, 1};uint8 i = 0;// 当前的位置    uint8 CurrentDigit;    uint8 TempDigit;    // 确定该位是否要显示字符的标志变量    uint8 Leading0Flag = 0;
    /* 如果设置了华氏度,则进行转换 */     /* 9/5 ~= 461/256, 320 = 32*10 */    if(TemperatureModeFlag == FAHRENHEIT_MODE)    {      Temperature = ((461 * Temperature) >> 8) + 320;    }
    /* 如果是负数,则在字符串中添加负号,并保留绝对值 */    if(Temperature < 0)     {      DisplayString = '-';      Temperature = -(Temperature);    }
    /* 对每一位的温度值进行转换,并存入全局变量DisplayString 字符数组中*/    for(CurrentDigit = 0; CurrentDigit < 4; CurrentDigit++)    {       TempDigit = 0;                /* 初始化该为数字为0 */   // 使用循环相减的方式得到该位的实际值,搞不明白为啥不直接除?!       while(Temperature >= DigitPower)       {         TempDigit++;         Temperature -= DigitPower;         Leading0Flag = 1;       }       if(CurrentDigit == 2)          /* 保证小数点前面至少有个0 */       { Leading0Flag = 1; }
       if(Leading0Flag == 1)         /* 将当前位数的值转换为字符保存在数组中 */       { DisplayString = TempDigit + '0'; }
       if(CurrentDigit == 2)         /* 在个位后面添加个小数点 */       { DisplayString = '.'; }    }
    DisplayString = '\'';    /* 如果是华氏度,添加’F’ */    if(TemperatureModeFlag == FAHRENHEIT_MODE)    { DisplayString = 'F'; }    else    { DisplayString = 'C'; }    DisplayString = '\0';       /* 字符串的结束字符 */
}

另附模拟复用器和电压数模转换器的文档








sky-Hawk where 发表于 2012-10-3 00:04:22

好难学啊,努力努力{:3_42:}

sky-Hawk where 发表于 2012-10-1 23:25:38

很详细啊

sky-Hawk where 发表于 2012-10-1 22:05:30

这样的帖要顶

sky-Hawk where 发表于 2012-10-1 20:31:19

灰常不错。。。!
页: [1]
查看完整版本: PSoC3 FirstTouc Starter Kit 例子源代码之ThermistorTemperatureSense

Baidu
map