打印

请教:程序为何不能正常运行?

[复制链接]
2662|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sbcceeq|  楼主 | 2011-6-21 19:29 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
TE, PWM, ic, ge
本帖最后由 sbcceeq 于 2011-6-22 13:22 编辑




众位高手好,我根据资料改编了一个程序,功能是控制充电和电机的正反转,使用PIC16F886,程序能通过编译,但是接在电路

板上之后运行,发现什么动作也没有,很是苦恼,程序里肯定有错误,但到底是什么导致无相应动作呢?比如我按键盘让电机正转,但什么动作也没有,盼望大家能帮我指出错误,我把程序和电路主图放在下面。
万分感谢!!!
#include <pic.h>

/*__CONFIG(0x3F71);*/
__CONFIG(HS&WDTDIS&LVPDIS);        
/***************/


    unsigned int t_count;
    unsigned char seco;                    // global seconds
    unsigned char min;                    // global minutes
    unsigned char hour;                   // global hour
   

#define uchar unsigned char
#define uint  unsigned int
#define T1_1MS        1000 //延时常数1000,此数用于TMR1每隔 1毫秒中断扫描键盘
void TRICKLE_charge();
void FAST_charge();
void DELAY(unsigned int n);
void init(void)
{
/***** TMR0设置 *****/
//option=0b00000111;
  T0CS=0; // 选择CLKOUT信号为时钟源
  PSA=0; // 预分频器给TIMER0用
  PS2=1;
  PS1=1;
  PS0=1; // 分频比为1:256
  TMR0=0; // Timer0计数值寄存器初值为零,单片机主频为4M,产生1S定时需要中断1000000/65536=15.28次近似取15次
  T0IF=0; // Timer0中断标志位清空  
  T0IE=1; // Timer0中断使能位置位,允许Timer0中断
  GIE=1;  // 总中断打开
  
//CCP1口PWM设置*****/
        TRISC2=0;                        //RC2/CCP1为输出
        PR2=39;                        //周期为(1/25)ms
        CCPR1L=0;        //当初始占空比为0,此值为0x20时,占空比0.8
        CCP1CON=0b00001100;        //PWM模式
        T2CON=0b00000100;        //TMR2预分频1:1,开始工作

// PORTB中断初始 *****/
//void                 PORTBINT( )可以起这个名, PORTB电平变化引起中断


RBPU=0;;//B口弱上拉有效*/
        PORTB=0X00;                        //RB1,RB2 先送低电平*/
        RBIE=1;;                                //B口电平变化中断允许 */
        PORTB=PORTB;                        //读B口的值,以锁存旧值,为变位中断创造条件*/
// TMR1中断初始 *****/

TMR1H=T1_1MS>>8;        //取延时常数的高字节,延时常数为1000,此数用于TMR1每隔 1毫秒中断扫描键盘
        TMR1L=T1_1MS;                //取延时常数的低字节
        TMR1IE=1;                        //TMR1中断使能
        INTCON=0b1000000;        //GIE、PEIE置1才能进入TMR1中断
        T1CON=0b00000001;                //TMR1预分频系数1:1,内部延时,开始工作


/***** I/O Ports *****/

        PORTA = 0x00;        //  Port A清零
ANSEL=0;
        PORTB = 0x00;        // Port B清零
        PORTC = 0x00;        //  Port C清零
        TRISA = 0x0F;        // Port A 低4位口为输入
        TRISB=0XE0;      // 输入:RB5,RB6,RB7 输出:RB1,RB2,RB3,RB4
        TRISC = 0xEB;        // 输入:RC7、RC6、RC5  输出:RC2
        /***** A/D *****/
        ADCON1 = 0x80;//Port A 模拟量输入,右对齐,每位AD转换时间TAD=32Tosc=8us
    }

// 在AD转换中用到的关闭PWM的函数//

void NO_PWM()                         //在下降沿时关闭PWM .
{
  if (CCPR1L != 0)
  {
   
      while(!RC2);                     // 等待PWM == 1
      while(RC2);                     // 等待PWM == 0  
   
    TRISC2 = 1;                          // 关闭PWM
  }
}   

#define VOLTAGE 1
#define TEMPERATURE 2
#define CURRENT 0
unsigned int  measure(unsigned char value)//用来采集电压电流等模拟量,经过处理得到平均值
{
   unsigned int av=0;  // 存放多次A/D转换10位结果的平均值
   uchar i=0;
   uchar a=0;
  switch (value)
  {//通道号赋值
    case VOLTAGE:
          NO_PWM();
        a=1;//选AN1模拟通道准备测电池电压
         break;   
    case TEMPERATURE:
          NO_PWM();
        a=2;//选AN2模拟通道准备测温度
          break;
     case CURRENT:
        a=0;//选AN0模拟通道准备测电池电流
        break;
        }  

    //进行AD转换,计算10位AD采样结果的平均值
av=0;
   for(i=10;i;--i)
    {uchar q;
unsigned int  x;
ADCON0=(0x81|(a<<3));//使能AD模块,设置并打开AD转换通道,AD时钟为32Tosc
    for (q=1;q<5;i++) NOP();        //打开AD通道后延时20us左右
        GODONE=1;                                //开始AD转换
        while (GODONE==1);                        //等待AD转换结束
        ADIF=0;                                //清AD结束标志
        x=ADRESH<<8;   
        x|=ADRESL;//AD转换结果转为10位
         av = av+x;
    }
    if(RC2==1)
       {TRISC2 = 0;
        }        //若关闭了CCP2口则现在打开
    av = av/10;
     return(av); // 返回处理后的平均值                  
}

void  TMINT(void)//计时器,充电时间控制用
{
  if(T0IE && T0IF)
  {
    T0IF=0;
        TMR0=0;//TMR0重新赋初值
     t_count++;
    if( t_count==15) //单片机主频为4M,产生1S定时需要中断1000000/65536=15.28次近似取15次
    {
      t_count=0;
if ( 60 == ++seco )
    {
      if ( 60 == ++min )
      {
        if ( 24 == ++hour )
        {
            hour = 0x00;
        }
        min = 0x00;
        }
        seco = 0x00;      
     }
    }

  }
}  

void DELAY(unsigned int n)//延时n毫秒
{
        unsigned int j;
        char k;
        for (j=0;j<n;j++)
                        for (k=246;k>0;k--)
                                NOP();
}







#define k1 RC6//正转按键
#define k2 RC7//反转按键
#define k3 RC5//停止按键

#define in1 RB5//上行程开关输入
#define in2 RB6//下行程开关输入
#define in3 RB7//红外输入

#define out1 RB3//正转输出
#define out2 RB4//反转输出



unsigned char keyval;  //储存按键值*/
void motor()  //电机控制函数
{
   keyval=0;              //按键值初始化为0,什么也不做
   while(1)
           {
                   switch(keyval)
                                  {
                                     case 1:  out1=0;out2=1;//K1按下,电机正转
                                                 break;
                                          case:  out1=1;out2=0;//K2按下,电机反转
                                                 break;
                                          case 3:  out1=0;out2=0;//K3按下,电机停止
                                                 break;
                                           }
                        
         }

          }
         


/*************************************************
函数功能:定时器TMR1的中断服务子程序,用于扫描键盘
**************************************************/
uint T1_100MS=1000;
void        keyint();

static void interrupt
isr(void)
{

uchar A,num;
if (TMR1IF==1)
        {        TMR1IF=0;                        //清TMR1溢出中断标志位
                TMR1H=T1_100MS>>8;        //延时常数重新赋值,常数为1000,此数用于TMR1每隔 1毫秒中断扫描键盘,TMR1H=(65536-

1000)/256
                TMR1L=T1_100MS;                //整形数赋给字符型变量,只赋整型的低字节,TMR1L=(65536-1000)%256
                if((PORTC&0xf0)!=0xf0)         //第一次检测到有键按下
                     {
                              DELAY(20);   //延时20ms再去检测,防止键盘抖动
                                   if(k1==0)keyval=1;      //按键k1被按下
                                       
                                        if(k2==0)keyval=2;      //按键k2被按下
                                         
                                        if(k3==0)keyval=3;      //按键k3被按下
                                         
                                                         
                      }
             if(A==1){num++;                            //电机反转(关门)启动计时标志
                                              //关门启动时间计数器
                   A=0 ;                             //电机反转(关门)启动计时标志清零
                 }
        }
else if(RBIF==1)keyint();        
else if(T0IF){TMINT();}
}


//PORTB端口电平变化中断服务程序,信号来自红外和行程开关,保护电机与人身安全
void        keyint()
{

if(RBIF)
{
        DELAY(10);                                ///软件延时10ms
        if ((RB7==0)||(RB6==0)||(RB5==0))                //确认开关信号是否为干扰
                                                        
        if(RB5==0)            //上行程信号输入后电机停止
        {        out1=0;  out2=0;}

            if(RB6==0)
                {        out1=0;  out2=0;}//下行程信号输入后电机停止

   
        PORTB=PORTB;                        ///读B口的值,改变中断发生的条件,避免键
                                                        //一直按下时,连续进行键识别
        RBIF=0;                                ///键扫描时可能会产生"电平变化"而使RBIF
}                                                        ///置1,再清除一次RBIF以避免额外中断
}



//快充,包括恒流充电和恒压充电**************************************************************************//
#define  MAX_I_FAST 614 //最大充电电流1A,经电流采样电路后的数值为(3*1023)/5=614
#define I_BUFFER 8 //电流允许误差
#define I_tricle 62 //涓充转换电流,充电电流小于此值时就认为已转到涓充阶段,(3*0.1)/1023=62
#define MAX_TEMP_ABS 1023 // 充电允许的最大温度,超过此温度,电池不应充电
#define MIN_TEMP_ABS 1
#define MAX_TEMP_FAST 800
#define MiX_VOLTAGE 584   //电池允许充电的最低电压,低于此值,电池属故障,292对应电池20V
#define MaX_VOLTAGE  865
#define VOLT_const 848// 恒压充电时的电压,对应于恒压充电电压29V
#define  VOLT_TOLERANCE 8//恒压充电时电压允许误差
#define VOLT_TRICKLE 818//涓充时电压 ,对应于涓充充电电压28V
#define tricle_TIME_need 30//涓充时间30分钟
#define MAX_TIME_FAST 90 //根据电池容量和最大电流得到快充最大时间是90分钟左右







void FAST_charge()
{
    unsigned int temp = 0;
    unsigned char fast_finish_hour = 0,fast_finish_min,fast_charge_I;
     unsigned char last_min;

   unsigned char        A=1;//快充标志位

    temp = measure(TEMPERATURE);
    // if TEMPERATURE within absolute limits
    if ((temp > MIN_TEMP_ABS) && (temp < MAX_TEMP_ABS)&& (temp <MAX_TEMP_FAST))
    {
        // calculate FAST charge finish time
        fast_finish_min = (min + MAX_TIME_FAST);
        fast_finish_hour = hour;
        while (fast_finish_min        > 60)
        {
            fast_finish_min = fast_finish_min        - 60;
            fast_finish_hour++;
        }
        
        CCPR1L = 0x00;
         
         temp = measure(VOLTAGE);
        if ((temp > MiX_VOLTAGE) &&(temp < MaX_VOLTAGE))      //MiX_VOLTAGE  是我定义的最小电池电压,应该是10V
        {
            /*恒流充电*/   
            do
                {
                    fast_charge_I = measure(CURRENT);
                    if (fast_charge_I < (MAX_I_FAST-I_BUFFER))
                        CCPR1L++;
                    else if (fast_charge_I > (MAX_I_FAST-I_BUFFER))//fast_charge_I是恒流电流
                    CCPR1L--;
                } while        (fast_charge_I != (MAX_I_FAST-I_BUFFER));//取成614-8=606
        }
      
         //恒压充电 VOLT_const就是恒压充电电压28V对应848,没有加公差8
        while ((temp >= (VOLT_const - VOLT_TOLERANCE)) && (temp <= (VOLT_const + VOLT_TOLERANCE)))  
        {
           
                do
                {
                    temp = measure(VOLTAGE);
                           if (temp < VOLT_const)
                        CCPR1L++;
                    else if (temp > VOLT_const)
                        CCPR1L--;
                } while        (temp != VOLT_const);


//快充时间溢出
                        if ((hour        == fast_finish_hour)&&(min        == fast_finish_min))
                    {
                               NO_PWM();
                               RB2=1;
                        }
            
            temp = measure(TEMPERATURE);
                        if ( temp >MAX_TEMP_ABS)
                        {
                            NO_PWM();
                                RB2=1;
                        }

            temp = measure(CURRENT);
                        if ( temp >        MAX_I_FAST)
                        {
                                //电流超过最大快充电流时禁止PWM输出,故障指示亮
                         NO_PWM();
                          RB2=1;
                        
                        }

            //每隔一分钟检测电流是否到涓充转换电流,若到就转涓充
            if (min != last_min)   
            {
                last_min = min;
                temp = measure(CURRENT);
                            if ( temp <        I_tricle)//I_tricle是涓充电流
                            {
                                       
               TRICKLE_charge();  //转涓充
                            }
            }                           
        }
    }
   
                else
                {   NO_PWM();
                    RB2=1;//电池电压过低,无法充电,报警响,提示要更换电池
        }
            
}

// 涓充
//************************************************************************************/
unsigned char trickle_finish_min = 0,tricle_min=0;

uchar last_min=0,tricle_hour=0;
void TRICKLE_charge()
{
    unsigned int temp = 0;
   
    unsigned char trickle_finish_hour = 0;
       // if TEMPERATURE within absolute limits
        temp = measure(TEMPERATURE);
        if ((temp > MIN_TEMP_ABS) &&(temp < MAX_TEMP_ABS))
        {
            
// if charge voltage lower than absolute max charge voltage
            if (measure(VOLTAGE) <= (VOLT_TRICKLE + VOLT_TOLERANCE))//818对应是涓充电压,8对应变化量,则相加为826
            {
                   if (min != last_min)   
                    {
                        last_min = min;
                        if ( (measure(CURRENT)) <I_tricle)//I_tricle)是我自己定义的在涓充时的电流
                        {
                            // calculate tricle finish time
                            tricle_min = (min + tricle_TIME_need);//tricle_TIME_need是我自己定义的涓充时间
                            tricle_hour = hour;
                            while (tricle_min > 60)
                            {
                                tricle_min = tricle_min - 60;
                                tricle_hour++;
                            }            
                        }
                     }
                    do                      // set VOLT_TRICKLE
                    {
                        temp = measure(VOLTAGE);
                        if ((temp < VOLT_TRICKLE)&&(CCPR1L < 0xFF))
                        {
                            CCPR1L++;
                        }
                        if ((temp > VOLT_TRICKLE)&&(CCPR1L > 0x00))
                        {
                            CCPR1L--;
                        }
                    }while (temp!= VOLT_TRICKLE);    // VOLT_TRICKLE is set now      
                       
          if ((hour == tricle_hour) && (min == tricle_min))                              
                    {
                           
                                             NO_PWM();
                         RB1=1;//充满灯亮
                     }
                                                                              
                        }
     

            else if(RB2=0)
                           {
                RB2=1;// 故障灯亮
                    }
                 
                   }                 
            else if(RB2=0)
            {   
                RB2=1;//故障灯亮
            }
  
}







void main()
{init();
while(1)
{
FAST_charge();
motor();
}
}
沙发
yewuyi| | 2011-6-22 08:53 | 只看该作者
你慢慢等,也许等各万把年会有人来帮你看程序的。

使用特权

评论回复
板凳
sbcceeq|  楼主 | 2011-6-22 13:15 | 只看该作者
void main()
{void init(void);
while(1)
{
FAST_charge();
motor();
}
}
应改成
void main()
{init();
while(1)
{
FAST_charge();
motor();
}
}
之后发现程序能运行部分,一上电就是RB2输出为高电平,我现在只想试里面的面板按键控制电机正反转这一个模块,但就这一个模块还是调不好,上电后按任何键就是没有输出。很是苦恼着急,盼望各把万年大师早点现身
另外程序有一些错误我已修改,修改后的见一楼,现在程序里的键盘不起作用,当务之急是先克服这个。

使用特权

评论回复
地板
sbcceeq|  楼主 | 2011-6-23 09:30 | 只看该作者
经过一个高人的指点,现在电机键盘控制完全好了,是因为键盘中断函数static void interrupt
isr(void)出了问题,里有一个20ms的DELAY延时 本身中断就是1ms  所以矛盾了。程序一直在这个中断里死循环,现在的程序调到充电部分了,问题是没有PWM波形,PWM设置本身没有错误,应该是AD转换算返回平均值的measure函数或AD出了问题,这个函数一直没有正确执行,不知怎么改好

使用特权

评论回复
5
qzhui121| | 2011-6-23 15:06 | 只看该作者
我的乖乖啊!!好长,好晕的!!看不懂

使用特权

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

本版积分规则

个人签名:fdfasfsadf

13

主题

41

帖子

0

粉丝