AVR单片机控制的电动自行车驱动系统

发布者:真瓷堂最新更新时间:2016-10-29 来源: eefocus关键字:AVR  单片机控制  电动自行车  驱动系统 手机看文章 扫描二维码
随时随地手机看文章
#i nclude 

#i nclude 

//电动车双闭环程序,采用双闭环方式控制电机,以得到最好的zh转速性能,并且可以

//限制电机的最大电流。本应用程序用到两个CCP部件,其中CCP1用于PWM输出,以控

//制电机电压;CCP2用于触发AD,定时器TMR2、TMR1,INT中断,RB口电平变化中断,

//看门狗以及6个通用I/O口

#define AND  0xe0                //状态采集5,6,7位  

#define CURA 0X0a                //电流环比例和积分系数之和

#define CURB 0X09                //电流环比例系数

#define THL  0X6400               //电流环最大输出

#define FULLDUTY 0X0FF             //占空比为1时的高电平时间

#define SPEA 0X1d            //转速环比例和积分系数之和

#define SPEB 0X1c             //转速环比例系数

#define GCURHILO 0X0330               //转速环最大输出

#define GCURH 0X33              //最大给定电流

#define GSPEH 0X67              //最大转速给定

#define TSON 0X38          //手柄开启电压1.1 V,TSON*2为刹车后手柄开启电压,即 

                                 //2.2 V

#define VOLON 0X4c          //低电压保护重开电压3.0 V即33 V

#define VOLOFF 0X49           //低电压保护关断电压2.86 V即31.5 V

volatile unsigned char DELAYH,DELAYL,oldstate,speed,

        speedcount,tsh,count_ts,count_vol,gcur,currenth,

        voltage;        //寄存器定义

static bit sp1,spe,ts,volflag,spepid,lowpower,

        off,shutdown,curpid;     //标志位定义

static volatile unsigned char new[10]={0xaf,0xbe,0xff,0x7e,0xcf,

        0xff,0xd7,0x77,0xff,0xff};       //状态寄存器表

//------------PIC16F877初始化子程序------------

void INIT877()

           PORTC=0X0FF;           //关断所有MOSFET

           TRISC=0X02;            //设置C口输出

           PIE1=0X00;             //中断寄存器初始化,关断所有中断

           TRISA=0XCF;             //设置RA4,RA5 输出

           TRISB=0XEF;             //RB 口高三位输入,采集电机三相的霍尔信号

           PORTC=new[(PORTB&AND)>>5];//采集第一次霍尔信号,并输出相应的信号,导通

                                     //两个MOS管

           T2CON=0X01;          //TMR2 4分频

           CCPR1L=0X0FF;         //初始时PWM输出全高

           CCP1CON=0X0FF;         //CCP1设置为PWM方式

           CCP2CON=0X0B;           //CCP2设置为特殊方式,以触发AD

           ADCON0=0X81;             //AD时钟为32分频,且AD使能,选择AN0通道采集手

                                    //柄电压 

           TMR2=0X00;                  //TMR2寄存器初始化

           TMR1H=0X00;                //TMR1寄存器初始化

           TMR1L=0X00;

           T1CON=0X00;              //TMR1为

           CCPR2H=0X08;

           CCPR2L=0X00;            //电流采样周期设置为TAD=512 μs

           PR2=0XC7;                 //PWM频率设置为5 kHz

           ADCON1=0X02;              //AD结果左移

           OPTION=0XFB;              //INT上升沿触发

           TMR2ON=1;                 //PWM开始工作

           INTCON=0XD8;              //中断设置GIE=1,PEIE=1,RBIE=1

           ADIE=1;              //AD中断使能

           speedcount=0x00;         //转速计数寄存器

           speed=0x7f;              //转速保持寄存器

           spe=1;     //低速标志位

           sp1=1;      //低速标志位

           oldstate=0x0ff;      //初始状态设置,区别于其他状态

           count_ts=0x08;      //电流采样8次,采集1次手柄

           count_vol=0x00;       //采样256次手柄,采集1次电池电压

           ts=1;       //可以采集手柄值的标志位

           ADGO=1;        //AD采样使能

           TMR1ON=1;                 //CCP2部件开始工作

   }

   //------------延时子程序---------------

#pragma interrupt_level 1

void DELAY1(x)

         char x;

   {

          DELAYH=x;                //延时参数设置

      #asm

        DELAY2 MOVLW 0X06

          MOVWF _DELAYL

        DELAY1 DECFSZ _DELAYL

        GOTO DELAY1

        DECFSZ _DELAYH

        GOTO DELAY2

     #endasm

  }

    //-----------状态采集子程序----------------------

void sample()

  {

        char state1,state2,state3,x;

      do  {

         x=1;

         state1=(PORTB&AND);        //霍尔信号采集

         DELAY1(x);

         state2=(PORTB&AND);

         }while(state1-state2);        //当三次采样结果不相同时继续采集状态

         if(state1-oldstate!=0)        //看本次采样结果是否与上次相同,不同

                                               //则执行

             {oldstate=state1;            //将本次状态设置为旧状态

               state1=(oldstate>>5);

               PORTC=new[state1];        //C口输出相应的信号触发两个MOS管

                 if(sp1==1){spe=1;sp1=0;}

                  else {           //如果转速很低,则spe置1

                        spe=0;sp1=0;

                        speedcount<<=1;

                        state3=(TMR1H>>2);     //否则,spe=0,计转速

                        speed=speedcount+state3;   //speed寄存器为每256 μs加1

               } 

                speedcount=0;

        }

}

   //-----------------AD采样子程序----------------------

void AD()

  {

           char x;

           ADIF=0;          //清AD中断标志位

           if(ts==1){               //如果为手柄采样,则采样手柄值

           CHS0=1;                   //选择电流采样通道

           count_vol=count_vol+1;      //电池采样计数寄存器

           spepid=1;              //置转速闭环运算标志

           ts=0;tsh=ADRESH;       //存手柄值

           if(count_vol==0) {   //如果电池采样时间到,则选择AN2通道,采集电池电压

           CHS0=0;CHS1=1;volflag=1;x=1;DELAY1(x);ADGO=1;

          }

      }

         else if(volflag==1) {    //电池采样完毕,进行相应的处理

         CHS1=0;CHS0=1;volflag=0;voltage=ADRESH;lowpower=1;

     }

        else

                  {         //否则,中断为采样电流中断

           speedcount=speedcount+1;   //speedcount寄存器加1,作为测量转速用

           if(speedcount>0x3d) 

           sp1=1;            //如果转速低于1 000 000 μs/(512 μs*3eh*3)    

                                    // 则认为为低速状态

          currenth=ADRESH;

          curpid=1;

          count_ts=count_ts-1;

          if(count_ts==0) {     //如果手柄时间到,则转入手柄采样通道

           CHS0=0;count_ts=0x08;ts=1;x=1;DELAY1(x);ADGO=1;

           }

     }

}

   //-------------刹车处理子程序------------------

void BREAKON()

{

         char x;

         off=0;             //off清零,如果是干扰则不复位

         shutdown=0;

         if(RB0==1) {     //如果刹车信号为真,则停止输出电压

         ADIE=0;         //关AD中断

                INTE=0;            //关刹车中断

                CCPR1L=FULLDUTY;          //输出电压0

                TMR1ON=0;      //关CCP2,不再触发AD

                for(;ADGO==1;) continue;   //如正在采样,则等待采样结束

                ADIF=0;       //ADIF位清零

                CHS0=0;      //选择通道0采样手柄

                CHS1=0;

                x=1;

    DELAY1(x);

          do {

                        ADGO=1;

                        for(;ADIF==0;)continue;

                         ADIF=0;

                         CCPR1L=FULLDUTY;

                         asm("CLRWDT");

                         tsh=(ADRESH>>1);

                     }while(tsh>TSON||RB0==1); //当手柄值大于2.2 V或刹车仍旧继续时,执行以

                                                //上语句

               off=1; //置复位标志

            }

  }

     //---------欠保护子程序-------------------

void POWER()

   {

             char x;

             lowpower=0;

             voltage>>=1; //电压值换为7位,以利于单字节运算

             if(voltage        ADIE=0;

                INTE=0;

                TMR1ON=0;

                CCPR1L=FULLDUTY;

                for(;ADGO==1;)continue;

                ADIF=0;

                CHS0=0;CHS1=1;

                 x=1;

  DELAY1(x);

           do{ADGO=1;

                        for(;ADIF==0;)continue;

                        ADIF=0;

                        voltage=(ADRESH>>1);

                        CCPR1L=FULLDUTY;

                        asm("CLRWDT");

                    }while(voltage            off=1; //置复位标志

       }

  }

     //------------电流环运算子程序-----------------

void CURPI()

        static int curep=0x00,curek=0x00,curuk=0x00;

           union data{int pwm;

           char a[2];}b; //定义电流环运算寄存器

           curpid=0; //清电流运算标志

             curep=curek*CURB; //计算上一次偏差与比例系数的积

               if(currenth<2)currenth=2; //如果采样电流为零,则认为有一个小电

 

流以利于

//使转速下降

            currenth>>=1;

            curek=gcur-currenth; //计算本次偏差

           curuk=curuk+curek*CURA-curep; //按闭环PI运算方式得到本次输出结果,

 

//面对结果进行处理

            if(curuk<0x00) { //如果输出小于零,则认为输出为零

            curuk=0;CCPR1L=FULLDUTY;CCP1X=0;CCP1Y=0; 

     } 

       else if(curuk-THL>=0) 

         { //如果输出大于限幅值,则输出最大电压

                  curuk=THL;CCPR1L=0;CCP1X=0;CCP1Y=0;

               }

    else { //否则,按比例输出相应的高电平时间到CCPR1寄存器

                        b.pwm=THL-curuk;

                        b.pwm<<=1;

                        CCPR1L=b.a[1];  //CCPR1L=(b.pwm>>8)&0x0ff;将PWM寄存器的高半字节

                        if(b.pwm&0x80!=0) CCP1X=1;

                        else CCP1X=0;

                        if(b.pwm&0x40!=0) CCP1Y=1;

                        else CCP1Y=0;

           }

   }

  //---------------转速环运算子程序-----------------------

void SPEPI()

{

        static int speep=0x00,speek=0x00,speuk=0x00;

        int tsh1,speed1; //转速寄存器定义

        spepid=0; //清转速运算标志 

          if(spe==1)

         speed1=0x00; //若转速太低,则认为转速为零

         else speed1=0x7f-speed; //否则计算实际转速

         if(speed1<0) speed1=0;

         speep=speek*SPEB;

         tsh1=tsh-0x38; //得到计算用的手柄值

         speek=tsh1-speed1;

         if(tsh1<0) {speuk=0;gcur=0;} //当手柄值低于1.1 V时,则认为手柄给定为零

        else { //否则,计算相应的转速环输出

          if(tsh1>=GSPEH) //限制最大转速

          tsh1=GSPEH;

         speuk=speuk+speek*SPEA-speep; //计算得转速环输出

          if(speuk<=0X00) {speuk=0x00;gcur=0x00;}//转速环输出处理

          else if(speuk>GCURHILO) { //转速环输出限制,即限制最大电流约12 

 

A

            speuk=GCURHILO;gcur=GCURH;}

             else { //调速状态时的输出

                gcur=(speuk>>4)&0x0ff;

             }

      }

}

    //-----------主程序-------------------------

main()

{

        for(;;){

         INIT877(); //单片机复位后,先对其进行初始化

           off=0; //清复位标志

          for(;off==0;) { //复位标志为零,则执行下面程序,否则复位

           if(curpid==1) CURPI(); //电流PI运算

                else if(spepid==1) SPEPI(); //转速PI运算

                else if(lowpower==1) POWER();

                else if(shutdown==1) BREAKON();

                asm("CLRWDT");

           }

      }

}

    //---------中断服务子程序---------------------

#pragma interrupt_level 1

void interrupt INTS(void)

         if(RBIF==1) {RBIF=0;sample();}

         else if(ADIF==1) AD();

         else if(INTF==1)

        {shutdown=1;INTF=0;} //刹车中断来,置刹车标志

}

关键字:AVR  单片机控制  电动自行车  驱动系统 引用地址:AVR单片机控制的电动自行车驱动系统

上一篇:M8,ICCAVR下的温度传感器18B20程序
下一篇:20x4字符液晶的函数

推荐阅读最新更新时间:2024-03-16 15:18

AVR开发 Arduino方法(附一) 工具链与调试技术
前文中所有代码都可以使用Arduino IDE编译通过,电路图都是使用Fritzing绘制的。Arduino IDE和Fritzing都可以运行在多种操作系统上,可以通过以下方式获取它们: 1. Arduino IDE 在浏览器中访问https://www.arduino.cc/en/Main/Software: 找到“Download the Arduino IDE”,根据自己的操作系统下载相应版本的Arduino IDE即可。如果你使用的是Windows操作系统,建议选择“Windows Installer”版本,可以省去安装驱动程序的麻烦。 Arduino IDE安装完成后,还需要对它的配置文件进行一些修改,以便进行
[单片机]
<font color='red'>AVR</font>开发 Arduino方法(附一) 工具链与调试技术
关于AVR单片机熔丝位的设置和拯救方法大全
熔丝位是ATMEL公司AVR单片机比较独到的特征。在每一种型号的AVR单片机内部都有一些特定含义的熔丝位,其特性表现为多次擦写的E²PROM。用户通过配置(编程)这些熔丝位,可以固定地设置AVR的一些特性,参数以及I/O配置等,当然也包括对片内运行代码的锁定(加密)。 用户使用并行编程方式、ISP编程方式、JTAG编程方式都可以对AVR的熔丝位进行配置,但不同的编程工具软件提供对熔丝位的配置方式(指人机界面)也是不同的。有的是通过直接填写熔丝位位值(如:CVAVR、PonyProg2000和SLISP等),有的是通过列出表格选择(如AVR STUDIO、BASCOM-AVR)。前者程序界面比较简单,但是需要用户在仔细查询操作,
[单片机]
关于<font color='red'>AVR</font>单片机熔丝位的设置和拯救方法大全
AVR单片机定时器的要点
  分5种工作类型   一 普通模式 WGM1=0跟51的普通模式差不多,有TOV1溢出中断标志,发生于MAX(0xFFFF)时   1采用内部计数时钟用于 ICP捕捉输入场合——-测量脉宽/红外解码(捕捉输入功能可以工作在多种模式下,而不单单只是普通模式)   2 采用外部计数脉冲输入用于计数,测频其他的应用,采用其他模式更为方便,不需要像51般费神   二 CTC模式 [比较匹配时清零定时器模式] WGM1=4,12跟51的自动重载模式差不多   1 用于输出50%占空比的方波信号   2 用于产生准确的连续定时信号WGM1=4时, 最大值由OCR1A设定,TOP时产生OCF1A比较匹配中断标志WGM1=12时,最
[单片机]
AVR软USB接口在数据采集系统中应用
  在设计AVR软USB接口固件(ATmega8单片机程序)时,USB接口参数配置按USB-isp(同样是AVR软USB虚拟RS232接口)下载线设置;并在PC机系统中安装其虚拟串口驱动程序。能支持PC机WIN7和XP等操作系统。   1.引言   在电力生产和电气测试工作中经常需要用便携式PC机通过接口采集和处理数据。   常用的带RS232串口的数据采集器,不允许带电(热)拔插,使用很不方便。而且现在大部分的PC机不带RS232接口,尤其是便携式机。取而代之的是USB接口。目前AVR单片机USB软接口技术应用的很普遍,最旱是ATMEL公司在《AVR309 Software UniversalSerial Bus》一文中,
[单片机]
<font color='red'>AVR</font>软USB接口在数据采集<font color='red'>系统</font>中应用
学习AVR(七)通用寄存器堆
通用寄存器堆(General Purpose Register File) 优化的寄存器堆用于AVR加强型RISC指令组。为了实现要求的性能和灵活性,寄存器堆支持如下的输入/输出方案: 一个8位输出操作数和一个8位结果输入 两个8位输出操作数和一个8位结果输入 两个8位输出操作数和一个16位结果输入 一个16位输出操作数和一个16位结果输入 下图所示为AVR CPU中通用工作寄存器的结构。 寄存器堆中大部分的指令运算都可以直接访问所有寄存器,而且大多数指令都是单周期指令。
[单片机]
学习<font color='red'>AVR</font>(七)通用寄存器堆
AVR单片机为核心的全自动太阳能工程热水器控制器设计
引 言 随着人们生活水平的提高, 各种热水器的使用已相当普及, 与之相配套的控制仪也相继问世。然而, 目前市场上的各种热水器控制电路还与理想要求相差甚远。消费者需要真正的全自动 控制, 以实现使用的最简单化, 就像家用电视机、电冰箱一样, 接通电源、设定完毕就不用再操心了。鉴于国内太阳能热水器市场不断扩大, 而与其相配套的控制器却急需改进的情况, 研制了这套太阳能热水器控制器。本文设计的太阳能热水器是以AVR Meg a 32 单片机为检测控制核心,不仅实现了温度、水位两种参数的实时显示功能, 而且具有温度设定与控制功能。控制器可以根据天气情况利用辅助加热装置使蓄水箱内的水温达到预先设定的温度, 从而达到24 小时供应热水的目的。
[单片机]
以<font color='red'>AVR</font>单片机为核心的全自动太阳能工程热水器控制器设计
BASCOM-AVR 驱动数码管简洁代码
'''''''''''''''''''''' BASCOM-AVR 驱动一个数码管显示数字 0-9 下载附件查看原理图 代码 实物照片 ''''''''''''''''''''''''''''''''
[单片机]
BASCOM-<font color='red'>AVR</font> <font color='red'>驱动</font>数码管简洁代码
用于LCD测试系统的程控驱动器设计
  引言   液晶显示器是一种电压型非主动发光显示器,典型液晶显示器利用液晶材料的介电常数各向异性和折射率各向异性的物理特性,通过改变加在液晶盒上的电压来改变液晶分子的排列方式,从而改变液晶盒的透光率这一原理来实现对光的控制,通过反射(无背光型)或透射(有背光型)光来实现显示。液晶盒透过不同的强度和不同颜色的光,然后再使用空间混色法,就可以实现全彩色显示。   试验室用于LCD的测试系统就是在液晶盒中注入不同的液晶材料,用电极引线做成笔段式或矩阵型的LCD,然后在电极上加上所要求的驱动脉冲,使被选行与被选列交叉位置上的液晶像素或笔段在电场作用下呈现显示状态(遮光或透光),以此测试LCD的性能,所需的各种驱动脉冲由驱动电源提供。
[测试测量]
用于LCD测试<font color='red'>系统</font>的程控<font color='red'>驱动</font>器设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved