为什么AD采样无显示?(附C源代码)

2020-02-09 09:16发布

#include <pic.h> //16F877A,4MHz晶振
#include <math.h>   
__CONFIG(XT&WDTEN&LVPDIS);
#define uchar unsigned char
#define uint  unsigned int
uchar dis_table[]={0xeb,0x88,0xb3,0xba,0xd8,0x7a,0x7b,0xa8,0xfb,0xfa,0x00};//数码管不带点显示
static uchar bank2  dis_table1[]={0xef,0x8c,0xb7,0xbe,0xdc,0x7e,0x7f,0xac,0xff,0xfe,0x00};//带点显示
uchar tmr0num,ledflashnum,whichdisp;//led闪烁计数值
uint lednum[3],dischargenum;         //AD值lednum[0]为放电电流值[1]充电电流值[2]为电池电压值

void init(void)
{
   TRISA=0xff;          
   TRISB=0xf9;           //RB0RB1RB2为输出,其他未用设置为输入
   TRISC=0x03;           //RC2-RC7置为输出0,RC0RC1设置为输入1
   TRISD=0x00;  //TRISE不能随便给值否则会影响到RD脚功能见书P191《实战上》
      
}       
void AD_init(void)
{
        ADCS0=0;
        ADCS1=1;        //AD转换时钟选择位=FOSC/32               
        PCFG0=1;
        PCFG1=0;
        PCFG2=0;               
        PCFG3=1;//设定ADCON1,1001RA0RARA5为AD转换口       
        ADIE=1;       
        ADFM=1;//设定ADCON1AD值右对齐
     
}
void intinit(void)//INT中断初始化
{
RB0=1;
INTEDG=1;
INTF=0;
INTE=1;
GIE=1;
}
void tmr0init(void)//TIMR0初始化
{
  OPTION=0x06;    //0001 0110 预分频128,允许内部上拉,预分频分配给TMR0,用于内部指令计数
  T0IF=0;   
  GIE=1;
  T0IE=1;
  PEIE=1;
  TMR0=217;//217初值,每5ms中断一次
}
uint adc_read(uchar channel)//电流采样、放电次数、电池电压
{
        uint k,buf,adbuf;
        double i_val;
        ADCON0 = (channel << 3) + 0x81;                // 启动 AD模块工作, FOSC/32 osc.
        asm("CLRWDT");
        asm("NOP");
        asm("NOP");
        asm("NOP");
        asm("NOP");
        ADGO = 1;//启动转换
        while(ADGO)
                continue;                //wait for conversion complete*/
        adbuf=ADRESH*256+ADRESL;               
        i_val=(double)adbuf;
    if(channel==0)//AN0放电电流采样通道
        {
      i_val=(i_val*38.34)/1023;//放电电流
          if(i_val>2500) i_val=2500;
        }
        if(channel==2)//AN2充电电流采样通道
        {
        ;
        }

        if(channel==4)//AN4电压采样通道
        {

          i_val=(i_val*15.76)/1023;//电压采样转换
      if(i_val>1000) i_val=1000;
        }
        k=(int)i_val;
        return k;
       
}
void interrupt int0tmr0(void)
{
   if(INTF&&INTE)
    {
    INTF=0;
    whichdisp++;
    dischargenum++;
    if(dischargenum>9999) dischargenum=0;
    if(whichdisp>=3) whichdisp=0;
    }
   if(T0IF&&T0IE)
    {
     T0IF=0;
   
              //if((ledflashnum==20)&&(lednum>=600)) RB1=!RB1;//如果电压一直大于6V则红灯闪烁
                  //if(lednum<600) RB1=1; //如果电压低于6V则红灯常亮,表示放电完毕,正在休息1个小时。                           
   
     switch (whichdisp)//选择显示放电电流?放电次数?还是电池电压要根据INTRB0按键顺序
       {
           case 0://电池电压显示
                 {
                 if(tmr0num==0)
                    {
                    RC5=1;
                    RC6=1;
                    RC7=1;
                if((lednum[2]/1000)>0)
                        {
                            PORTD=dis_table[lednum[2]/1000];//第1位显示
                            RC4=0;
                            }
                            else  RC4=1;
                }      
             if(tmr0num==1)
                {
                    RC4=1;
                    RC6=1;
                    RC7=1;
                           PORTD=dis_table1[lednum[2]%1000/100];//第2位带点显示
                        RC5=0;
                }
             if(tmr0num==2)
                {
                RC4=1;
                RC5=1;
                RC7=1;
                        PORTD=dis_table[lednum[2]%100/10];//第3位显示
                        RC6=0;
                    }
             if(tmr0num==3)
                {
                RC4=1;
                RC5=1;
                RC6=1;
                    PORTD=dis_table[lednum[2]%10];//第4位显示
                    RC7=0;
                }
             break;  
                 }   //电池电压在此行选择结束
                
           case 1://放电次数显示
                 {
                 if(tmr0num==0)
                {
                     RC5=1;
                     RC6=1;
                     RC7=1;
                 PORTD=dis_table[dischargenum/1000];//第1位显示
                         RC4=0;
                        }      
             if(tmr0num==1)
                {
                    RC4=1;
                    RC6=1;
                    RC7=1;
                           PORTD=dis_table[dischargenum%1000/100];//第2位显示
                        RC5=0;
                }
             if(tmr0num==2)
                {
                RC4=1;
                RC5=1;
                RC7=1;
                        PORTD=dis_table[dischargenum%100/10];//第3位显示
                        RC6=0;
                    }
             if(tmr0num==3)
                {
                RC4=1;
                RC5=1;
                RC6=1;
                    PORTD=dis_table[dischargenum%10];//第4位显示
                    RC7=0;
                }
                 break;
                 }
           case 2: //放电电流显示
                {
                    if(tmr0num==0)
                {
                     RC5=1;
                     RC6=1;
                     RC7=1;
                 if((lednum[0]/1000)>0)
                        {
                            PORTD=dis_table[lednum[0]/1000];//第1位显示
                            RC4=0;
                            }
                            else  RC4=1;
                }      
             if(tmr0num==1)
                {
                    RC4=1;
                    RC6=1;
                    RC7=1;
                           PORTD=dis_table[lednum[0]%1000/100];//第2位显示
                        RC5=0;
                }
             if(tmr0num==2)
                {
                RC4=1;
                RC5=1;
                RC7=1;
                        PORTD=dis_table[lednum[0]%100/10];//第3位显示
                        RC6=0;
                    }
             if(tmr0num==3)
                {
                RC4=1;
                RC5=1;
                RC6=1;
                    PORTD=dis_table[lednum[0]%10];//第4位显示
                    RC7=0;
                }
             break;//放电电流显示在此行选择结束
                 }
           default:
                 break;
                
       }  //SWITCH选择到此结束
   
   TMR0=217;//217初值,每5ms中断一次
   tmr0num++;
   if(tmr0num>=4)tmr0num=0;
   }   //T0中断到此行结束
}

void main()
{
uchar i;
init();
intinit();
tmr0init();
AD_init();

while(1)
  {
   asm("CLRWDT");   
   for(i=0;i>=3;i++)
        
        lednum=adc_read(i*2);//轮循采样
      
      
   }
  
          
     
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
4条回答
spcliu
2020-02-09 13:33
回复【1楼】surf_131
采样采到没有?在程序中插入探测标志(闪烁的led),先看看。
有了adc通过的前提,再看读数数值是否与预想一致,也就是那个lednum数组是否放进了数据。
按键读出部分不知道为什么没有防抖。显示部分是否能跑通没有细看。这部分需要用假数据单独测试。
还是换用16f887比较好。其ansel/anselh都能够显性设置ad端口。
-----------------------------------------------------------------------

单独试了,各个AD通道及动态数码管显示,都正常的。

一周热门 更多>