数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 5362|回复: 22

[other] 我的ADC是8位的?这是为什么?

[复制链接]
发表于 2021-2-22 09:40:36 | 显示全部楼层 |阅读模式
最近开始学习ADC(芯片是stm32f103cbt6),先是做了一个光敏二极管的ADC,用的原子的例程,用来控制LED点阵屏的亮度,既然成功了,好开心,然后又做个NTC的ADC,很简单,还是用的光敏二极管的ADC修改一下就可以,但要显示温度就得花一些功夫了,需要用到查表法,然后找到NTC的温度电阻表和AD值表,就是想要做个温度计,显示日常的温度,所以做了一个表

突然发现,AD值不对

ADC显示是148,与上表相去甚远,现在的温度大概是19度左右,AD怎么也要在2320左右吧,什么原因??查程序,没发现问题,再看一下硬件,分压电阻没问题,NTC没问题,手摸NTC有变化,但是变化的值有些奇怪,数值超过255后会回0,一定有鬼,把NTC拨下,显示245

测量IO口电压3.2V左右,12位ADC最高这时应该是4096低一些吧,明显现在ADC应该是8位的,什么原因?在网上疯狂的搜索,没找到如何将ADC配置成12位类似的内容,傻了。
  1. void NTC_ADC1_Init(void)                //NTC  ADC初始化
  2. {        
  3.   GPIO_InitTypeDef GPIO_InitStructure;
  4.         ADC_InitTypeDef ADC_InitStructure;
  5.        
  6.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);        //使能PORTF时钟       
  7.        
  8.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12MHZ   
  9.        
  10.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                                //PA4 对应第4通道
  11.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
  12.         GPIO_Init(GPIOA, &GPIO_InitStructure);       
  13.        
  14.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式: 独立模式
  15.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
  16.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
  17.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
  18.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
  19.         ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
  20.         ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器  
  21.        
  22.         ADC_Cmd(ADC1, ENABLE);                                                                                        //使能指定的ADC1       
  23.         ADC_ResetCalibration(ADC1);                                                                        //使能复位校准
  24.         while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束       
  25.         ADC_StartCalibration(ADC1);                                                                         //开启AD校准
  26.   while(ADC_GetCalibrationStatus(ADC1));                         //等待校准结束
  27. }               
复制代码
以上代码应该没有问题吧,然后加上 ADC_DeInit(ADC1)进行复位,也不成功,请大神出手帮帮我,如何才能设置为12位ADC。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
发表于 2021-2-22 10:10:53 | 显示全部楼层
前两天看了一个帖子也是这个问题,说是默认是8位的需要设置,忘了在哪看的了
回复 支持 反对

使用道具 举报

发表于 2021-2-22 10:16:05 | 显示全部楼层
没用过单片机的AD
排除几个问题:
存储器位数
实数转化
还有可能就是8位传感器
但是传感器超过范围应该在255不变才对,你这超范围变0是有问题的
回复 支持 反对

使用道具 举报

发表于 2021-2-22 10:20:18 | 显示全部楼层
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-22 11:02:09 | 显示全部楼层
nb267213667 发表于 2021-2-22 10:16
没用过单片机的AD
排除几个问题:
存储器位数

应该是255溢出,进入到下一个周期了,因为NTC的值仍然在变。
回复 支持 反对

使用道具 举报

发表于 2021-2-22 11:02:40 | 显示全部楼层
找官方的AD例程呀,记得配置ADC时有一个选择精度的参数
回复 支持 反对

使用道具 举报

发表于 2021-2-22 12:03:41 | 显示全部楼层
lipeixian 发表于 2021-2-22 11:02
应该是255溢出,进入到下一个周期了,因为NTC的值仍然在变。

"数值超过255后会回0"  数据类型不对,或者计算过程不对导致丢失精度。发你ADC计算过程出来看看。

下面是我用的代码,供参考。


//获得ADC1某个通道的值
//ch:通道值 0~16
//返回值:转换结果

u16 Get_Adc(u8 ch)   
{         
        ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道ch
        ADC1->SQR3|=ch;                                             
        ADC1->CR2|=1<<22;       //启动规则转换通道
        while(!(ADC1->SR&1<<1));//等待转换结束                    
        return ADC1->DR;                //返回adc值        
}
//获取通道ch的转换值,取times次,然后平均
//ch:通道编号
//times:获取次数
//返回值:通道ch的times次转换结果平均值

u16 Get_Adc_Average(u8 ch,u8 times)
{
        u16 temp_val=0;
        u8 t;
        Delay_ms(10);
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc(ch);
        }
        return temp_val/times;
}

回复 支持 反对

使用道具 举报

发表于 2021-2-22 12:06:25 | 显示全部楼层
本帖最后由 crazy0qwer 于 2021-2-22 12:08 编辑
夜游虾 发表于 2021-2-22 10:10
前两天看了一个帖子也是这个问题,说是默认是8位的需要设置,忘了在哪看的了 ...

好像是F0的要设置,我看F1的规格书并没有这个寄存器。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 反对

使用道具 举报

发表于 2021-2-22 12:30:29 | 显示全部楼层
你这个是不是只取了低位,高位没有取:loveliness:
回复 支持 反对

使用道具 举报

发表于 2021-2-22 12:52:08 | 显示全部楼层
把你的ADC采样代码贴出来。
我遇到过:
1、采样脚与电路引脚不相符,也就是设置错了引脚或电路设计错误。
2、采样时或计算过程中某一变量只有8位,把高4位滤掉了。
回复 支持 反对

使用道具 举报

发表于 2021-2-22 13:26:52 | 显示全部楼层
应该是哪里用了个Uint8 然后吧数据高四位丢了
回复 支持 1 反对 0

使用道具 举报

发表于 2021-2-22 13:38:27 | 显示全部楼层
楼主只是贴出了ADC初始化的代码,没看到转换部分的代码。我也觉得变量的数据类型设置错误的可能性更大些,或者是ADC的数据宽度没有设置正确。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-22 16:12:20 | 显示全部楼层
crazy0qwer 发表于 2021-2-22 12:03
"数值超过255后会回0"  数据类型不对,或者计算过程不对导致丢失精度。发你ADC计算过程出来看看。

下面是 ...
  1. //获得ADC值

  2. u16 Get_NTC_Adc1()   
  3. {
  4.           //设置指定ADC的规则组通道,一个序列,采样时间
  5.         ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_239Cycles5);
  6.   
  7.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);                                                //使能指定的ADC1的软件转换启动功能
  8.        
  9.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));                //等待转换结束
  10.        
  11.         return ADC_GetConversionValue(ADC1);                                                        //返回最近一次ADC1规则组的转换结果
  12. }
  13.          


  14. //读取NTC的值

  15. u8 Get_NTC_Val(void)
  16. {
  17.         u32 temp_val = 0;
  18.         u8 t;
  19.         for(t = 0; t < 10; t++)                                                                //读10次
  20.         {
  21.                 temp_val += Get_NTC_Adc1();                                        //读取ADC值
  22. //                delay_ms(5);
  23.         }
  24.         temp_val /= 10;                                                                                                //取平均值
  25.         if(temp_val > 4000)        temp_val = 4000;
  26.         return (u32)temp_val;
  27.        
  28. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-22 16:12:57 | 显示全部楼层
u8 Get_NTC_Val(void)

这个错误?晚上回去试试
回复 支持 反对

使用道具 举报

发表于 2021-2-22 16:23:13 | 显示全部楼层
可能的问题:1、ADC位数没设置对。2、计算时的数据类型不对。3、只读取了结果寄存器的低八位。
回复 支持 反对

使用道具 举报

发表于 2021-2-22 20:40:02 | 显示全部楼层
u8 Get_NTC_Val(void) 返回值类型是 return (u32)temp_val;溢出了
回复 支持 1 反对 0

使用道具 举报

发表于 2021-2-22 20:58:59 | 显示全部楼层
lipeixian 发表于 2021-2-22 16:12
u8 Get_NTC_Val(void)

这个错误?晚上回去试试

return都是u32了,怎么给u8的定义
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-23 07:18:57 | 显示全部楼层
本帖最后由 lipeixian 于 2021-2-23 10:07 编辑

最终结果是U8定义错误,限制了最高位的显示,改为u16正常。
这是原子的程序



本例错误原因是复制原子的程序并未对变量进行分析,导致错误,重新分析才注意到,原子在函数内对结果进行了/40运算,所以结果不需要u16,自己检查时也曾怀疑过变量问题,修改过u16 u32,但没找对位置,最终忘记改回,见笑了,感谢各位大师的指点,受教了,感谢感谢。






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 反对

使用道具 举报

发表于 2021-2-23 08:46:02 | 显示全部楼层
我猜就是你用了uint8=adc赋值了。。
回复 支持 反对

使用道具 举报

发表于 2021-2-25 00:05:36 | 显示全部楼层
建议加上均值滤波,不然抖的怀疑人生:lol:
回复 支持 1 反对 0

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-21 23:42 , Processed in 0.140400 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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