查看: 3027|回复: 4

PSoC3 FirstTouc Starter Kit 例子源代码之ThermistorTemperatureSense

[复制链接]
  • TA的每日心情
    奋斗
    2018-8-29 20:40
  • 签到天数: 1341 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2012-10-1 18:46:08 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 wangku001wei 于 2012-10-1 18:56 编辑

    首先看原理图
    QQ截图20121001151155.jpg
    红色代表模拟引脚 绿色代表数字引脚
    电路原理图
    QQ截图20121001151321.jpg
    QQ截图20121001152359.jpg
    新使用了一个模拟复用器8位的电压模数转换器,对应端口为
    VRefPort——P5[5]——T_POWER
    VSignalPort——P5[6]——T_SENSE
    模拟复用端口采用了3个通路
    QQ截图20121001153241.jpg
    采用这种方式的原因是为了降低热敏电阻上采集到的电压误差
    QQ截图20121001152417.jpg
    根据电流相等,得到公式1
    QQ截图20121001155029.jpg                     公式1
    由公式1,推导,得到公式2,热敏电阻阻值公式:
    未命名.jpg                    公式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
    以上设置可以在引脚分配视图上看出
    QQ截图20121001151904.jpg

    主函数代码分析
    /*******************************************************************************************
    * 主函数的功能:
    * 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
    QQ截图20121001161448.jpg                            公式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)
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2016-6-12 21:59
  • 签到天数: 647 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2012-10-1 20:31:19 | 显示全部楼层
    灰常不错。。。!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2020-2-5 16:14
  • 签到天数: 518 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2012-10-1 22:05:30 | 显示全部楼层
    这样的帖要顶
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-7-11 11:26
  • 签到天数: 1982 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    发表于 2012-10-1 23:25:38 | 显示全部楼层
    很详细啊
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2015-7-11 15:23
  • 签到天数: 567 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2012-10-3 00:04:22 | 显示全部楼层
    好难学啊,努力努力
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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



    手机版|小黑屋|与非网

    GMT+8, 2024-12-24 20:13 , Processed in 0.164775 second(s), 24 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.