打印
[技术支持]

有关ADC12位转换问题!请芯圣的高手 指点

[复制链接]
3959|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
boya355|  楼主 | 2024-8-20 15:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
再次启用芯圣的单片机, 使用在HC89f0541上, 其中的ADC12位转换上, 卡壳了“数码管显示不全”:是哪条语句写错! 还是 计算出问题? 望高手过路 指教一下   多谢赐教


#include "VoltADC.h"
#include "string.h"
#define uchar unsigned char
#define uint unsigned int

void delay_ms(u16  nms);
                                              
sbit  CV= P0^5;                          // ADC输出口
unsigned int ADvalue;
uchar  AdcBufCount =0;   
uint ADvalueBuf[8]={0x00};       //ADC缓存值

uchar AdcFlag = 0;
float Vin;
unsigned char dispVin[3]={0,0,0};  //待数码管显示值
void Disp_Vin();
//***************************************************
void Delay_2us(uchar i)    // @16MHz   2US 延时
{
        while(--i);       
}
//***************************************
void Delay1ms(void)        //@16MHz
{
        unsigned char  i, j;

        i = 16;
        j = 141;
        do
        {
                while (--j);
        } while (--i);
}

//************ADC**************************  
void voltADC_init(void)        //  
{
       
        P0M5 =  0x02;            // 设置P05为模拟输入
        ADCC0 = 0x80;            //开启ADC电源
        Delay_2us(10);             //延时 保稳定
        ADCC1 = 0x05;            //选择P05为转换通道

        ADCC2 = 0x4B;             //12位 右对齐
        SCANCON = 0x6F;          //单通道带缓存连续扫描模式
        IE1 |= 0x40;                  //打开ADC转换中断
        EA = 1;
        ADCC0 |= 0x40;            //启动转换
        Delay_2us(10);             //
        EADC = 1;

}
//**********************************
void ADC_Rpt() interrupt ADC_VECTOR
{
    AdcFlag = 1;                       //
    IE1 &=~ 0x40;                      //
          ADCC0 &=~ 0x20;                                                       
       
}
//***************************************
unsigned int   ADC_GetResault()       //
{
  unsigned int AD_Dat = 0;            // 定义转换值
        unsigned int Tmp = 0;  
static uchar i;       
        voltADC_init();
        SCANCON = 0x6F;                 // 单通道带缓存连续 扫描8次
       
   while(1)
                 { if(AdcFlag == 1)          //ADC转换结束
                         {
                                        ADvalueBuf[0] = SCR0;
                                        ADvalueBuf[1] = SCR1;
                                        ADvalueBuf[2] = SCR2;
                                        ADvalueBuf[3] = SCR3;
                                        ADvalueBuf[4] = SCR4;
                                        ADvalueBuf[5] = SCR5;
                                        ADvalueBuf[6] = SCR6;
                                        ADvalueBuf[7] = SCR7;
                                 for(i = 0; i <= 8; i ++)
                                        {
                                       
                                         ADvalue += ADvalueBuf[i];
                                        }
                                                ADvalue /= 8;       //8次扫描均值

                                                if(ADvalue <= 0x10) {CV = 1;}
                                                else {CV =0;}
                                                AdcFlag = 0;         //
                                                AdcBufCount = 0;
                                                memset(ADvalueBuf, 0 ,10);    //清缓冲
                                                IE1 |= 0x40;
                         }
                         Vin = ADvalue;
                         return Vin;
                  }
                       
       
               
       
}
void Disp_Vin()  //数码管待显示的 百 十 个
{
   unsigned char i;
        for(i=0 ; i<3; i++)
        {
        dispVin[0] = ( ADC_GetResault()*3700/4095)/100;               
  dispVin[1] = ( ADC_GetResault()*3700/4095 )  % 100 / 10;
  dispVin[2] = ( ADC_GetResault()*3700/4095 )  % 10 ;
                if(dispVin[0] == 0)                                   //高位0时 不显示
                {  dispVin[0] = 10;      
                        if (dispVin[1] == 0)   dispVin[1] = 10;  //高位0时 不显示
                 }
  }
}


省去后面的数码显示单元程序,  此程序 已经测试验证OK

使用特权

评论回复
沙发
cr315| | 2024-8-20 15:58 | 只看该作者
你应该将ADC的初始化和启动放在其他地方(如主函数中),只在需要时读取结果。

使用特权

评论回复
板凳
elephant00| | 2024-8-20 16:00 | 只看该作者
在 Disp_Vin() 的循环中,你每次迭代都重新计算 dispVin 数组的值,但这并不符合常规显示逻辑。通常,你会根据 ADC_GetResault() 返回的值计算一次,并更新 dispVin 数组,然后在循环中显示这些值。

使用特权

评论回复
地板
两只袜子| | 2024-8-20 18:00 | 只看该作者
在 for(i = 0; i <= 8; i++) 循环中,你访问了 ADvalueBuf[8],这是越界的,因为数组 ADvalueBuf 的索引是从0到7。应该使用 i < 8。

使用特权

评论回复
评论
boya355 2024-8-20 22:07 回复TA
高手明晰秋毫 , 是我大意了 谢谢细评 
boya355 2024-8-20 22:05 回复TA
高手明晰秋毫 , 是我大意了 谢谢细评 
5
jcky001| | 2024-8-20 19:09 | 只看该作者
考虑返回 float 类型的值,或者在函数外部处理转换。

使用特权

评论回复
6
boya355|  楼主 | 2024-8-20 22:21 | 只看该作者

i<=8 在此处  好像越界的,  毕竟总共8次  我试试  效果也是相同

使用特权

评论回复
7
丙丁先生| | 2024-8-21 06:53 | 只看该作者
根据您提供的代码,数码管显示不全的问题可能是由于在`Disp_Vin()`函数中多次调用`ADC_GetResault()`函数导致的。每次调用`ADC_GetResault()`函数时,都会重新初始化ADC并进行8次扫描,这可能导致数码管显示的数据不稳定。

为了解决这个问题,您可以将`ADC_GetResault()`函数的调用移出`Disp_Vin()`函数,并在主循环中调用一次。这样,您可以确保在进行数码管显示之前只进行一次ADC转换。以下是修改后的代码:

```c
void Disp_Vin()  //数码管待显示的 百 十 个
{
   unsigned char i;
        for(i=0 ; i<3; i++)
        {
        dispVin[0] = ( Vin*3700/4095)/100;               
  dispVin[1] = ( Vin*3700/4095 )  % 100 / 10;
  dispVin[2] = ( Vin*3700/4095 )  % 10 ;
                if(dispVin[0] == 0)                                   //高位0时 不显示
                {  dispVin[0] = 10;      
                        if (dispVin[1] == 0)   dispVin[1] = 10;  //高位0时 不显示
                 }
  }
}

int main()
{
    voltADC_init();
    while(1)
    {
        Vin = ADC_GetResault();
        Disp_Vin();
        // 在这里添加数码管显示的代码
    }
}
```

这样修改后,您的数码管应该可以正常显示了。如果仍然有问题,请检查硬件连接和数码管驱动部分的代码。

使用特权

评论回复
8
xionghaoyun| | 2024-8-21 09:03 | 只看该作者
51单片机打扰了

使用特权

评论回复
9
boya355|  楼主 | 2024-8-21 13:57 | 只看该作者
丙丁先生 发表于 2024-8-21 06:53
根据您提供的代码,数码管显示不全的问题可能是由于在`Disp_Vin()`函数中多次调用`ADC_GetResault()`函数导 ...

很有说服道理  高手! 我试试  再反馈   谢谢你的关注和参与

使用特权

评论回复
10
boya355|  楼主 | 2024-8-22 10:14 | 只看该作者
本帖最后由 boya355 于 2024-8-22 10:16 编辑
丙丁先生 发表于 2024-8-21 06:53
根据您提供的代码,数码管显示不全的问题可能是由于在`Disp_Vin()`函数中多次调用`ADC_GetResault()`函数导 ...

你好   按照你的思路调试后, 效果基本没有改变  还是段码呀!
不知究竟错在哪里?

使用特权

评论回复
11
shenxiaolin| | 2024-8-30 15:20 | 只看该作者
数码管显示有位数限制

使用特权

评论回复
12
yzh657531561| | 2024-8-30 22:59 | 只看该作者
unsigned int   ADC_GetResault()       //
{
        unsigned int AD_Dat = 0;            // 定义转换值
        unsigned int Tmp = 0;  
        static uchar i;      
        voltADC_init();
        SCANCON = 0x6F;                 // 单通道带缓存连续 扫描8次

        while(1)
        {
                if(AdcFlag == 1)          //ADC转换结束
                {
                        ADvalueBuf[0] = SCR0;
                        ADvalueBuf[1] = SCR1;
                        ADvalueBuf[2] = SCR2;
                        ADvalueBuf[3] = SCR3;
                        ADvalueBuf[4] = SCR4;
                        ADvalueBuf[5] = SCR5;
                        ADvalueBuf[6] = SCR6;
                        ADvalueBuf[7] = SCR7;
                        for(i = 0; i < 8; i ++)
                        {
                                ADvalue += ADvalueBuf[i];
                        }
                        ADvalue /= 8;       //8次扫描均值

                        if(ADvalue <= 0x10)
                        {
                                CV = 1;
                        }
                        else
                        {
                                CV =0;
                        }
                        AdcFlag = 0;         //
                        AdcBufCount = 0;
                        memset(ADvalueBuf, 0 ,10);    //清缓冲
                        IE1 |= 0x40;
                       
                        Vin = ADvalue;
                        return Vin;
                }
        }
}

void Disp_Vin()  //数码管待显示的 百 十 个
{
        unsigned int disp_value;
       
        disp_value=(unsigned long)ADC_GetResault()*3700/4095;
       
        dispVin[0] = disp_value/100;
        dispVin[1] = disp_value%100/10;
        dispVin[2] = disp_value%10;

        if(dispVin[0] == 0)                                   //高位0时 不显示
        {
                dispVin[0] = 10;      
                if(dispVin[1] == 0)
                {
                        dispVin[1] = 10;  //高位0时 不显示
                }
        }
}

使用特权

评论回复
13
boya355|  楼主 | 2024-9-13 08:38 | 只看该作者
yzh657531561 发表于 2024-8-30 22:59
unsigned int   ADC_GetResault()       //
{
        unsigned int AD_Dat = 0;            // 定义转换值

很是经典指导, 虽花谢花落, 但是精髓已在 受益无穷    感谢你的改进

使用特权

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

本版积分规则

5

主题

21

帖子

0

粉丝