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'; /* 字符串的结束字符 */
}
另附模拟复用器和电压数模转换器的文档
好难学啊,努力努力{:3_42:} 很详细啊 这样的帖要顶 灰常不错。。。!
页:
[1]