4回答

0收藏

PSoC3 FirstTouc Starter Kit 例子源代码之ThermistorTemperatureSense

英飞凌 英飞凌 4080 人阅读 | 4 人回复 | 2012-10-01

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

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

新使用了一个模拟复用器8位的电压模数转换器,对应端口为
VRefPort——P5[5]——T_POWER
VSignalPort——P5[6]——T_SENSE
模拟复用端口采用了3个通路
采用这种方式的原因是为了降低热敏电阻上采集到的电压误差
根据电流相等,得到公式1
                    公式1
由公式1,推导,得到公式2,热敏电阻阻值公式:
                   公式2
注意,我们这个例子中 电压值V2为0
aPort_YAxia 和三轴加速度的一个引脚向量
dPort_AcclControl和三轴加速度的三个控制引脚相连,用于向加速度传感器写入命令
dPort8IO口组成,且由于在POSC的端口设置中如果端口的位宽大于1,则在实际分配引脚时,这些端口必须是同一个Px口上的相邻IO口,因此dPort分为了高低各四位的dPort_LSBdPort_MSB
PdPort_LSB 对应P2口的P2[3:0]控制
dPort_MSB 对应P4口的P4[3:0]控制
同样的,反向是因为电路设计为低电平点亮LED,高电平熄灭LED
ADC转换器选择了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[RasterCount]);
        }

       /* 等待这次挥动结束 */
        do
        {
            AcclADC_StartConvert();
            AcclADC_IsEndConversion(AcclADC_WAIT_FOR_RESULT);
        }while(AcclADC_GetResult16() < (255 - ACCEL_TRIGGER));
    }
}


关于得到测量温度的函数 Thermistor.c 文件中的
void Thermistor_TemperatureCompute(void)函数
使用了查找表 表中记录了从-40125摄氏度每隔1摄氏度对应的ADC采样值
整摄氏度之间的值采用线性插值的方法算出
插值计算过程:
TempTable_UpperLimit 对应的是表中索引小,温度低而实际值大的
TempTable_LowerLimit 对应的是表中索引大,温度高而实际值小的
ThermistorResistance ADC转换出来的值
Thermistor_Temperature 是最终得到的温度数值,由于要保留1位小数,结果乘以了10
TempTable_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[Count] >= ThermistorResistance; Count++);

    /* 根据公式3插值计算温度值 */
    TempTable_Decimal = 0;               
    TempTable_LowerLimit = Thermistor_TempTable[Count];
    TempTable_UpperLimit = Thermistor_TempTable[Count-1];

    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[i++] = '-';
        Temperature = -(Temperature);
    }

    /* 对每一位的温度值进行转换,并存入全局变量DisplayString 字符数组中*/
    for(CurrentDigit = 0; CurrentDigit < 4; CurrentDigit++)
    {
       TempDigit = 0;                  /* 初始化该为数字为0 */
   // 使用循环相减的方式得到该位的实际值,搞不明白为啥不直接除?!
       while(Temperature >= DigitPower[CurrentDigit])
       {
           TempDigit++;
           Temperature -= DigitPower[CurrentDigit];
           Leading0Flag = 1;
       }
       if(CurrentDigit == 2)          /* 保证小数点前面至少有个0 */
       { Leading0Flag = 1; }

       if(Leading0Flag == 1)           /* 将当前位数的值转换为字符保存在数组中 */
       { DisplayString[i++] = TempDigit + '0'; }

       if(CurrentDigit == 2)           /* 在个位后面添加个小数点 */
       { DisplayString[i++] = '.'; }
    }

    DisplayString[i++] = '\'';
    /* 如果是华氏度,添加’F’ */
    if(TemperatureModeFlag == FAHRENHEIT_MODE)
    { DisplayString[i++] = 'F'; }
    else
    { DisplayString[i++] = 'C'; }
    DisplayString[i++] = '\0';         /* 字符串的结束字符 */

}

另附模拟复用器和电压数模转换器的文档
VDAC8中文.pdf (929.3 KB, 下载次数: 19)


AMux_v1_10英文.pdf (92.32 KB, 下载次数: 10)


AMux_v1_50中文.pdf (315.76 KB, 下载次数: 15)


VDAC8_v1_10英文.pdf (116.38 KB, 下载次数: 9)


分享到:
回复

使用道具 举报

回答|共 4 个

倒序浏览

沙发

QQ哥

发表于 2012-10-1 20:31:19 | 只看该作者

灰常不错。。。!
我就是QQ哥,QQ哥就是我!
https://www.cirmall.com/bbs/?fromuser=QQ%E5%93%A5
板凳

dzcn

发表于 2012-10-1 22:05:30 | 只看该作者

这样的帖要顶
地板

feiante

发表于 2012-10-1 23:25:38 | 只看该作者

很详细啊
5#

醉清风-385874

发表于 2012-10-3 00:04:22 | 只看该作者

好难学啊,努力努力
做对的事情比做对事情更重要!
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条