打印

哪位前辈能告诉我,Pic16f883测电压不准是怎么回事?

[复制链接]
134|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lvsezhidu|  楼主 | 2025-3-17 21:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我手头有两只pic16f883,不想报废,于是参考别人代码编写了2路A/D转换程序,采用Proteus仿真误差很大,明明是5V参考电压,结果显示8V多,不知哪里出问题了?时钟从1MHZ~20MHZ都是一样的结果,不知是Proteus仿真软件的bug还是代码有问题,请大侠帮忙//  名称: 数码管显示两路A/D转换结果     
//-----------------------------------------------------------------
//  说明: 调节RV1和RV2时,两路模拟电压将显示在集成式数码管上.
//
//-----------------------------------------------------------------
#include <pic.h>
__CONFIG(0x2004);      //?????? //配置字要在头文件后 PROTEUS仿真也要有  改为__CONFIG(0x2002); 也不行
//bit13=1禁止在线调试 bit12=0关系RB3数字口  bit11=0禁止故障保护时钟监视器 bit10 =0禁止内外时钟切换
//bit9/8=00禁止欠压复位 bit7=0使能RAM保护 bit6=0使能ROM bit5=0内部复位RB3为数字引脚
//bit4=0使能上电延时定时器 bit3=0禁止看门狗 bit2:0=100INTOSCO振荡,RA6/7为I/O口     手册14.1配置位

#define INT8U   unsigned char
#define INT16U  unsigned int
#define _XTAL_FREQ 4000000UL
//共阳数码管0~9的数字段码,最后一位为黑屏
const INT8U SEG_CODE[] =
{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF};
//两路模拟转换结果显示缓冲,显示格式为:X.XX X.XX ,第4位和第8位不显示
volatile INT8U Display_Buffer[] = {0,0,0,10,0,0,0,10};

//1.108ms  @1MHZ
void delay_xms(INT16U ms)
{
        INT8U i;
        while(ms--)
        for(i = 0; i < 20; i++);
}

//-----------------------------------------------------------------
// 对通道Channel进行模数转换,转换结果分解存入显示缓冲
//-----------------------------------------------------------------
void ADC_Convert(INT8U Channel)
{   

   //设置ADCON0寄存器的通道选择位CHS[3..0]=Channel(0~13)
   //选择通道后等待
   CHS3 = Channel >> 3;
   CHS2 = Channel >> 2;
   CHS1 = Channel >> 1;
   CHS0 = Channel >> 0;

        //__delay_us(1);       //选择通道后等待
   delay_xms(10);
   //开始转换--->等待,直到一次转换结束(ADGO还可替换成GO_DONE)
   //GO_DONE = 1;  while(GO_DONE);
   //ADGO = 1;  while(ADGO);    //PIC16F877的写法
    GODONE = 1;while(GODONE);
   //读取转换结果,并转换为电压值
   //参考电压5v,所以转换结果*500/1023.0,使结果在000~500间
   int  Result = (  int) ((ADRESL + (ADRESH << 8)) * 500.0 / 1023.0);
   //AN0的结果放入数组0,1,2单元中,AN1的结果放入数组4,5,6单元中
    if (0 == Channel)     //通道0的在左面3个数码管显示
   {
           Display_Buffer[0] = Result / 100;
           Display_Buffer[1] = Result / 10 % 10;
           Display_Buffer[2] = Result % 10;
   }
    else if (1 == Channel)  //通道1的在4、5、6数码管显示
   {
           Display_Buffer[4] = Result / 100;
           Display_Buffer[5] = Result / 10 % 10;
           Display_Buffer[6] = Result % 10;
   }  
}

//-----------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------
void main()
{  
  //SCS= 1;                     //内部时钟,OSCCON配置 手册P64,
                     //0=时钟由配置字1的FOSC2:0决定,1=时钟由IRCF2:0决定
  //IRCF2=1;IRCF1=1;IRCF0=0;            //内部4MHZ,OSCCON配置 手册P64

  //OSTS = 0;                       //器件依靠内部内部时钟运行,OSCCON配置 手册P64
                                    //1=时钟靠时钟配置字1的FOSC2:0决定,手册P71
   TRISB = TRISC = 0x00;                      //配置数码管输出端口
   PORTB = PORTC = 0x00;
   //以下配置用于TMR0定时器刷新数码管显示
    PSA = 0;                                //前分频给TMR0
        PS2 = 0; PS1 = PS0 = 1;                 //16分频(OPTION低3位为011)
        TMR0 = (INT8U)(256 - _XTAL_FREQ / 4 / 16 * 0.002); //2ms定时
        T0IF = 0;                               //清TMR0中断标志
        T0CS = 0;                               //TMR0工作于定时器
        T0IE = 1;                               //允许TMR0溢出中断
        GIE = 1;                                //开全局中断
//PEIE = 1;

   TRISA0 = 1; TRISA1 = 1;           //AN0/AN1输入口
   ANS0=1;     ANS1=1;              //AN0/AN1模拟输入
        ADCS1 = 1; ADCS0 =0;              //设置AD转换时钟为F_OSC/32
   VCFG1=0;VCFG0=0;               //以电源脚VDD\VSS为参考电压
    //VRSS = 0;VROE =0;              //VRCON寄存器的bit6/4 手册P98
        ADFM = 1;                               //转换结果右对齐
        ADON = 1;                               //打开A/D转换模块
        //__delay_ms(1700);

   delay_xms(3000);             //等待AD模块稳定
   while(1)                    //AN0,1通道开始持续A/D转换
   {
       ADC_Convert(0);delay_xms(10);//__delay_ms(5);
           ADC_Convert(1);delay_xms(10);//__delay_ms(5);
   }
}

//-----------------------------------------------------------------
// TMR0定时器溢出中断控制数码管刷新显示两路A/D转换结果
//-----------------------------------------------------------------
void interrupt TMR0_ISR(void )
{
     static INT8U i = 0;
     if (T0IF&&T0IE)
     {
        //PORTB = 0xff;
        PORTC = 0x00;                       //暂时关闭位码
                PORTB = SEG_CODE[Display_Buffer[i]]; //发送数字段码
                PORTC = 1 << i;                      //发送数码管位码
                if(i== 0 || i == 4)   RB7 = 0;       //点亮小数点
        i = (i + 1) & 0x07;                  //下一位数字索引
        TMR0 = (INT8U)(256 - _XTAL_FREQ / 4 / 16 * 0.002);//位间延时间隔2ms
        T0IF = 0;                            //清TMR0中断标志
     }
}

使用特权

评论回复

相关帖子

沙发
yzdel7| | 2025-3-17 23:28 | 只看该作者
你先检查一下你的电压转换结果是否读取正确,是在0到1023之间,若是这个没问题再检查result变量的结果,这样应该可以排查。

使用特权

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

本版积分规则

1

主题

2

帖子

0

粉丝