电动车控制器C语言源代码
- 格式:doc
- 大小:76.50 KB
- 文档页数:44
多变量预测控制(MPC)是一种用于控制多变量系统的算法,它可以根据系统的当前状态和未来的预测来优化系统的性能。
下面是一个简单的MPC控制器的C代码源码示例,用于控制一个简单的多变量系统。
```c#include <stdio.h>#include <stdlib.h>// 系统模型参数double A[3][3] = { {1, 1, 0}, {0, 1, 1}, {0, 0, 1} };double B[3][1] = { {0}, {0}, {0} };double C[1][1] = { {1} };double D[1][1] = { {0} };// MPC控制器参数double K[3] = {0}; // 控制增益double q_min = -1; // 参考输入下限double q_max = 1; // 参考输入上限double q_ref = 0; // 参考输入double q_next_ref = 0; // 下一步参考输入double dt = 0.02; // 时间步长double control_timeout = 5; // 控制周期// MPC控制器状态变量double state[3] = {0};// MPC控制器算法函数void mpc_control(double q) {// MPC算法实现过程...// 这里省略具体算法实现过程...}int main() {// 设置系统模型参数// 设置MPC控制器参数和状态变量...for (int i = 0; i < control_timeout; i++) {// 系统当前状态double x[3] = {state[0], state[1], state[2]};// 系统参考输入double u = q_ref;// 系统当前输出double y[1] = {0};y[0] = C[0][0]*x[0] + C[0][1]*x[1] + C[0][2]*x[2];// 根据当前状态和参考输入计算MPC控制器的下一步参考输入和目标值...q_next_ref = mpc_control(q); // 控制器的输出是一个新的参考输入q_next_ref和目标值T(x, u)(通过系统模型转换为输入和状态约束的等式)// 根据目标值和约束条件更新参考输入和状态变量...q_ref = q_next_ref; // 更新当前参考输入为下一步参考输入q_next_refstate[0] += A[0][0]*dt + K[0]; // 根据状态方程更新状态变量x[0]state[1] += A[1][1]*dt + K[1]; // 根据状态方程更新状态变量x[1]state[2] += A[2][2]*dt + K[2]; // 根据状态方程更新状态变量x[2]}return 0;}```以上代码是一个简单的MPC控制器的C代码源码示例,它可以根据系统的当前状态和未来的预测来优化系统的性能。
C 语言实现单片机控制步进电机加减速源程序1. 引言在现代工业控制系统中,步进电机作为一种常见的执行元件,广泛应用于各种自动化设备中。
而作为一种常见的嵌入式软件开发语言,C 语言在单片机控制步进电机的加减速过程中具有重要的作用。
本文将从单片机控制步进电机的加减速原理入手,结合 C 语言的编程技巧,介绍如何实现单片机控制步进电机的加减速源程序。
2. 单片机控制步进电机的加减速原理步进电机是一种能够精确控制角度的电机,它通过控制每个步骤的脉冲数来实现旋转。
在单片机控制步进电机的加减速过程中,需要考虑步进电机的加速阶段、匀速阶段和减速阶段。
在加速阶段,需要逐渐增加脉冲的频率,使步进电机的转速逐渐增加;在匀速阶段,需要保持恒定的脉冲频率,使步进电机以匀速旋转;在减速阶段,需要逐渐减小脉冲的频率,使步进电机的转速逐渐减小。
这一过程需要通过单片机的定时器和输出控制来实现。
3. C 语言实现步进电机加减速的源程序在 C 语言中,可以通过操作单片机的 GPIO 来控制步进电机的旋转。
在编写源程序时,需要使用单片机的定时器模块来生成脉冲信号,以控制步进电机的旋转角度和速度。
以下是一个简单的 C 语言源程序,用于实现步进电机的加减速控制:```c#include <reg52.h>void main() {// 初始化定时器// 设置脉冲频率,控制步进电机的加减速过程// 控制步进电机的方向// 控制步进电机的启停}```4. 总结与回顾通过本文的介绍,我们了解了单片机控制步进电机的加减速原理和 C 语言实现步进电机加减速源程序的基本思路。
掌握这些知识之后,我们可以更灵活地应用在实际的嵌入式系统开发中。
在实际项目中,我们还可以根据具体的步进电机型号和控制要求,进一步优化 C 语言源程序,实现更加精准和稳定的步进电机控制。
希望本文能为读者在单片机控制步进电机方面的学习和应用提供一定的帮助。
5. 个人观点与理解在我看来,掌握 C 语言实现单片机控制步进电机加减速源程序的技术是非常重要的。
无刷直流电机调速--C语言源程序附录1. C语言源程序:#include"stdio.h"#include"myapp.h"#include"ICETEK-VC5502-EDU.h"#include"scancode.h"#include"lcd.h"#define CTRSTATUS (*(unsigned int * )0x608000) //port8000 #define CTRLED (*(unsigned int * )0x608004) //port8004#define MCTRKEY (*(unsigned int * )0x608005) //port8005 #define CTRCLKEY (*(unsigned int * )0x608006) //port8006 #define CTRMOTORBSPEED (*(unsigned int * )0x608003)void InitMcBSP();void INTR_init( void );void InitForMotorB( void );void showparameters();void LCDPutString(unsigned int * pData,int x,int y,unsigned int nCharNumber,unsigned color);void PIDControl(int rk,int yk);void PrintParameters();//定时器分频参数#define T100 99 // 100个时钟周期中断一次#define T2Hz 20000 // 20000个时钟周期读取速度一次//工作变量usigned int uWork,uN,nCount,nCount1,nCount2,nCount3,nCount4;int nSSS,nJSSpeed,pwm1;int md,wc;unsigned int nScreenBuffer[30*128];float a=0.6f,b=0.2f,c=0.1f,duk;int ek,ek1,ek2,tz;int nInput;unsigned int *www=(unsigned int *)0x608003;Int m_nSpeed,m_bPCSet;// 主函数main(){unsigned char ccc;int speed[100],sp,lj;float ljh;int i,w1,w2,w3;unsigned int uWork1;unsigned int bWork1,*pWork;int breakflage;// 初始化工作变量for ( sp=0;sp<100;sp++ )speed[sp]=0;for ( sp=0;sp<1024;sp++ ) nScreenBuffer[sp]=0;sp=nSSS=nCount=nCount1=nCount2=nCount3=nCount4= nJSSpeed=0;nInput=tz=wc =0;ek=ek1=ek2=0;uN=40;md=70;pwm1=60;m_nSpeed=70;m_bPCSet=0;inputspeed=0;uWork1=0;breakflage=0;initemif();CLK_init();*(int*)0x400001=1;CREG=1; //使能外部总线接口InitCTR();CTRGR=0x80;CTRGR=0;CTRGR=0x80;LCDTurnoff();// 设置显示参数和内容LCDSetDelay(1); //设置延时等待参数LCDSetScreenBuffer(nScreenBuffer); // 显示缓冲区for (bWork=0,pWork=nScreenBuffer;bWork<30*128;bWork++,pWork++) (*pWork=0)LCDTurnOn();//打开显示LCDCLS();//清除显示内存LCDPutCString(str1,0,127,8,0);LCDPutCString(str2,0,111,2,1);LCDPutCString(str3,68,111,2,1);LCDPutCString(str4,68,79,2,1);LCDPutCString(str5,68,95,2,1);LCDPutCString(str6,0,95,2,1);LCDPutCString(str7,0,79,3,1);ShowParamctors();//参数显示InitMcBSP();INTR-init();InitForMotorB();While(!breakflage){if(nCount==0) //读取键盘标志{uWork=MCTRKEY;CTRCLKEY=0;Switch(uWork1){Casc 128;if(inputspecd!=0){Md=inputspecd;Inputspecd=0;LCDPutCString(numbers+104,104,79,1,1); LCDPutCString(numbers+104,112,79,1,1); LCDPutCString(numbers+104,120,79,1,1); LCDRefreshScreen();}break;case 64;breakflage=1;case 1;inputspeed=inputspeed+1break;case 2;inputspeed=inputspeed-1;break;case 4;inputspeed=inputspeed+10;break;case 8;inputspeed=inputspeed-10;break;}if(inputspeed>90){inputspeed=90;}if(inputspeed<0){inputspeed=0;}w1=inputspeed%1000/100;w2=inputspeed%100/10;w3=in putspeed%10; LCDPutString(numbers+w1*8,104,79,1,1);LCDPutString(numbers+w2*8,112,79,1,1);LCDPutString(numbers+w3*8,120,79,1,1);LCDRefreshScreen();}if(m-bPCSet){m-bPCSst=0;if (m-nSpeed>=0&&m-nSpeed<256){md=m-nSpeed;LCDPutCString(numbers+104,104,79,1,1); LCDPutCString(numbers+104,112,79,1,1);LCDPutCString(numbers+104,120,79,1,1); LCDRefreshScreen();printparameters();}}if(nJSSpeed==0) //读取速度标志{LED=1;nJSSpeed=0;ccc=CTRMOTORBSPEED; //读取端口速度计数ccc=ccc&0xff;nSSS=ccc;if(nSSS>=0 && nSSS<400) //合法性检测{speed(sp)=Nssssp++;sp%=33;}if(sp==0) //读取实际速度{lj=0;ljh=0;for(i=0;i<33;i++){if(speed(i)>=0&&speed(i)<400){ljh+=speed(i);lj++;}}nCount3++;nCount3%=3;if(nCount3==2){PIDControl(md,wc); //调用PID算法控制程序uN=100-pwml; //利用占空比调整控制Showparameters(); //显示各参数到LCD }CloseCTR();exit(0);}//PID算法控制子程序void PIDControl(int rk,int yk){ek=rk-yk;duk=a*ek+b*ek1+c*ek2; //计算控制输出ek2=ek1; ek1=ek;tz=(int)duk;pwm1+=tz; //计算当前占空比if(pwml<0) pwml=0;else if(pwml>99) pwml=99;}void interrupt Timer(){uWork=PCR1; //pwml输出if(nCont1>u N){uWork=4; //根据占空比设置FSR状态}else{uWork&=0x0fffb;}PCR1=uWork;//设置中断控制寄存器void INTR-init(void){asm(“BSET INTM”);IVPD=0x01;IVPH=0x01;IERO=0x10;DBIERO=0x10;IFRO=0xffff;asm(“BCLR INTM”);}void InitForMotorB(void)ioport unsigned int *GPTCTL1-0;ioport unsigned int *GPTPRD1-0;ioport unsigned int *GPTGCTL1-0;*GPTCTL1-0=0;*GPTPRD1-0=0x1d8;*GPTGCTL1-0=0x3;}//显示参数到LCDvoid ShowParameters(){int w1,w2,w3;w1=md%1000/100;w2=md%100/10,w3=md%10; LCDPutString(numbers+w1*8,36,111,1,1); LCDPutString(numbers+w2*8,44,111,1,1); LCDPutString(numbers+w3*8,52,111,1,1);if (ek>=0){LCDPutString(numbers+88,36,95,1,1);w3=((int)ek)%100;}else{LCDPutString(numbers+96,36,95,1,1);w3=((int)(-ek))%100;}for (j=0;j<16;j++,k<<=1){if (color==2) mcolor=2;elsemcolor=(pData(1*8+i)&k)(1):(0);if(color==0) mcolor=1-mcolor;}LCDPutPixel(x+1*8+I,y-j,mcolor);}int wwss;void PrintParameters(){wwcc=wc-md;printf(“测速(%3d) 设置(%3d) 误差(%+4d) PID调整量(%+3d) 占空比(%3d%%)\n”,wc,md,wwcc,tz,pwm1);}。
用单片机控制直流电动机的正反转、加减速的程序如何用C语言写参考一下这个例子吧。
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit PW1=P2^0 ;sbit PW2=P2^1 ; //控制电机的两个输入sbit accelerate=P2^2 ; //调速按键sbit stop=P2^3 ; //停止按键sbit left=P2^4 ; //左转按键sbit right=P2^5 ; //右转按键#define right_turn PW1=0;PW2=1 //顺时针转动#define left_turn PW1=1;PW2=0 //逆向转动#define end_turn PW1=1;PW2=1 //停转uint t0=25000,t1=25000; //初始时占空比为50%uint a=25000; // 设置定时器装载初值 25ms 设定频率为20Hz uchar flag=1; //此标志用于选择不同的装载初值uchar dflag; //左右转标志uchar count; //用来标志速度档位void keyscan(); //键盘扫描void delay(uchar z);void time_init(); //定时器的初始化void adjust_speed(); //通过调整占空比来调整速度//**********************************//void main(){time_init(); //定时器的初始化while(1){keyscan(); //不断扫描键盘程序,以便及时作出相应的响应}}//*************************************//void timer0() interrupt 1 using 0{if(flag){flag=0;end_turn;a=t0; //t0的大小决定着低电平延续时间TH0=(65536-a)/256;TL0=(65536-a)%256; //重装载初值}else{flag=1; //这个标志起到交替输出高低电平的作用if(dflag==0){right_turn; //右转}else{left_turn; //左转}a=t1; //t1的大小决定着高电平延续时间TH0=(65536-a)/256;TL0=(65536-a)%256; //重装载初值}}void time_init(){TMOD=0x01; //工作方式寄存器软件起动定时器定时器功能方式1 定时器0TH0=(65536-a)/256;TL0=(65536-a)%256; //装载初值ET0=1; //开启定时器中断使能EA=1; // 开启总中断TR0=0;}//****************************************//void delay(uchar z) //在12M下延时z毫秒{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}//******************************//void keyscan(){if(stop==0){TR0=0; //关闭定时器0 即可停止转动 end_turn;}if(left==0){TR0=1;dflag=1; //转向标志置位则左转}if(right==0){TR0=1;dflag=0; //转向标志复位则右转}if(accelerate==0){delay(5) ; //延时消抖if(accelerate==0){while(accelerate==0) ; //等待松手count++;if(count==1){t0=20000;t1=30000; //占空比为百分之60}if(count==2){t0=15000;t1=35000; //占空比为百分之70}if(count==3){t0=10000;t1=40000; //占空比为百分之80}if(count==4){t0=5000;t1=45000; //占空比为百分之90}if(count==5){count=0;}}}}功能特点:1)总线速度高达40 M Hz,CAN总线:3个1Mbps的CAN总线,兼容CAN2.0 A/B;2)128 KB程序Flash和8 KB DataFlash,用于实现程序和数据存储,均带有错误校正码(E CC);3)可配置A/D:16通道模数转换器;可选8位10位和12位精度,3μs的转换时间4)内嵌MS CAN模块用于CAN节点应用,内嵌支持LIN协议的增强型SIC模块和SPI模块;5)4通道16位计数器,CRG时钟和复位发生器:锁相环、看门狗、实时中断;增强型捕捉定时器;6)出色的低功耗特性,带有中断唤醒功能的10,实现唤醒休眠系统的功能;7)通道PWM:8位8通道或16位4通道PWM,易于实现电机控制。
附录D -无刷直流电动机代码//------------------------------------------------------------------- //例子4//无刷直流电机控制//------------------------------------------------------------------- //版权所有2004 Silicon Laboratories公司////认证:KAB//日期:2004.05.24////这一程序规定,无刷直流电动机控制使用PCA为8位PWM模式。
一个单一的PCA模块生成//一个8位PWM 。
引脚跳过xbr0使PWM之间的三个输出p1.0,p1.1&p1.2多元化。
这三//个输出用于驱动下晶体管3相桥的配置。
p0.4p0.5&p0.6用来驱动上晶体管。
////ADC用来读取电位器p0.6上的电压。
ADC使用查询模式和64样品平均。
////p0.0,p0.1,p0.2用于霍尔效应传感器输入。
这个引脚用于确定转子位置。
The//readHalls() function需要三个相同的样本,并返回the hall code。
从//hallpattern发现电机的通讯状况,这种状况然后用于使电机方向转换。
////单步和使用断点只与电机电线断开是安全的。
不要通过代码单步与电机电线连接。
PWM输出//当CPU停止工作时仍然存在。
尤其不要单步越过那些产生PWM的电线。
这些电线应该在所//有盒式磁带程序设计系统中用注释标记好////目标: c8051f33x////工具链:KEIL Eval ‘c’//-----------------------------------------------------------------------------// Includes//-----------------------------------------------------------------------------#include <c8051f330.h> // SFR声明//-----------------------------------------------------------------------------// MACROS//-----------------------------------------------------------------------------#define GSAMP 3//-----------------------------------------------------------------------------// Hall-effect and commutation patterns霍尔效应和整流模式//-----------------------------------------------------------------------------const unsigned char code hallPattern[7]={ 0x00, 0x01, 0x03, 0x02, 0x06, 0x04, 0x05};const unsigned char code skipPattern[7]={~0x01,~0x01,~0x01,~0x02,~0x02,~0x04,~0x04};const unsigned char code P1Pattern[7]={~0x00,~0x20,~0x40,~0x40,~0x10,~0x10,~0x20};//-----------------------------------------------------------------------------// Function PROTOTYPES函数原型//-----------------------------------------------------------------------------void SYSCLK_Init (void);void PORT_Init (void);void PCA0_Init (void);void PCA0_ISR (void);void ADC_Init (void);unsigned char readVin(void);unsigned char avgVin(void);unsigned char readHalls(void);unsigned char hallPosition(void);void commutate(unsigned char);void coast(void);//-----------------------------------------------------------------------------// MAIN Routine主要例行//-----------------------------------------------------------------------------void main (void) {unsigned char h,p;bit start;PCA0MD &= ~0x40; // Disable Watchdog Timer禁用看门狗定时器SYSCLK_Init (); // initialize system clock初始化系统时钟PORT_Init (); // initialize i/o初始化输入/输出PCA0_Init (); // configure PCA0 to 8-bit PWM配置pca0至8位PWMADC_Init(); // initialize i/o初始化输入/输出EA = 1; // enable global interrupts使全球中断p = 0; // clear p清晰pstart = 1; // set start bit设定起始位while (1){h = hallPosition(); // h=霍尔位置if(h) //如果好的位置{if ((h != p)||(start)) //如果新的位置或启动{p = h; //更新p// DO NOT SINGLE-STEP PAST THE NEXT 不要单步过去THE NEXT// LINE WITH MOTOR WIRES CONNECTED 线路与电机电线连接commutate(p); // commutate motor, enables PWM commutate电机,使脉宽调制start = 0;}PCA0CPH0 = avgVin(); // get avg reading and output to PWM获得平均阅读和输出的PWM }else{ coast(); // coast until good reading coast直至良好的阅读start = 1; // set start bit to restart motor设定起始位,以重新启动马达}}}//-----------------------------------------------------------------------------// SYSCLK_Init//-----------------------------------------------------------------------------void SYSCLK_Init (void){OSCICN = 0x83; // configure for 24.5 MHz配置为24.5兆赫}//-----------------------------------------------------------------------------// PORT_Init//-----------------------------------------------------------------------------//// Configure the Crossbar and GPIO ports.配置了横梁和GPIO端口// P0.0 - HA// P0.1 - HB// P0.2 - HC// P0.3 -// P0.4 -// P0.5 -// P0.6 -// P0.7 - Vin - analog input//// P1.0 - Abottom - push-pull output// P1.1 - Bbot - push-pull output// P1.2 - Cbot - push-pull output// P1.3 -// P1.4 - Atop - push-pull output// P1.5 - Btop - push-pull output// P1.6 - Ctop - push-pull output// P1.7 -//void PORT_Init (void){XBR0 = 0x00; // enable nothing on XBR0 使XBR0=0XBR1 = 0x01; // enable PCA CEX0P0SKIP = 0xFF; // skip all pins on P0跳过P0所有管脚P0MDIN =~0x80; // P0.7 analog input p0.7模拟输入P1SKIP =~0x01; // skip all except P1.0除p1.0其余跳过P1MDOUT = 0x77; // enable P1 outputsXBR1 |= 0x40; // enable crossbarP1 = 0xff; // P1 all high}//-----------------------------------------------------------------------------// PCA0_Init//-----------------------------------------------------------------------------void PCA0_Init (void){PCA0MD = 0x02; // PCA uses sysclk/4, no CF intPCA0CPM0 = 0x00; // clear mode, pin highPCA0L = 0x00; // reset the timer重置计时器PCA0H = 0x00;PCA0CPH0 = 0x00; // initial to 0%CR = 1; // START PCA0 timer开始pca0计时器}//-----------------------------------------------------------------------------// coast function//-----------------------------------------------------------------------------void coast(void){PCA0CPM0 = 0x00; // disable PWM禁用PWMP1 = 0xff; // disable upper transistors禁用上晶体管}//-----------------------------------------------------------------------------// readHalls function//-----------------------------------------------------------------------------// reads and debounces Hall-Sensor inputs读取并debounces霍尔传感器输入unsigned char readHalls(void){unsigned char g,h,i;g = 0;h = 0;while (g<GSAMP) // while less that 3 good samples{i = P0 & 0x07; // read hallsif (h == i) // if the sameg++; // one more goodelseg = 0; // else start overh = i; // update h}return h; // return good hall code}//-----------------------------------------------------------------------------// hallPosition function//----------------------------------------------------------------------------- unsigned char hallPosition (void){unsigned char h,p;h = readHalls(); // get debounced hall reading// find corresponding pattern index寻找相应的模式指数for (p=6;(h != hallPattern[p])&&(p!=0);p--);return p;}//-----------------------------------------------------------------------------// hallPosition function//-----------------------------------------------------------------------------void commutate (unsigned char i){ PCA0CPM0 = 0x00; // disable PWMP1 = 0xFF;XBR1 &= ~0x40; // disable crossbarP1SKIP = skipPattern[i];P1 = P1Pattern[i];XBR1 |= 0x40; // enable crossbar// DO NOT SINGLE-STEP PAST THE NEXT// LINE WITH MOTOR WIRES CONNECTEDPCA0CPM0 = 0x42; // enable 8-bit PWM mode}//-----------------------------------------------------------------------------// ADC functions//-----------------------------------------------------------------------------void ADC_Init(void){AMX0P = 0x07; // positive input P0.7AMX0N = 0x11; // single ended mode单端模式ADC0CF = 0xC4; // 1MHz clock, left justified 1MHz的时钟,左有道理ADC0CN = 0x80; // configure ADC for polled mode配置ADC为调查模式REF0CN = 0x08; // use Vdd as ADC full scale}unsigned char readVin(void){AD0INT = 0; // clear ADC0 end-of-conversionAD0BUSY = 1; // initiate conversion启动转换while (!AD0INT); // wait for conversion to complete等待转换完成return ADC0H;}unsigned char avgVin(void){unsigned char i, result;unsigned int sum;sum = 0;for (i = 64; i != 0; i--) // repeat 64 times重复64次{sum += readVin(); // read ADC and add to sum读取ADC和与sum相加}result = (unsigned char)(sum>>6); // divide by 64 and cast to uchar除以64并设为uchar数据return result; // return average reading回到average reading}。
第14章单片机控制的电动自行车驱动系统14.4.4 C语言程序#include <pic.h>//电动车双闭环程序,采用双闭环方式控制电机,以得到最好的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 Vvolatile 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; //关断所有MOSFETTRISC=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设置为特殊方式,以触发ADADCON0=0X81; //AD时钟为32分频,且AD使能,选择AN0通道采集手//柄电压TMR2=0X00; //TMR2寄存器初始化TMR1H=0X00; //TMR1寄存器初始化TMR1L=0X00;T1CON=0X00; //TMR1为1分频CCPR2H=0X08;CCPR2L=0X00; //电流采样周期设置为T AD=512 μsPR2=0XC7; //PWM频率设置为5 kHzADCON1=0X02; //AD结果左移OPTION=0XFB; //INT上升沿触发TMR2ON=1; //PWM开始工作INTCON=0XD8; //中断设置GIE=1,PEIE=1,RBIE=1ADIE=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 1void DELAY1(x)char x;{DELAYH=x; //延时参数设置#asmDELAY2 MOVLW 0X06MOVWF _DELAYLDELAY1 DECFSZ _DELAYLGOTO DELAY1DECFSZ _DELAYHGOTO 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置1spe=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; //输出电压0TMR1ON=0; //关CCP2,不再触发ADfor(;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<VOLOFF) { //电池电压小于3*k(V)时保护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<VOLON); //电池电压小于35 V时继续保护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 1void interrupt INTS(void){if(RBIF==1) {RBIF=0;sample();}else if(ADIF==1) AD();else if(INTF==1) {shutdown=1;INTF=0;} //刹车中断来,置刹车标志}。
51单片机控制的步进电机C语言程序用的是L298驱动的和ULN2003一样,你把它换成2003就行拉#include <AT89X51.H>unsigned char codetable[]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9,0x00,0xf1,0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0x f3,0x00};unsigned char temp,temp_old;unsigned char key;unsigned char i,j,k,m,s;void delay(int i){for(m=i;m>0;m--)for(j=250;j>0;j--)for(k=10;k>0;k--);}void saomiao(){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0e:key=1;break;case 0x0d:key=2;break;case 0x0b:key=3;break;case 0x07:key=4;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}}void main(void){while(1){saomiao();if(key==1){ P1=0;P2=0;saomiao();}if(key==2){temp_old=key;for(s=0;s<8;s++){ P2=table[s];P1_4=0;delay(13);saomiao();if(key!=temp_old){P1_4=1;break;}}}if(key==3){temp_old=key;for(s=0;s<8;s++){ P2=table[s];P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==4){temp_old=key; for(s=0;s<8;s++){ P2=table[s];P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}if(key==5){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_7=0;delay(13);saomiao();if(key!=temp_old){P1_7=1;break;}}}if(key==6){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==7){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}}}C语言程序源代码#include <REGX51.H> // 51寄存器定义#include "intrins.h"#define control P1 //P1_0:A相,P1_1:B相,P1_2:C相,P1_3:D相#define discode P0 //显示代码控制端口#define uchar unsigned char //定义无符号型变量#define uint unsigned intsbit en_dm=P3^0; //显示代码锁存控制sbit en_wk=P3^1; //位控锁存控制uchar code corotation[4]= {0x03,0x06,0x0c,0x09};//电机正转uchar code rollback[4]={0x0c,0x06,0x03,0x09}; //电机反转uchar code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示字段uint code Levspeed[5]={500,400,300,200,100};//电机速度等级uchar Hscan,speedcount;//Hscan行扫描,speedcount 速度等级计数uint uu; //频率计数uint step,setstep; //step:电机步伐计数,setstep:手动设置电机步伐uint speed=500; //电机初始速度uchar count;uchar flag[5];uchar butcount; //按键次数//****************************************//flag[0] 正转标志//flag[1] 反转标志//flag[2] 加速标志//flag[3] 减速标志//flag[4] 设置标志//****************************************Delay1mS(unsigned int tt) //延时1ms “Delay1mS”延时子程序,用循环语句延时。
#define _E_BIKE_W79E83X_C_#include intrins.h#include E_BIKE_W79E83X.H#includeW79E834.h/*************************************************************************** *** 主函数**************************************************************************** **/void main(void){Init(); // 初始化Init_IO(); // 初始化端口H_Sample(); // 霍尔信号采样Phase_Change(); // 相位变换AutoHelpEN(1,0x1AA,200);/*第一个参数设定助力功能允许与否,1为允许,0为禁止第二个参数设定助力力量(PWM占空比),数值范围:0~0x355,数值越大,力量越大第三个参数设定助力时间,数值越大,时间越长*/Keep_SpeedEN(1,0x20,6);/*第一个参数设定定速巡航功能允许与否,1为允许,0为禁止第二个参数设定定速巡航最低速设置第三个参数设定在巡航点保持多长时间后才进入巡航*/Current_Lim(0xB48);/*过流保护上限值设定0xB00对应限电流最大大约为2.6A0xB80对应限流值最大大约为3.8A*/LowVoltage_Lim(0x9B0);/*欠压保护下限值设定电池电压为47.9V时ADC采样值为0xB6 ==> 0xB60推算电池电压为41V时的采样值为0x9B ==> 0x9B0推算电池电压为40V时的采样值为0x98 ==> 0x980*/EABS_Set(1,1);/*第一个参数为滑行充电功能使能,1为允许,0为禁止第二个参数为电刹车功能使能,1为允许,0为禁止*/Speed_LimHW(0,0,0,1);/*硬件控制最大速度参数只能有一个为1。
PIV10F200的简单C语言程序PIC10F200是Microchip 的一款8 位微控制器,通常用于简单的控制任务。
由于PIC10F200是一款非常基本的微控制器,它不支持浮点数运算,也没有复杂的指令集。
通常,为PIC10F200编写的程序会涉及基本的I/O 操作、定时器和简单的算术运算。
下面是一个简单的C 语言程序,用于PIC10F200微控制器,这个程序会循环点亮和熄灭一个连接到某个GPIO 引脚(例如RP0)的LED 灯。
c复制代码#include <xc.h>#define _XTAL_FREQ 4000000 // 定义晶振频率,这里假设是4 MHzvoid main(void) {// 配置RP0 引脚为输出TRISCbits.TRISC0 = 0; // 设置RP0 为输出while (1) { // 无限循环TC0 = 1; // 点亮LED__delay_ms(500); // 等待500 毫秒TC0 = 0; // 熄灭LED__delay_ms(500); // 等待500 毫秒}}注意:1.你需要使用Microchip 的MPLAB X IDE 和XC8 编译器来编译这个程序。
2.这个程序假设你已经正确配置了你的开发环境,并且选择了正确的微控制器型号(PIC10F200)。
3.__delay_ms函数是MPLAB XC8 编译器提供的,用于生成基于晶振频率的延迟。
你需要根据你的实际晶振频率来调整延迟时间。
4.你还需要配置你的微控制器来匹配你的硬件设置,例如GPIO引脚分配等。
最后,请确保在连接硬件和测试程序之前,你已经仔细检查了所有的连接和配置,以防止任何可能的损坏或短路。
电动车控制器stm32源码1. 介绍电动车控制器是电动车的核心部件之一,负责控制电动机的启停、转速、扭矩等参数,实现对电动车的驱动控制。
本文将介绍电动车控制器的stm32源码开发。
2. STM32开发环境搭建2.1 安装Keil MDKKeil MDK是一款常用的嵌入式开发工具,支持多种芯片平台,包括STM32系列。
通过Keil MDK,我们可以方便地进行stm32源码的开发和调试。
2.2 编写stm32源码在Keil MDK中,我们可以使用C语言编写stm32的源码。
源码主要包括以下几个部分:2.2.1 引入头文件在源码的开头,我们需要引入一些头文件,以便使用相关的函数和宏定义。
例如:#include "stm32f10x.h"#include "stm32f10x_gpio.h"#include "stm32f10x_rcc.h"2.2.2 定义全局变量在源码中,我们可以定义一些全局变量,用于保存各种状态和参数。
例如:uint8_t speed = 0; // 电动车的速度uint8_t torque = 0; // 电动车的扭矩2.2.3 初始化函数在源码中,我们需要编写初始化函数,用于初始化STM32的各个模块和外设。
例如:void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);}2.2.4 主函数在源码中,我们需要编写主函数,用于实现电动车控制器的逻辑功能。
电动车控制器原理及编程一、电动车控制器的原理:1.信号采集与处理:电动车控制器通过传感器采集车速、踏板力度、刹车信号等信号,并通过微处理器对这些信号进行处理。
其中,车速传感器一般使用霍尔传感器或光电传感器,可以实时检测电动车的速度;踏板传感器可以感知骑行者的踩踏力度,通过不同力度的踩踏来控制车辆的加速和减速;刹车信号传感器用于实现刹车功能,及时停止电动车的运动。
控制器通过处理这些信号来实现对电机的控制。
2.电流控制:电动车控制器使用PWM(脉宽调制)技术来控制电机的电流。
通过改变PWM信号的占空比和频率来改变电机的电流大小,从而实现对车辆速度和加速度的控制。
PWM控制可以根据不同的需求和骑行状态进行调整,以达到最佳的动力输出和能耗。
3.速度反馈:电动车控制器还需要接收速度反馈信号来调整电机的电流输出。
通过安装速度传感器来实时检测电机转速,与期望速度进行比较,并通过控制电流大小来调整电机的转速。
速度反馈可以提高电动车的稳定性和安全性,避免过速或过慢的情况发生。
二、电动车控制器的编程:1.算法设计:编程前需要设计合适的算法来实现不同功能的控制。
例如,加速时可以根据踏板传感器的信号输出相应的电流大小,并通过PWM调节占空比和频率来控制电机转速;减速时可以减小电流输出,或者通过反向PWM控制来制动电机;刹车时可以通过控制电机的短路来实现紧急制动等。
算法的设计需要根据具体的电机和控制器参数进行调整,以达到最佳的控制效果。
2.编程实现:根据算法设计,将代码编写到微处理器中。
编程语言可以是汇编语言、C语言等。
在编程实现过程中,需要使用特定的编程工具和开发环境,对不同的微处理器和控制器进行适配和调试。
3.调试和优化:编程完成后,需要进行调试和优化,以确保控制器的运行稳定和性能优良。
通过不断调整代码和参数,找出潜在的问题,并进行优化改进。
调试和优化过程需要反复实地测试,对控制器的各种功能进行验证和调整。
总之,电动车控制器的原理和编程是电动车系统中的关键环节。
MPC控制器C代码模型预测控制(MPC)是一种先进的控制策略,它使用数学模型预测系统的未来行为,并优化控制输入以实现特定的目标。
在编写MPC控制器的C代码时,通常需要以下几个步骤:1.定义系统模型:根据实际系统的动态特性,使用数学模型描述系统的行为。
在C语言中,可以使用结构体或类来定义系统的状态、输入和输出等变量。
2.定义MPC控制器:根据系统模型和目标,编写MPC控制器的算法。
在C语言中,可以使用循环结构和条件语句来实现控制算法。
3.计算优化问题:MPC控制器需要解决一个优化问题,以确定最优的控制输入。
在C语言中,可以使用数值优化算法(如梯度下降法、牛顿法等)来求解优化问题。
4.实现控制输入:根据计算出的最优控制输入,实现控制系统的实际输入。
在C语言中,可以使用函数或指针来实现控制输入的输出。
以下是一个简单的MPC控制器的C代码示例:#include <stdio.h>#include <stdlib.h>#include <math.h>// 定义系统模型typedef struct {double x; // 状态变量double u; // 控制输入double y; // 输出} System;// 定义MPC控制器void MPC_Controller(System* system, double target_y, double* control_input) {// 计算最优控制输入double min_u = system->u - 0.1; // 最大允许输入减小0.1double max_u = system->u + 0.1; // 最大允许输入增加0.1double optimal_u = system->u + (target_y - system->y) / system->x; // 计算最优控制输入control_input[0] = fmin(fmax(optimal_u, min_u), max_u); // 取最优控制输入的上下界之间的值}int main() {// 初始化系统模型和控制输入System system = {1.0, 0.0, 0.0}; // 系统初始状态为x=1, u=0, y=0double control_input[1] = {0.0}; // 控制输入初始化为0double target_y = 0.5; // 目标输出为0.5// 进行MPC控制for (int i = 0; i < 10; i++) {MPC_Controller(&system, target_y, control_input); // 调用MPC控制器函数,计算最优控制输入并输出到系统模型中system.u = control_input[0]; // 将计算出的最优控制输入赋值给系统模型的控制输入变量system.x = system.x + system.u; // 根据系统模型更新状态变量x的值system.y = system.x * system.u; // 根据系统模型计算输出变量y的值并输出到终端中printf("Time %d: x=%f, u=%f, y=%f", i, system.x, system.u, system.y); // 输出当前时间步长的状态变量x、控制输入u和输出y的值到终端中}return 0;}。
#define _E_BIKE_W79E83X_C_#include "intrins.h"#include "E_BIKE_W79E83X.H"#include"W79E834.h"/******************************************************************** ********** 主函数********************************************************************* *********/void main(void){Init(); // 初始化Init_IO(); // 初始化端口H_Sample(); // 霍尔信号采样Phase_Change(); // 相位变换AutoHelpEN(1,0x1AA,200);/*第一个参数设定助力功能允许与否,1为允许,0为禁止第二个参数设定助力力量(PWM占空比),数值范围:0~0x355,数值越大,力量越大第三个参数设定助力时间,数值越大,时间越长*/Keep_SpeedEN(1,0x20,6);/*第一个参数设定定速巡航功能允许与否,1为允许,0为禁止第二个参数设定定速巡航最低速设置第三个参数设定在巡航点保持多长时间后才进入巡航 */Current_Lim(0xB48);/*过流保护上限值设定0xB00对应限电流最大大约为2.6A0xB80对应限流值最大大约为3.8A*/LowVoltage_Lim(0x9B0);/*欠压保护下限值设定电池电压为47.9V时ADC采样值为0xB6 ==> 0xB60 推算电池电压为41V时的采样值为0x9B ==> 0x9B0推算电池电压为40V时的采样值为0x98 ==> 0x980 */EABS_Set(1,1);/*第一个参数为滑行充电功能使能,1为允许,0为禁止第二个参数为电刹车功能使能,1为允许,0为禁止 */Speed_LimHW(0,0,0,1);/*硬件控制最大速度参数只能有一个为1。
电动车控制器C语言源代码.#define _E_BIKE_W79E83X_C_ #include "intrins.h"#include "E_BIKE_W79E83X.H" #include"W79E834.h"/******************************************************************** ********** 主函数******************************************************************** **********/void main(void){Init(); // 初始化Init_IO(); // 初始化端口H_Sample(); // 霍尔信号采样Phase_Change(); // 相位变换AutoHelpEN(1,0x1AA,200);/*第一个参数设定助力功能允许不否,1为允许,0为禁止第二个参数设定助力力量(PWM占空比),数值围:0~0x355,数值越大,力量越大第三个参数设定助力时间,数值越大,时间越长*/Keep_SpeedEN(1,0x20,6);/*第一个参数设定定速巡航功能允许不否,1为允许,0为禁止第二个参数设定定速巡航最低速设置..第三个参数设定在巡航点保持多长时间后才进入巡航*/Current_Lim(0xB48);/*过流保护上限值设定0xB00对应限电流最大大约为2.6A0xB80对应限流值最大大约为3.8A*/LowVoltage_Lim(0x9B0);/*欠压保护下限值设定电池电压为47.9V时ADC采样值为0xB6 ==> 0xB60 推算电池电压为41V时的采样值为0x9B ==> 0x9B0推算电池电压为40V时的采样值为0x98 ==> 0x980 */EABS_Set(1,1);/*第一个参数为滑行充电功能使能,1为允许,0为禁止第二个参数为电刹车功能使能,1为允许,0为禁止*/Speed_LimHW(0,0,0,1);/*硬件控制最大速度参数只能有一个为1。
第一个参数对应15km/h第二个参数对应20km/h..第三个参数对应30km/h第四个参数对应40km/h*/Speed_LimSW(0x01);/*软件控制最大速度参数数值由0x00~0x20,数值越小速度越大,反之则越小*/while(1){_nop_();//AutoHelpEN(0,0x1AA,100);//Keep_SpeedEN(1,0x20,6);//Current_Lim(0xB50);//LowVoltage_Lim(0x9B0);//EABS_Set(0,0);//Speed_LimHW(0,0,0,1);}}/******************************************************************** *********** I/O端口初始化******************************************************************** **********/void Init_IO(void){//------P0端口设置------//P0M1=0xBE;..P0M2=0x01;/*P0M1.Y P0M2.Y=00 设置I/O端口为普通双向模式P0M1.Y P0M2.Y=01 设置I/O端口为推拉模式P0M1.Y P0M2.Y=10 设置I/O端口为输入,高阻,模式P0M1.Y P0M2.Y=11 设置I/O端口为开漏模式*///P0ID=0x78; // 设置四个AD端口0数字输入禁止P0=0xFF;//------P1端口设置------//P1M1=0x1C;P1M2=0xC0;P1=0xFF;//------P2端口设置------//P2M1=0x01;P2M2=0x1E;P2=0xFF;}/******************************************************************** *********** 初始化程序******************************************************************** **********/void Init(void){unsigned char i;//------PWM设置------//..// PWMP > PWMn 高电平,反之低电平PWMPH=0X03;PWMPL=0X55;PWM0H=0X00;PWM0L=0X00;PWM1H=0X00;PWM1L=0X00;PWM2H=0X00;PWM2L=0X00;PWMCON1=0XC7; // 打开PWM电路,三个PWM口反相输出PWMCON3=0xF0;//------飞车保护--------//EA=1;/*do {ADCCON=1;ADCCON&=0xef;ADCCON|=0x08;ADC_Ready=0;while(ADC_Ready);}while (ADCH>0x60);*///-----相位检测-------//while(P02==0){H_Sample();Phase_Detect(); ..}//------变量初始化------// for (i=0;i<32;i++) {Current_Buffer[i]=0; }for (i=0;i<20;i++) {Speed_Buffer[i]=0;}for (i=0;i<16;i++) {Voltage_Buffer[i]=0; }Current_P=0;Speed_P=0;Voltage_P=0;;Speed_SUM=0;// PWM_MAX=0; Current_SUM=0; Voltage_SUM=0;H_State=0;Old_State=0;PWM_Duty=0;// PWM_MAX=0;Count_Current=0;Count_Speed=0;Count_Voltage=0; ..Speed_REQ=0;Current_REQ=0;Voltage_REQ=0;ADC_Ready=0;//PWM_Duty=0;PWM_Duty_min=0;//*********************KeepSpeed_Flag = 0;KS_Z1 = 0;KS_Z2 = 0;Motor_Speed = 0x50;//*********************AutoHelp_Flag = 0;Current_Max=0xcffe;Speed_Low=0x0500;//Speed_High=0x1c37;//Speed_MAX=0x1c00; //-----定时器的设置-----//TH0=0x50;TL0=0x50; // 设定定时器的初值TH1=0xE0;TL1=0xE0; // 设定定时器的初值TMOD=0x22; // T0选为定时器,八位,模式2,TL0自动加载TH0中的初值CKCON&=0X00; // 定时器选择为1/12系统时钟ET0=1; // 允许定时器中断TR0=1; // 启动定时器ET1=1;TR1=1;..//-----外部中断设定-----//EX1 = 1; // 允许外部中断1IT1 = 0; // 电平触収中断1AUXR1|=0x04; // 打开ADC电路EADC=1; // 允许ADC中断ADCCON &= 0xE7;// Settings of Timer2 capture modeCKCON=0x60;CAPCON0=0xA8;CAPCON1=0x00;T2MOD=0xF0;IE1 |= 0x80; // enable capture mode interruptRCAP2L = 0x00; //自动重装载低位RCAP2H = 0x00; //自动重装载高位IE1 |= 0x40;//EA=1; // enable interruptT2CON |= 0x04;//enable timer2//***************************//KS_EN = 1;KS_Time = 8;//***************************// }/******************************************************************** **********..* ADC中断处理程序******************************************************************** **********/void ADC_ISR(void) interrupt 11{//UB=~UB;UB=~UB;//EADC=0;ADC_Ready=1;ADCCON &= 0xE7;if(Current_REQ) // 电流采样{Current_REQ=0;if(Current_SUM>Current_Buffer[Current_P]) Current_SUM -= Current_Buffer[Current_P]; Current_Buffer[Current_P]=ADCH;Current_SUM += ADCH;Current_P++;if(Current_P>31)Current_P=0;}if(Speed_REQ) // 转把电压采样{Speed_REQ=0;if(Speed_SUM>Speed_Buffer[Speed_P]) Speed_SUM-=Speed_Buffer[Speed_P]; Speed_Buffer[Speed_P]=ADCH;Speed_SUM+=ADCH;Speed_P++;..if(Speed_P == 14)Speed_P=0;}if(Voltage_REQ) // 电源电压采样{Voltage_REQ=0;if(Voltage_SUM>Voltage_Buffer[Voltage_P])Voltage_SUM -= Voltage_Buffer[Voltage_P];Voltage_Buffer[Voltage_P]=ADCH;Voltage_SUM += ADCH;Voltage_P++;if(Voltage_P>15)Voltage_P=0;}//PWM_ADJ();//UB=~UB;}/******************************************************************** *********** 定时器0中断处理函数******************************************************************** **********/// ========== Interrupt Cycle: 100uS===================void T0M1_ISR(void) interrupt 1{//UB=~UB;//UB=~UB;ADC_Ready=0;Current_REQ=1;..Speed_REQ=0;Voltage_REQ=0;ADCCON=2;Count_Speed++;KS_CNT++;AH_Count++;if(Count_Speed>5)//17{ADCCON=4;Current_REQ=0;Speed_REQ=1;Count_Speed=0;Count_Voltage++;if( Count_Voltage>5)//50{ADCCON=3;Speed_REQ=0;Voltage_REQ=1;Count_Voltage=0;//******** Keep Speed Setting ******// KS_Finish();}}//***Function Set***//if(AH_Count >= 100){AutoHelp(); // 自助力AH_Count = 0;}..if(KS_CNT >= 3000){KS_CNT = 0;Keep_Speed(); // 巡航定速}Volt_Low(); // 欠压保护if(P02==0)Brake_Setting(); // 刹车ADCCON&=0xef;ADCCON|=0x08;EADC=1;PWM_ADJ();}/******************************************************************** *********** 定时器1中断处理函数******************************************************************** **********/void T1M1_ISR(void) interrupt 3 {_nop_();}/******************************************************************** *********** 定时器2捕获模式中断处理函数******************************************************************** **********/void Timer2_ISR() interrupt 13 using 2 ..{//*******Motor Speed*******//Motor_Speed = TH2;TH2 = 0;TL2 = 0;H_Sample(); // 霍尔信号采集Phase_Change(); // 相位变换}/******************************************************************************* 定时器2溢出中断处理函数******************************************************************** **********/void T2_ISR() interrupt 8 {TF2 = 0;Motor_Speed = 0x50;Block_Detect(); // 堵转保护}/******************************************************************** *********** 外部中断处理函数,过流中断******************************************************************** **********/void INT1_ISR() interrupt 2 {CurrentOver_Count++;if(CurrentOver_Count >= 5) // 防抖处理..{PWM_Duty_min = 1;CurrentOver_Count = 0;}}/******************************************************************** *********** 定时器3中断处理函数,采叏捕获模式********************************************************************* *********/void H_Sample(void) {CAPCON1 &= 0xF8;H1=P12;H2=P07;H3=P20;do{State1=H1<<2;State1+=H2<<1;State1+=H3;_nop_();_nop_();State2=H1<<2;State2+=H2<<1;State2+=H3;}while(State1!=State2); // 状态去抖H_State=State1; .. }/******************************************************************** *********** 根据电机霍尔换向信号给出相应控制信号 * 上桥臂:VT,UT,WT* 下桥臂:VB,UB,WB******************************************************************** **********/void Phase_Change(void) {if(EABS_Flag){if(!AutoHelp_Flag){UB = 1;VB = 1;WB = 1;_nop_();UT = 1;VT = 1;WT = 1;}}else if(PWM_Duty_min){UT=0;VT=0;WT=0;UB=1;VB=1;WB=1; // 电机停转}else..{switch(H_State){case 6: // 110,V3,V4VT=0;UT=0;VB=1;WB=1;_nop_();WT=1;UB=0;break;case 2: // ,V4,V5case 7:UT=0;WB=0;VB=1;WB=1;_nop_();VT=1;UB=0;break;case 3: // 011,V5,V6UT=0;WT=0;UB=1;VB=1;_nop_();VT=1;WB=0;break;case 1: // 001,V6,V1WT=0;VT=0;UB=1;VB=1; _nop_();UT=1;WB=0;break;case 5: // 101,V1,V2case 0:WT=0;VT=0;UB=1;WB=1; _nop_();VB=0;UT=1;break;..case 4: // 100,V2,V3UT=0;VT=0;UB=1;WB=1; _nop_();WT=1;VB=0;break;case 9:UT=0;VT=0;WT=0;UB=1;VB=1;WB=1; break;default:break;}}/*if(PWM_Duty_min){UT=0;VT=0;WT=0;UB=1;VB=1;WB=1; // 电机停转}*/}/******************************************************************** *********** 相位检测程序* 上桥臂:VT,UT,WT* 下桥臂:VB,UB,WB******************************************************************** **********/void Phase_Detect(void){WT=0;UT=0;VT=0;switch(H_State)..{case 6: // 110,V3,V4UB=0;VB=1;WB=1;break;case 2: // ,V4,V5case 7:UB=0;VB=1;WB=1;break;case 3: // 011,V5,V6UB=1;VB=1;WB=0;break;case 1: // 001,V6,V1UB=1;VB=1;WB=0;break;case 5: // 101,V1,V2case 0:UB=1;VB=0;WB=1;break;case 4: // 100,V2,V3UB=1;VB=0;WB=1;break;default:break;}}/******************************************************************************* PWM值转换程序* 在限流允许下,将转把电压ADC值转换为PWMn的值 * 电流超过限流值时,做限流处理..******************************************************************** **********/void PWM_ADJ(void){//=====没有超过限流最大值的情冴====//if(Current_SUM < Current_Max){if(Speed_SUM < Speed_Low){ //---没有转把电压,由Speed_Low的值决定转把电压最小值---//if(!KeepSpeed_Flag){if(!AutoHelp_Flag){ // 定速,助力功能下电机正常转动,否则电机停转//PWM_Duty=0;//PWM_Duty_min=1; // 停转标志//PWM_Duty_Max = 0;if(Motor_Speed < 0x010){if(P02==1){if(EABS_SlipEN){EABS_Flag = 1;if(PWM_Duty_Max<0x55)PWM_Duty_Max = 0x055; // 滑行充电}else{PWM_Duty_Max = 0; ..PWM_Duty_min=1; // 停转标志PWM_Duty=0;}}else{PWM_Duty_Max = 0;PWM_Duty_min=1; // 停转标志PWM_Duty=0;}}else{PWM_Duty_Max = 0;PWM_Duty_min=1; // 停转标志PWM_Duty=0;}}}Block_Flag = 0;}else if(P02 == 1){ //---转把电压有效---//PWM_Duty_Max=Speed_SUM-Speed_Low; // 对应转把电压的最大计算值EABS_Flag = 0;if(PWM_Duty_min){if(!Block_Flag){..PWM_Duty_min = 0; // 退出无有效转把电压状冴Phase_Change(); // 相序对应}}/*if(LowNoise_Flag){PWM_Duty_Max += 0x200;}*/if(PWM_Duty_Max>0x06F0)PWM_Duty_Max = 0x06E8; // 最大值限制PWM_Duty_Max=PWM_Duty_Max>>1; // 由转把电压转换为PWMn的值}if(AutoHelp_Flag){PWM_Duty_Max=AH_Duty; // 助力下为PWMn赋值EABS_Flag = 0;}if(KeepSpeed_Flag){PWM_Duty_Max=KS_PWM_Duty; // 定速模式下为PWMn赋值AutoHelp_Flag = 0; // 定速巡航状态时无助力}if(PWM_Duty < PWM_Duty_Max){if(Motor_Speed > SP_Lim)PWM_Duty++; // 转把电压相对应的PWMn值缓慢增加 ..}else{if(PWM_Duty > 3)PWM_Duty--; // 转把电压相对应的PWMn值缓慢减小elsePWM_Duty = 0;}}//======超过限流最大值的情冴======//else{if(PWM_Duty > 0x02){PWM_Duty--; // PWMn值减小}else{PWM_Duty=0;}}PWM_Duty_H = PWM_Duty>>8;PWM_Duty_L = (PWM_Duty & 0x0FF); // 对应PWMn的值,高、低位,if (Power_Off)PWM_Duty_min = 1; // 欠压保护//PWM_Duty_H = 0x01; ..//PWM_Duty_L = 0x20; //测试之用PWM_Setting();}/******************************************************************** *********** 过流保护上限值设定* 0x1600对应限电流最大大约为2.6A* 0x1700对应限流值最大大约为3.8A******************************************************************** **********/void Current_Lim(unsigned int CM) {Current_Max = CM;}/******************************************************************** *********** 欠压保护程序******************************************************************** **********/void Volt_Low(void){if(Voltage_SUM < Voltage_Min){ // 欠压状态Voltage_Count++;if(Voltage_Count > 200)Power_Off=1;}else..{Power_Off=0;Voltage_Count = 0;}}/******************************************************************** *********** 欠压保护下限值设定* 电池电压为47.9V时ADC采样值为0xB6 ==> 0xB60 * 推算电池电压为41V时的采样值为0x9B ==> 0x9B0 * 推算电池电压为40V时的采样值为0x98 ==> 0x980********************************************************************* *********/void LowVoltage_Lim(unsigned int CM) {Voltage_Min = CM;}/******************************************************************** *********** 软件控制最大速度* 分为四个档位1,2,3,4分别对应15km/h,20km/h,30km/h,40km/h********************************************************************* *********/void Speed_LimSW(unsigned char SG) {SP_Lim = SG;}../******************************************************************** *********** 硬件控制最大速度* 分为四个档位SG1,SG2,SG3,SG4分别对应15km/h,20km/h,30km/h,40km/h ******************************************************************** **********/void Speed_LimHW(bit SG1,bit SG2,bit SG3,bit SG4){SP_Lim = 0x01;if(SG4)SP_Lim = 0x01;else if(SG3)SP_Lim = 0x03;else if(SG2)SP_Lim = 0x05;else if(SG1)SP_Lim = 0x08;}/******************************************************************** *********** 堵转保护程序******************************************************************** **********/void Block_Detect(void){if(Current_SUM > Current_Max - 0x80){Block_CNT++;}..elseBlock_CNT = 0;if(Block_CNT >= 20){PWM_Duty_min = 1;Block_Flag = 1;AutoHelp_Flag = 0;KeepSpeed_Flag = 0;UT=0;VT=0;WT=0;UB=1;VB=1;WB=1; // 电机停转}}/******************************************************************** *********** 刹车功能******************************************************************** **********/void Brake_Setting(void) {unsigned char i;KeepSpeed_Flag = 0;AutoHelp_Flag = 0;PWM_Duty_min = 1;Block_Flag = 0;UB = 1;VB = 1;WB = 1;Speed_SUM = 0;for(i=0;i<20;i++){..Speed_Buffer[i] = 0;}if(EABS_BrakeEN) // 电子刹车{if(Speed_SUM < Speed_Low) {PWM_Duty_H = 0x01; PWM_Duty_L = 0x00; EABS_Flag = 1;UT = 1;VT = 1;WT = 1;}else{UT = 0;VT = 0;WT = 0;}PWM_Setting();}}/******************************************************************** *********** 滑行充电功能******************************************************************** **********//*void Slip_Setting(void) {..if(EABS_SlipEN){UB = 1;VB = 1;WB = 1;_nop_();EABS_Flag = 1;UT = 1;VT = 1;WT = 1;}}/******************************************************************** *********** 电刹车功能使能* EBS_EN:滑行充电功能使能* EBB_EN:电刹车功能使能******************************************************************** **********/void EABS_Set(bit EBS_EN,bit EBB_EN) {EABS_SlipEN = EBS_EN;EABS_BrakeEN = EBB_EN;}/******************************************************************** *********** 1:1自动程序助力* 电动车中轴速度传感器(单开关霍尔信号),当转动中轴时产生高低电平信号。