[STM8]

请教STM8L AD转换问题

[复制链接]
5641|21
手机看帖
扫描二维码
随时随地手机跟帖
zhxingyu|  楼主 | 2014-4-14 12:09 | 显示全部楼层 |阅读模式
先用到STM8L的AD转换输入,输入端为0V,AD转换后都有0.375V,不知道怎么回事?基准是同电源Vcc连接一起的3.3V,请大侠看看。
void ADCinit(void)
{
       ADC1_CR1 = 0x00;
        ADC1_CR2 = 0x02;//0x02  0~23通道AD16分频寄存器
        ADC1_SR = 0x00;
        ADC1_SQR1 = 0x80;//禁用DMA模块
        ADC1_SQR2 = 0x00;
        ADC1_SQR3 = 0x00;
        ADC1_SQR4 = 0x08;//
        ADC1_CR1 |= 0x01;//使能ADC
        Delay_us(20);
        ADC1_CR1 |= 0x02;//启动ADC
}
void ADConvert(void)
{
        unsigned int ADCValue=0;
        
        if(!(ADC1_SR&0x01))return;
        ADC1_SR &= 0xfe;//清除转换标志
        //ADCValue = ADC1_DRL;
        //ADCValue |= ADC1_DRH << 8;
        ADCValue = ADC1_DRH << 8;
        ADCValue += ADC1_DRL;
        ADV += ADCValue;
        wdt_reset();
        if(ADCunter < 15)//15
          ADCunter ++;
        else
        {
                 ADCunter = 0;
                 switch(ADStep)
                 {
                        case  3:{PowerVolat = ((float)ADV/65536)*10;break;}
                        case  4:{UsbBatVolat[0] = ((float)ADV/65536) * 10;break;}   
                        case  5:{UsbBatVolat[1] = ((float)ADV/65536)* 10;break;}      
                        case  6:{UsbBatVolat[2] = ((float)ADV/65536)* 10;break;}      
                        case  7:{UsbBatVolat[3] = ((float)ADV/65536)* 10;break;}     
                        case  8:{UsbBatVolat[4] = ((float)ADV/65536)* 10;break;}   
                        case  9:{UsbBatVolat[5] = ((float)ADV/65536)* 10;break;}
                        case  10:{UsbBatVolat[6] = ((float)ADV/65536)* 10;break;}
                        case  11:{UsbBatVolat[7] = ((float)ADV/65536)* 10;break;}
                        case  12:{UsbBatVolat[8] = ((float)ADV/65536)* 10;break;}
                        case  13:{UsbBatVolat[9] = ((float)ADV/65536)* 10;break;}
                        
                        case  14:{UsbSwVolat[0] = ((float)ADV/65536)* 10;break;}
                        case  15:{UsbSwVolat[1] = ((float)ADV/65536)* 10;break;}
                        case  16:{UsbSwVolat[2] = ((float)ADV/65536)* 10;break;}
                        case  17:{UsbSwVolat[3] = ((float)ADV/65536)* 10;break;}
                        case  18:{UsbSwVolat[4] = ((float)ADV/65536)* 10;break;}
                        case  19:{UsbSwVolat[5] = ((float)ADV/65536)* 10;break;}
                        case  20:{UsbSwVolat[6] = ((float)ADV/65536)* 10;break;}
                        case  21:{UsbSwVolat[7] = ((float)ADV/65536)* 10;break;}
                        case  22:{UsbSwVolat[8] = ((float)ADV/65536)* 10;break;}
                        case  23:{UsbSwVolat[9] = ((float)ADV/65536)* 10;break;}
                 }
                 if(ADStep < 23)ADStep ++;
                 else ADStep = 3;
                 ADV = 0;
        }
        wdt_reset();
        ADC1_CR1 = 0x00;
        ADC1_CR2 = 0x02;//0~23通道AD16分频寄存器
        
        ADC1_SQR2 = 0;
        ADC1_SQR3 = 0;
        ADC1_SQR4 = 0;
        
        if(ADStep <= 7)
        {
               ADC1_SQR4 = (1<<ADStep);
        }
        else if(ADStep <= 15)
        {
               ADC1_SQR3 = (1<<(ADStep-8));
        }
        else if (ADStep <= 23)
        {
               ADC1_SQR2 = (1<<(ADStep-16));
        }
        
        ADC1_CR1 |= 0x01;
        Delay_us(20);
        ADC1_CR1 |= 0x02;
}
mmuuss586| | 2014-4-14 12:27 | 显示全部楼层
输入是0,测出来不是0也是正常的。

不过这个相差也太多了,大于10%了。

读取ADC的值,用联合体简单点。

你电压怎么换算的?

(float)ADV/65536)* 10;这个吗?

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 12:43 | 显示全部楼层
mmuuss586 发表于 2014-4-14 12:27
输入是0,测出来不是0也是正常的。

不过这个相差也太多了,大于10%了。

是的,没有*10是0.357V,不知道什么原因,是不是还有哪个寄存器没有用到?

使用特权

评论回复
mmuuss586| | 2014-4-14 12:51 | 显示全部楼层
/**************************************************************************
* 函数名:ADC_conf
* 描述  :ADC模块初始化
* 输入  :无
*
* 输出  :无
* 返回  :无
* 调用  :外部调用
*************************************************************************/
void ADC_conf()
{
   ADC_CR1 = (0<<4)|(1<<1)|(0<<0);    //ADC时钟输入频率为16MHz 这里设置分频系数为2  连续转换模式 先禁止ADC转换      
   ADC_CR2 = (1<<3)|(0<<1);           //设置数据右对齐  禁止扫描模式
  
   ADC_CSR = (0<<5)|(0xa<<0);         //不用外部触发 禁止转换结束中断 设置转换通道为AIN10
   ADC_TDRH = 4;                      //禁止AIN10施密特触发器功能  
   ADC_CR1 |= 1;                      //第一次写1是从低功耗模式唤醒
   ADC_CR1 |= 1;                      //在这一位是1的情况下再次写1启动ADC转换
}

使用特权

评论回复
mmuuss586| | 2014-4-14 12:52 | 显示全部楼层
/**************************************************************************
* 函数名:ADC_GetConversionValue
* 描述  :获取ADC转换结果
* 输入  :无
*
* 输出  :无
* 返回  :无
* 调用  :内部调用
*************************************************************************/
uint16_t ADC_GetConversionValue(void)
{
  uint16_t value,temph;        
  uint8_t templ;                  // 定义templ存储低8位数据  temph存储高8位数据
  
  while(!(ADC_CSR & 0x80));           //等待转换完成
  templ = ADC_DRL;
  temph = ADC_DRH;                  //读取ADC转换  在左对齐和右对齐模式下 读取数据的顺序不同  参考STM8寄存器.PDFP371         
  
  value = (unsigned int)(templ | (temph << 8));   //注意是10位的转换精度 value、temph应为unsigned int 变量
  return  value;
}

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 12:53 | 显示全部楼层
mmuuss586 发表于 2014-4-14 12:51
/**************************************************************************
* 函数名:ADC_conf
*  ...

你这是STM8S的吧?

使用特权

评论回复
mmuuss586| | 2014-4-14 12:56 | 显示全部楼层
zhxingyu 发表于 2014-4-14 12:43
是的,没有*10是0.357V,不知道什么原因,是不是还有哪个寄存器没有用到? ...

你0.375V怎么算出来的,或者你现在读到的AD值,写但一个缓冲区里,发上来看看是多少

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 13:00 | 显示全部楼层
mmuuss586 发表于 2014-4-14 12:56
你0.375V怎么算出来的,或者你现在读到的AD值,写但一个缓冲区里,发上来看看是多少 ...

这是*10的结果,输入端全部是0输入,请看图。
12.JPG

使用特权

评论回复
mmuuss586| | 2014-4-14 13:02 | 显示全部楼层
zhxingyu 发表于 2014-4-14 13:00
这是*10的结果,输入端全部是0输入,请看图。

发原始的AD数据。
可能你读的AD寄存器不多,也有可能你换算不对,我猜的
程序参考哪里的?

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 13:07 | 显示全部楼层
mmuuss586 发表于 2014-4-14 13:02
发原始的AD数据。
可能你读的AD寄存器不多,也有可能你换算不对,我猜的
程序参考哪里的? ...

这就是原始的数据。一个通道采样16次再平均,我怀疑是不是那个寄存器没有操作。

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 13:11 | 显示全部楼层
这STM8L怎么不见数据左对齐 右对齐选择寄存器呢?

使用特权

评论回复
122541325| | 2014-4-14 13:15 | 显示全部楼层
没左对齐啊

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 13:20 | 显示全部楼层
122541325 发表于 2014-4-14 13:15
没左对齐啊

是哪个寄存器?请明示。

使用特权

评论回复
mmuuss586| | 2014-4-14 13:21 | 显示全部楼层
zhxingyu 发表于 2014-4-14 13:20
是哪个寄存器?请明示。

:)

stsw-stm8016.zip

15.28 MB

使用特权

评论回复
mmuuss586| | 2014-4-14 13:26 | 显示全部楼层
/**
  * @brief  Deinitializes the ADC peripheral registers to their default reset
  *         values.
  * @param  ADCx where x can be 1 to select the specified ADC peripheral.
  * @retval None
  */
void ADC_DeInit(ADC_TypeDef* ADCx)
{
  /*  Set the Configuration registers to their reset values */
  ADCx->CR1 =  ADC_CR1_RESET_VALUE;
  ADCx->CR2 =  ADC_CR2_RESET_VALUE;
  ADCx->CR3 =  ADC_CR3_RESET_VALUE;

  /*  Set the status registers to their reset values */
  ADCx->SR =  (uint8_t)~ADC_SR_RESET_VALUE;

  /*  Set the High threshold registers to their reset values */
  ADCx->HTRH =  ADC_HTRH_RESET_VALUE;
  ADCx->HTRL =  ADC_HTRL_RESET_VALUE;

  /*  Set the low threshold registers to their reset values */
  ADCx->LTRH =  ADC_LTRH_RESET_VALUE;
  ADCx->LTRL =  ADC_LTRL_RESET_VALUE;

  /*  Set the channels sequence registers to their reset values */
  ADCx->SQR[0] =  ADC_SQR1_RESET_VALUE;
  ADCx->SQR[1] =  ADC_SQR2_RESET_VALUE;
  ADCx->SQR[2] =  ADC_SQR3_RESET_VALUE;
  ADCx->SQR[3] =  ADC_SQR4_RESET_VALUE;

  /*  Set the channels Trigger registers to their reset values */
  ADCx->TRIGR[0] =  ADC_TRIGR1_RESET_VALUE;
  ADCx->TRIGR[1] =  ADC_TRIGR2_RESET_VALUE;
  ADCx->TRIGR[2] =  ADC_TRIGR3_RESET_VALUE;
  ADCx->TRIGR[3] =  ADC_TRIGR4_RESET_VALUE;
}

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-14 14:57 | 显示全部楼层
mmuuss586 发表于 2014-4-14 13:26
/**
  * @brief  Deinitializes the ADC peripheral registers to their default reset
  *         value ...

ADC1_HTRH = 0x0f;
        ADC1_HTRL = 0xff;
        ADC1_LTRH = 0x0f;
        ADC1_LTRL = 0xff;

这样配置有问题?
12.JPG

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-15 10:29 | 显示全部楼层
现在直接读取转换后的AD值,这1000多大数不知道怎么来的,输入测量了是0V,见图。
12.JPG

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-15 10:31 | 显示全部楼层
0V输入,为什么AD还能转换出这么大的数,究竟什么原因?有人遇到过这问题吗?

使用特权

评论回复
zhxingyu|  楼主 | 2014-4-19 14:01 | 显示全部楼层
最终用库把问题解决了,谢谢大家的回复。

使用特权

评论回复
luozuowen| | 2015-7-25 10:33 | 显示全部楼层
楼主,可不可以把你的程序发一份到我的邮箱284322984@qq.com,谢谢!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

69

主题

309

帖子

3

粉丝