找回密码
 立即注册
查看: 220|回复: 9

按照冲哥的adc,用ntc测温度.可是温度范围不对,好像我哪里错了

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-06-15 15:05:22
已绑定手机

142

主题

1688

回帖

2559

积分

金牌会员

积分
2559
发表于 2025-4-11 21:31:32 | 显示全部楼层 |阅读模式
用的ai8g1k08a  10位的adc ,ntc用的 B3950 10k

电路是 VCC3.3V-10K固定电阻,NTC -GND          P55脚在NTC和10k固定电阻中间
温度不管怎么降,只能到20°左右.. 用打火机烧也只能到40°,, 环境温度26°,和当前值差不多
因为我用的10位adc, 冲哥教程里用的12位的.我也把4096改成1024了

程序如下.大佬帮看看哪里出问题了.
  1. void AdcSetRate(void)                //50KSPS@11.0592MHz
  2. {
  3.         ADCCFG &= ~0x0f;
  4.         ADCCFG |= 0x02;                        //SPEED(2)
  5.         ADCTIM = 0x35;                        //CSSETUP(0), CSHOLD(1), SMPDUTY(21)
  6. }
  7. void ADC_Init(void)
  8. {
  9.        
  10.        
  11.         //1.初始化IO为高祖输入 P55高阻
  12.     P5M0 &= ~0x20; P5M1 |= 0x20;
  13.         //2.初始化ADC速度
  14.         AdcSetRate();
  15.        
  16.         //3.对齐模式
  17.         ADCCFG |= 0x20;
  18.        
  19.         //4.打开ADC电源
  20.         ADC_CONTR |= 0x80;                //ADC_POWER = 1;
  21. }
  22. u16 ADC_Read(u8 no)
  23. {
  24.         u16 adcval = 0;
  25.         ADC_CONTR &= 0Xf0;                //清空低四位
  26.         ADC_CONTR |= no;
  27.        
  28.         ADC_CONTR |= 0x40;                //ADC_START = 1;                //启动ADC转化
  29.         _nop_();
  30.         _nop_();
  31.         while(!(ADC_CONTR & 0x20));                //while(!ADC_FLAG);        //等待采集完成
  32.         ADC_CONTR &= ~0x20;                                 //ADC_FLAG = 0;
  33.        
  34.         adcval = (((u16)ADC_RES) << 8) + (ADC_RESL);        //获取到最终的ADC数值
  35.        
  36.         return adcval;
  37. }
  38. u16 code Temp_Tab[]=
  39. {
  40.         140 ,                //-40
  41.         149 ,
  42.         159 ,
  43.         168 ,
  44.         178 ,
  45.         188 ,
  46.         199 ,
  47.         210 ,
  48.         222 ,
  49.         233 ,
  50.         246 ,
  51.         259 ,
  52.         272 ,
  53.         286 ,
  54.         301 ,
  55.         317 ,
  56.         333 ,
  57.         349 ,
  58.         367 ,
  59.         385 ,
  60.         403 ,
  61.         423 ,
  62.         443 ,
  63.         464 ,
  64.         486 ,
  65.         509 ,
  66.         533 ,
  67.         558 ,
  68.         583 ,
  69.         610 ,
  70.         638 ,
  71.         667 ,
  72.         696 ,
  73.         727 ,
  74.         758 ,
  75.         791 ,
  76.         824 ,
  77.         858 ,
  78.         893 ,
  79.         929 ,
  80.         965 ,
  81.         1003,
  82.         1041,
  83.         1080,
  84.         1119,
  85.         1160,
  86.         1201,
  87.         1243,
  88.         1285,
  89.         1328,
  90.         1371,
  91.         1414,
  92.         1459,
  93.         1503,
  94.         1548,
  95.         1593,
  96.         1638,
  97.         1684,
  98.         1730,
  99.         1775,
  100.         1821,
  101.         1867,
  102.         1912,
  103.         1958,
  104.         2003,
  105.         2048,
  106.         2093,
  107.         2137,
  108.         2182,
  109.         2225,
  110.         2269,
  111.         2312,
  112.         2354,
  113.         2397,
  114.         2438,
  115.         2479,
  116.         2519,
  117.         2559,
  118.         2598,
  119.         2637,
  120.         2675,
  121.         2712,
  122.         2748,
  123.         2784,
  124.         2819,
  125.         2853,
  126.         2887,
  127.         2920,
  128.         2952,
  129.         2984,
  130.         3014,
  131.         3044,
  132.         3073,
  133.         3102,
  134.         3130,
  135.         3157,
  136.         3183,
  137.         3209,
  138.         3234,
  139.         3259,
  140.         3283,
  141.         3306,
  142.         3328,
  143.         3351,
  144.         3372,
  145.         3393,
  146.         3413,
  147.         3432,
  148.         3452,
  149.         3470,
  150.         3488,
  151.         3506,
  152.         3523,
  153.         3539,
  154.         3555,
  155.         3571,
  156.         3586,
  157.         3601,
  158.         3615,
  159.         3628,
  160.         3642,
  161.         3655,
  162.         3667,
  163.         3679,
  164.         3691,
  165.         3702,
  166.         3714,
  167.         3724,
  168.         3735,
  169.         3745,
  170.         3754,
  171.         3764,
  172.         3773,
  173.         3782,
  174.         3791,
  175.         3799,
  176.         3807,
  177.         3815,
  178.         3822,
  179.         3830,
  180.         3837,
  181.         3844,
  182.         3850,
  183.         3857,
  184.         3863,
  185.         3869,
  186.         3875,
  187.         3881,
  188.         3887,
  189.         3892,
  190.         3897,
  191.         3902,
  192.         3907,
  193.         3912,
  194.         3917,
  195.         3921,
  196.         3926,
  197.         3930,
  198.         3934,
  199.         3938,
  200.         3942,                         //120
  201. };
  202. u16 Temp_Cal(u16 adc)                                //返回结果是放大10背的数值16.9*10 = 169
  203. {
  204.         u8 j = 0;
  205.         u16 k = 0;
  206.         u16 min;                                                //当前的位置
  207.         u16 max;                                                //当前最大的位置
  208.         u16 i;                                                        //温度
  209.        
  210.         adc = 1024 - adc;                                //得到当前的adc数值          4096 12位 1024 10位
  211.        
  212.         if( adc < Temp_Tab[0] )                        //温度最小值检测
  213.                 return 0xfffe;
  214.         if( adc > Temp_Tab[160] )                //温度最大值检测
  215.                 return 0xfffF;       
  216.        
  217.         min = 0;
  218.         max = 160;
  219.        
  220.         for( j=0;j<5;j++ )                                //实现五次二分法查询
  221.         {
  222.                 k = (min + max)/2;
  223.                 if( adc <= Temp_Tab[k] )
  224.                         max = k;
  225.                 else
  226.                         min = k;
  227.         }
  228.        
  229.         if( adc == Temp_Tab[min] )
  230.                 i = min *10;                //(20*10 - 400)/10 =  -20.0
  231.         else if( adc == Temp_Tab[max] )
  232.                 i = max * 10;
  233.         else                                        //50 -51之间
  234.         {
  235.                 while(min <= max )
  236.                 {
  237.                         min++;
  238.                         if( Temp_Tab[min] == adc )
  239.                         {
  240.                                 i = min * 10;
  241.                                 break;
  242.                         }
  243.                         else if( adc < Temp_Tab[min]  )                //超过这一档的温度的adc
  244.                         {
  245.                                 min --;
  246.                                 i = Temp_Tab[min];                                //上一档的adc数值记下来
  247.                                 j = Temp_Tab[min+1] -Temp_Tab[min] ;//这两档之间的差值 2-8
  248.                                 j = ( adc - i )*10/j;
  249.                                 i = min*10+j;
  250.                                 break;
  251.                         }
  252.                 }
  253.         }
  254.         return i;
  255. }
  256. void main()
  257. {
  258. u16 tempwfdu;
  259.        
  260.         sys_init();
  261.         while(1)
  262.         {
  263.                 delayms(500);
  264.                 tempwfdu = Temp_Cal(ADC_Read(5));  
  265.                
  266.                 printf("Temp_Cal= %u \r\n",tempwfdu);
  267.                
  268.         }
  269. }
复制代码



回复

使用道具 举报 送花

3

主题

722

回帖

155

积分

等待验证会员

积分
155
发表于 2025-4-11 21:33:00 | 显示全部楼层
从您描述的问题来看,温度测量范围不准确可能与以下几个因素有关:ADC配置、NTC电阻的计算、电路设计以及程序逻辑。以下是对可能问题的分析和建议:

1. ADC配置问题
您使用的是10位ADC,而教程中使用的是12位ADC。虽然您已经将4096改为1024,但需要注意的是,ADC的分辨率不仅影响数值范围,还可能影响精度和计算方式。建议您检查以下几点:
ADC参考电压:确保ADC的参考电压与电路中的VCC一致(3.3V)。
采样速率:您的代码中设置了50KSPS的采样速率,这可能会影响ADC的精度。可以尝试降低采样速率,以提高稳定性。
对齐模式:您设置了右对齐模式(ADCCFG |= 0x20),这通常是正确的,但需要确保读取ADC值时正确处理高低位。

2. NTC电阻计算问题
NTC(负温度系数热敏电阻)的阻值随温度变化是非线性的,通常需要使用Steinhart-Hart方程或查表法进行温度转换。B3950 10K NTC的典型参数如下:
B值:3950K
标称电阻:10KΩ @ 25°C

您需要根据ADC读取的电压值,计算出NTC的当前阻值,然后通过公式或查表法转换为温度。以下是计算步骤:
1. 计算NTC电阻:
   \[
   R{NTC} = \frac{R{固定} \times (V{ADC} / V{REF})}{1 - (V{ADC} / V{REF})}
   \]
   其中,\(R{固定}\)为10KΩ,\(V{ADC}\)为ADC读取的电压值,\(V{REF}\)为参考电压(3.3V)。

2. 计算温度:
   使用Steinhart-Hart方程:
   \[
   \frac{1}{T} = \frac{1}{T0} + \frac{1}{B} \ln\left(\frac{R{NTC}}{R0}\right)
   \]
   其中,\(T0\)为参考温度(25°C = 298.15K),\(R0\)为参考电阻(10KΩ),\(B\)为B值(3950K)。

3. 电路设计问题
您的电路设计是典型的电压分压电路,理论上没有问题,但需要注意以下几点:
NTC与固定电阻的匹配:确保NTC和固定电阻的阻值在测量范围内能够产生足够的电压变化。
电源稳定性:确保VCC(3.3V)稳定,避免电源波动影响ADC读数。
引脚配置:确保P55引脚配置为高阻输入模式,避免影响分压电路。

4. 程序逻辑问题
您的程序逻辑基本正确,但可以优化以下几点:
ADC读取函数:在读取ADC值时,建议增加延时或等待ADC转换完成的标志位,确保读取的值是稳定的。
温度转换函数:在读取ADC值后,确保正确计算NTC电阻和温度,避免计算错误。

示例代码优化
以下是优化后的ADC读取和温度计算代码示例:
```c
float CalculateTemperature(u16 adcValue) {
    float Vadc = (adcValue / 1024.0)  3.3; // 计算ADC电压值
    float Rntc = (10.0  Vadc) / (3.3 - Vadc); // 计算NTC电阻值
    float T0 = 298.15; // 参考温度(25°C)
    float B = 3950.0; // B值
    float R0 = 10000.0; // 参考电阻(10KΩ)
    float T = 1.0 / (1.0/T0 + (1.0/B)  log(Rntc/R0)); // 计算温度(K)
    return T - 273.15; // 转换为摄氏度
}

u16 ADCRead(u8 no) {
    u16 adcval = 0;
    ADCCONTR &= 0xF0; // 清空低四位
    ADCCONTR |= no; // 选择通道
    ADCCONTR |= 0x40; // 启动ADC转换
    while (!(ADCCONTR & 0x20)); // 等待转换完成
    adcval = (ADCRES

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-06-15 15:05:22
已绑定手机

142

主题

1688

回帖

2559

积分

金牌会员

积分
2559
发表于 2025-4-11 21:50:08 | 显示全部楼层
国芯人*** 发表于 2025-4-11 21:33
从您描述的问题来看,温度测量范围不准确可能与以下几个因素有关:ADC配置、NTC电阻的计算、电路设计以及程 ...

你可以帮我把我的代码优化一下吗?
如果我的代码里有哪些需要更改的地方,请帮我更改一下.谢谢
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2025-4-12 10:59:10 | 显示全部楼层
ADC位数不同,算法也不同,查表法的表格也要修改
还有一种简单的方法就是读出的10位ADC值直接乘以4,当成12位的再进行下一步计算
修改算法的话可以参考梁工PID温控程序中的实时计算方法
https://www.stcaimcu.com/thread-3720-1-1.html
NTC 热敏电阻温度计算公式:Rt = Ro *EXP(B/T-B/To),温度单位为绝对温度K,开尔文。
(1) Rt 是热敏电阻在温度T下的阻值。T是绝对温度。
(2) Ro是热敏电阻在To(25度)时的阻值。10K的热敏电阻25℃的值为10K(即Ro=10K)。To = (273.15+25)。
(3) EXP(n) 是 e 的 n 次方。
(4) B值是热敏电阻的材料系数。
通过转换可以得到温度T与电阻Rt的关系:T=1/(1/To+ln(Rt/Ro)/B)
对应的摄氏温度t=T-273.15。
电路连接: Vref -- 10K --ADC-- NTC -- GND, 12位ADC,计算出Rt/Ro的ADC值:
ADC = 4096*Rt/(Rt+Ro), 则
Rt/Ro = ADC/(4096-ADC), 从而
T = 1/(1/To+ln(ADC/(4096-ADC))/B)

DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:94
  • 最近打卡:2025-06-16 11:51:06

74

主题

6089

回帖

1万

积分

超级版主

积分
12721
发表于 2025-4-12 15:48:53 | 显示全部楼层
10位ADC结果*4(或adc <<2)再去查表即可。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-06-15 15:05:22
已绑定手机

142

主题

1688

回帖

2559

积分

金牌会员

积分
2559
发表于 2025-4-13 00:13:24 | 显示全部楼层
梁*** 发表于 2025-4-12 15:48
10位ADC结果*4(或adc

好的,梁工,我明天试试,有结果反馈给您
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-06-15 15:05:22
已绑定手机

142

主题

1688

回帖

2559

积分

金牌会员

积分
2559
发表于 2025-4-13 00:17:41 | 显示全部楼层
Debu*** 发表于 2025-4-12 10:59
ADC位数不同,算法也不同,查表法的表格也要修改
还有一种简单的方法就是读出的10位ADC值直接乘以4,当成12 ...

好的哥,明天我试试,今天太累了. 明天试出来反馈结果
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-06-15 15:05:22
已绑定手机

142

主题

1688

回帖

2559

积分

金牌会员

积分
2559
发表于 2025-4-13 13:15:11 | 显示全部楼层
Debu*** 发表于 2025-4-12 10:59
ADC位数不同,算法也不同,查表法的表格也要修改
还有一种简单的方法就是读出的10位ADC值直接乘以4,当成12 ...

报告哥,好像已经弄好了.
我把adc =  4096 - adc*4;        然后printf 就是650了
然后打印的值 -400 , 250 . 实际应该是 25.0 °符合当前温度(手机天气预报显示26°),然后用烟头烫ntc, 温度也能上升到100多°了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-06-15 15:05:22
已绑定手机

142

主题

1688

回帖

2559

积分

金牌会员

积分
2559
发表于 2025-4-13 13:15:31 | 显示全部楼层
梁*** 发表于 2025-4-12 15:48
10位ADC结果*4(或adc

报告梁工,好像已经弄好了.
我把adc =  4096 - adc*4;        然后printf 就是650了
然后打印的值 -400 , 250 . 实际应该是 25.0 °符合当前温度(手机天气预报显示26°),然后用烟头烫ntc, 温度也能上升到100多°了

点评

祝贺!这个二分法查表算法最早是我2013年的学习板中提供,ADC使用12位,10位的ADC要*4,为了避免小数运算,所以使用了无符号整数。  详情 回复 发表于 2025-4-13 14:42
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:94
  • 最近打卡:2025-06-16 11:51:06

74

主题

6089

回帖

1万

积分

超级版主

积分
12721
发表于 2025-4-13 14:42:19 | 显示全部楼层
vb2*** 发表于 2025-4-13 13:15
报告梁工,好像已经弄好了.
我把adc =  4096 - adc*4;        然后printf 就是650了
然后打印的值 -400 , 250 .  ...

祝贺!这个二分法查表算法我很早就实现过,ADC使用12位,10位的ADC要*4,为了避免小数运算,所以使用了无符号整数。
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-16 13:06 , Processed in 0.188412 second(s), 101 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表