首页 PIC单片机应用开发典型模块各章程序第七章程序

PIC单片机应用开发典型模块各章程序第七章程序

举报
开通vip

PIC单片机应用开发典型模块各章程序第七章程序(1)步进电机稳压直流稳压电源模块程序 #include unsigned char R1,R2,R3,TXDATA,LEDF,BJF,COUNTW,data; unsigned int i; const char table[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,0xFF}; //不带小数点的显示段码表 const char table0[11]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X...

PIC单片机应用开发典型模块各章程序第七章程序
(1)步进电机稳压直流稳压电源模块程序 #include unsigned char R1,R2,R3,TXDATA,LEDF,BJF,COUNTW,data; unsigned int i; const char table[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,0xFF}; //不带小数点的显示段码表 const char table0[11]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10,0xFF}; //带小数点的的显示段码表 unsigned char s[4]; //定义一个显示缓冲数组 //把需要显示的数字装入显示缓冲数组 void sfz() { s[0]=R3; s[1]=R2; s[2]=R1; s[3]=0x0A; //最后一个LED显示"DARK" } //系统各寄存器初始化子程序 void initial() { R1=0X00; R2=0X00; R3=0X00; sfz(); //把需要显示的数字装入显示缓冲数组 TXDATA=0X00; LEDF=0X01; BJF=0X01; TRISB1=0; TRISB2=0; TRISB4=1; TRISB5=1; //设置与键盘相关的各口的输入输出方式 RB1=0; RB2=0; //设置扫描初始条件 } //SPI方式显示初始化子程序 void SPIINIT() { PIR1=0; SSPCON=0x30; SSPSTAT=0xC0; //设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送,与"74HC595,当其 //SCLK从低到高跳变时,串行输入寄存器"的特点相对应 TRISC=0xD7; //SDO引脚为输出,SCK引脚为输出 TRISA5=0; //RA5引脚设置为输出,以输出显示锁存信号 } //I2C初始化子程序 void i2cint() { SSPCON = 0X08; //初始化SSPCON寄存器 TRISC3 =1; //设置SCL为输入口 TRISC4 =1; //设置SDA为输入口 TRISA4 = 0; SSPSTAT=0X80; //初始化SSPSTAT寄存器 SSPADD=0X02; //设定I2C时钟频率 SSPCON2=0X00; //初始化SSPCON2寄存器 di(); //关闭总中断 SSPIF=0; //清SSP中断标志 RA4=0; //关掉74HC165的移位时钟使能,以免74HC165 //移位数据输出与I2C总线的数据线发生冲突 SSPEN=1; //SSP模块使能 } //软件延时子程序 void DELAY() { for(i = 3553; --i ;) continue; } //键服务子程序 void keyserve() { PORTB=0XFD ; if(RB5==0) BJF=0X01; //S9键按下,步进加标志置1 PORTB=0XFB ; if(RB5==0) BJF=0X00; //S11键按下,步进加标志清0 RB1=0; //恢复PORTB的值 RB2=0; } //键扫描子程序 void KEYSCAN() { while(1){ while(1) { if (RB5==0) break; } DELAY(); //若有键按下,则软件延时 if (RB5==0) break; //若还有键按下,则终止循环扫描,返回 } } //SPI传送数据子程序 void SPILED(data) { SSPBUF=data; // 启动发送 do { ; }while(SSPIF==0); SSPIF=0; } //显示子程序 void display() { SPIINIT(); //spi方式显示初始化 RA5=0; //准备锁存 for(COUNTW=0;COUNTW<4;COUNTW++) { data=s[COUNTW]; if(COUNTW==1) data=table0[data];//第二位需要显示小数点 else data=table[data]; SPILED(data); //发送显示段码 } for(COUNTW=0;COUNTW<4;COUNTW++) { data=0xFF; SPILED(data); //连续发送4个DARK,使显示美观 } RA5=1; //最后给一个锁存信号,代表显示任务完成 } //I2C总线输出数据子程序 void i2cout() { i2cint(); //因为SPI输出和I2C输出不能同时工作,则需要 //不断在两种方式间切换 SEN=1; //产生I2C启动信号 for(i=0x02;--i;) continue; //给予一定的延时,保证启动 do { RSEN=1; //产生I2C启动信号 }while(SSPIF==0); //如果没能启动,则反复启动,直到启动为止 SSPIF=0; //SSPIF标志清0 SSPBUF=0X58; //I2C总线发送地址字节 do { ; }while(SSPIF==0); //等待地址发送完毕 SSPIF=0; //SSPIF标志清0 SSPBUF=0X01; //I2C总线发送命令字节 do { ; }while(SSPIF==0); //等待命令发送完毕 SSPIF=0; //SSPIF标志清0 SSPBUF=TXDATA; //I2C总线发送数据字节 do { ; }while(SSPIF==0); //等待数据发送完毕 SSPIF=0; //SSPIF标志清0 PEN=1; //产生停止条件 do { ; }while(SSPIF==0); //等待停止条件产生 SSPIF=0; //SSPIF标志清0 } //步进加子程序 void BJADD() { R1++; TXDATA=TXDATA+2; if(R1>9) { R1=0; R2++; if(R2>9) { R2=0; R3++; } } if((R3==1)&&(R2==2)&&(R1==1)) { R3=0; R2=0; R1=0; //若R3,R2,R1超过120,则又从0计起 TXDATA=0; } sfz(); //把需要显示的数字装入显示缓冲数组 } //步进减子程序 void BJSUB() { R1--; TXDATA=TXDATA-2; if(R1==0XFF) { R1=9; R2--; if(R2==0XFF) { R2=9; R3--; if(R3==0XFF) { R3=1; R2=2; R1=0; //若R3,R2,R1小于0,则又从120计起 TXDATA=0XF0; } } } sfz(); //把需要显示的数字装入显示缓冲数组 } //主程序 main() { initial(); //系统各寄存器初始化 display(); //调用一次显示子程序 while(1) { i2cout(); //调用I2C子程序,启动D/A转换 KEYSCAN(); //键盘扫描 keyserve() ; //若确实有键按下,则调用键服务程序 if(BJF==0X01) BJADD();//若步进加标志为1,则调用步进加子程序 else BJSUB(); //若步进加标志为0,则调用步进减子程序 display(); //调用一次显示子程序 } } (2步进电机驱动模块程序 PCL EQU 02H ;定义PCL寄存器地址 STATUS EQU 03H ;定义状态寄存器地址 PORTC EQU 07H ;定义端口C的数据寄存器地址 PORTD EQU 08H ;定义端口D的数据寄存器地址 TRISC EQU 87H ;定义端口C的方向寄存器 TRISD EQU 88H ;定义端口D的方向寄存器 INTCON EQU 0BH ;定义INTCON控制寄存器 CCP1IF EQU 2H ;定义CCP1IF CCP1CON EQU 17H ;定义CCP1CON控制寄存器 CCPR1L EQU 0EH ;定义CCPR1L控制寄存器 CCPR1H EQU 0FH ;定义CCPR1H控制寄存器 PIR1 EQU 0CH ;定义第一外设中断标志寄存器 PIR2 EQU 0DH ;定义第二外设中断标志寄存器 TMR1L EQU 0EH ;定义TMR1L TMR1H EQU 0FH ;定义TMR1F ADRESH EQU 1EH ;定义ADRESH ADCON0 EQU 1FH ;定义数/模转换器ADC的寄存器 PIE1 EQU 8CH ;定义第一外设中断屏蔽寄存器 PIE2 EQU 8DH ;定义第二外设中断屏蔽寄存器 ADCON1 EQU 9FH ;定义数/模转换器ADC的寄存器 T1CON EQU 10H ;定义TIMER1控制寄存器 RP1 EQU 06H ;定义状态寄存器中的页选位RP1 RP0 EQU 05H ;定义状态寄存器中的页选位RP0 Z EQU 02H ;定义状态寄存器中的0标志位Z C EQU 00H ;定义状态寄存器中的标志位C TMR1IF EQU 00H ;定义第二外设中断屏蔽寄存器中的TMR1IF DATA1 EQU 20H ;定义外循环变量 DATA2 EQU 21H ;定义内循环变量 TEMP EQU 22H ;定义临时变量存储端口D的输入 W_TEMP EQU 25H ;定义临时变量W_TEMP S_TEMP EQU 26H ;定义临时变量S_TEMP SCALER EQU 27H ;定义临时变量SCLEAR AD_STATUS EQU 28H ;定义临时变量AD_STATUS SIGN EQU 22H ;定义临时变量SIGN SUN EQU 24H ;定义临时变量SUN INDEX EQU 25H ;定义临时变量INDEX W_BUF EQU 26H ;定义临时变量W_BUF VALUE EQU 27H ;定义临时变量VALUE NUM EQU 28H ;定义临时变量NUM COUNT1 EQU 1AH ;定义存储外循环次数的变量 COUNT2 EQU 0FFH ;定义存储内循环次数的变量 ; ***************************主程序开始********************************* ORG 00H NOP ;空指令 GOTO MAIN ORG 04H ;中断向量的地址为04H GOTO INT ;跳到中断子程序 ; *****************************中断子程序开始**************************** INT MOVWF W_TEMP ;W寄存器的 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 存储 SWAPF STATUS,0 ;将STATUS寄存器中高低字节交换 MOVWF S_TEMP ;交换后的结果存入S_TEMP BCF STATUS,RP0 ;转到体0 BCF STATUS,RP1 ; BTFSC PIR1,TMR1IF ;查看是否TMR1中断 GOTO NEXT1 ;是 GOTO NEXT2 ;否 NEXT1 BTFSC SIGN,0 ;察看SIGN的第0位是否为0 GOTO NEXT3 ;否 BCF PORTC,2 ;是 NEXT3 COMF SIGN,1 ;SIGN取反 BCF PIR1,TMR1IF ;清中断标志位 CLRF TMR1L ;对TMR1重新输入值0F548H MOVLW 0F5H ; MOVWF TMR1H ; MOVLW 48H ; MOVWF TMR1L ; NEXT2 SWAPF S_TEMP,0 ;中断前的STATUS的内容,重新装入 MOVWF STATUS ; SWAPF W_TEMP,1 ;中断前的W的内容重新装入 SWAPF W_TEMP,0 ; RETFIE ; ********************************主程序开始***************************** MAIN CALL INITIAL ;调用初始化子程序 LOOP CALL AAA ;调用AAA输出子程序 NOP S_0 BTFSS SIGN,0 ;SIGN为1,则转到S_1 GOTO S_0 ; S_1 BTFSC SIGN,0 ;SIGN为0,则转到LOOP GOTO S_1 ; GOTO LOOP ; ;***************************初始化子程序开始********************************* INITIAL BCF STATUS,RP0 ;转到体0 BCF STATUS,RP1 ; CLRF W_TEMP ;将各个临时寄存器清零 CLRF W_BUF ; CLRF SIGN ; BSF STATUS,RP0 ;转到体1 BCF STATUS,RP1 ; BCF TRISC,2 ;将端口C的RC2设为输出 BCF STATUS,RP0 ;转到体0 BCF STATUS,RP1 ; CLRF T1CON ;清T1CON MOVLW 0F5H ;将TMR1设为0F548H MOVWF TMR1H ; MOVLW 048H ; MOVWF TMR1L ; CLRF INTCON ;清中断标志 BSF INTCON,6 ;中断使能 BSF STATUS,RP0 ;转到体1 BCF STATUS,RP1 ; BSF PIE1,0 ;TMR1中断使能 BCF STATUS,RP0 ;转到体0 BCF STATUS,RP1 ; CLRF PIR1 ;清中断标志 BSF STATUS,RP0 ;转到体1 BCF STATUS,RP1 ; BSF T1CON,0 ;开TMR1 BCF STATUS,RP0 ;转到体0 BCF STATUS,RP1 ; BSF INTCON,7 ;开第三梯队的中断 BCF PORTC,2 ;对各个变量清零 CLRF NUM ; CLRF VALUE ; CLRF NUM ; CLRF INDEX ; RETURN ;**********************AAA输出子程序*********************** AAA BCF STATUS,RP0 ;转到体0 BCF STATUS,RP1 ; MOVF NUM,0 ; BTFSS STATUS,Z ;NUM是否为零 GOTO BBB ;不是,跳转 CLRF NUM ;将NUM清零 BTFSC INDEX,4 ;INDEX是否大于16 CLRF INDEX ;是,清零 CALL TABLE ;否,查表 MOVWF VALUE ;查表的值存到VALUE INCF INDEX,0 ;INDEX加1 BBB MOVF VALUE,0 ; ADDWF NUM,0 ;VALUE+SUM存到W中 BTFSC STATUS,C ;测试是否有进位 GOTO NEXT4 ;有,跳转 BCF PORTC,2 ;无 RETURN NEXT4 BSF PORTC,2 ;有,RC2=1 RETURN TABLE MOVF INDEX,W ADDWF PCL,F RETLW 00H RETLW 04H RETLW 08H RETLW 0CH RETLW 10H RETLW 14H RETLW 14H RETLW 14H RETLW 14H RETLW 14H RETLW 14H RETLW 0CH RETLW 08H RETLW 04H RETLW 00H END (3)步进电机控制模块程序 #include <16F877.H> #DEVICE ICD=TRUE #DEVICE PIC16F877 *=16 ADC=10 #fuses XT,NONDT,NOPROTECT #use delay(clock=4000000) #byte PORTB=0x06 #byte PORTC=0x07 #byte PORTD=0x08 #byte OPTION=0x81 #byte INTCON=0x0B #byte TICON=0x10 #byte PR2=0x92 #byte T2CON=0x12 //timer2负责竖直方向运动 #byte TMRO=0x1 //timer0负责水平方向运动 #byte TMR2=0x11 #byte PR2=0x92 #bit RB_1 = 0x6.1 //力旋钮开关地址 #bit RB_2 = 0x6.2 #6it RB_4 = 0x6.4 #bit RB_5 = 0x6.5 #bit RBPU=Ox81.7 #bit TOIF=OxOB.2 #bit TMR2IF=0xOC.1 #bit TMR20N=0x12.2 #bit RCIF=OxDC.5 #bit fwardl=0x7.0 //脉冲发送脚地址 #bit bwardl=0x7.1 #bit fward2=0x7.2 #bit bward2=0x7.3 #bit RC_4=0x7.4 #bit RC_5=0x7.5 #bit zflg=0x08.0 //光电开关信号 #bit yflg=0x08.2 #bit xflg=0x08.4 #bit sflg=0x08.6 long int I; int j, k; long str[12]; //接收到的字符串 char dir; //方向 int a; long int pspeed, zspeed,distant; //运动参数 long int n_pulse; //完成运动电平变换次数(脉冲数的2倍?int ctmr0; //水平方向电平变换,所需timer0定时周期数 int ctmr2; //竖直方向电平变换,所需timer2定时周期数 float c_tmrO,ctmr2; //所需周期数的计算值 void setup() { RBPG=1; OPTION=0b10000110; //TMR0定时方式,分频值取1:64 T2CON=ObOO111001; //TMR2定时方式,分频值取1:32 enable_interrupts(CLOBAL); enable_interrupts(int_rda); RCIF=0; set_tris_B(0b11111111); set_tris_C(0b10000000); set_tris_D (Oblllllll); } long int round(float,x) //四舍五入函数 { long int n; n= (long int)(x): if ((x-n)<0.5) return(n); else return(n+l); } void forward1() //(向左运动) { fward1=!fward1; } void backward1() //水平后退(向右运动) { Bward1=bward1; } void forward2() //竖直步近电机运动 { fward2=!fward2; } void shoudong() { OPTION=0b10000101; //TMR0定时方式,分频值取1:64 T2CON=0b00111001; //TMR2定时方式,分频值取1:32 TMR2ON=1; //TMR2开始工作 bward2=0; //CCW接地,竖直向下 i= 0; TMR0=211; // TMR0定时64×45 output_high(PIN_C0 ); out put_high(PIN_C1); out put_high(PIN_C2); output_h igh(PIN_C3); while(1) { while(input(PIN_B1)= 0&&zflg!=0) { if(TOIF==1) { TMR0 = 211; TOIF = 0; Forward1(); } } Fward1=1; while (input(PIN_B2)=0&&yflg!=0) //后退 { if (TOIF==1) { TMR0 = 211; TOIF = 0 ; Backward1(); } } bward2=0; //CCW接地,竖直向下 PR2=62; //定时62*32us output_low(PIN_4); while(input(PIN_B4)==0&&xflg!=0) { //打开竖直电机制动 if(TMR2IF==1) { TMR2IF=0; forward2(); } //output_high(PIN_C4) hward2=1; //CCW接高,竖直向上 PR2=31; //定时3l×32us,速度10mm/s Output_low(PIN_C4); while (input(PIN_B5 )==0&&sflg!=0) { if(TMR2IF==1) { TMR2IF=0; forward2(); } } //output_high(PIN_C4); //关闭竖直电机制动 output_high(PIN_CO); output_high(PIN_C1 ); output_high(PIN_C2); output_high(PIN_C3); nable_interrupts(GLOBAL); void qidong() { output_low(PlN_C4); while(RCIF!=1) { i=0; bward2=1; while(sflg!=0&&i<3000) //以20mm每秒的速度上升30mm { forward2(); Delay_us(500); i++; } output_low(PIN_C4); while(RCIF!=1) { i=0; bward2 = 0; while (xflg!=0&&<3500) //以25mm/s的速度下降35mm;撞击,接触0.2s { forward2() ; delay_us(400); i++; } delay_ms(200); i= 0; bward2 = 1; while(sflg!=0&&i<500) //以25mm/s的速度上升5mm { forward2(); delay_us(400); i+ +; } delay_ms(1000); //延时1s,等待上位机判断有无电流产生 if(RCIF!=1) { bward2=1; i= 0; while(sflg!=0 && i<2500) //以20mm每秒的速度上升25mm {forward2(); Delay_us(500) ; i++; } } } //output_high(PIN_C4); //-------------------------------------------------- void reset() { output_low(PIN_C4 ); //打开竖直电机制动 bward2= 1; //竖直方向向上 while(sflg!=0&&yflg!=0) //右起点、上起点都没到 {backward1(); forward2(); delay_ms(2) } while(sflg!=0) {bward2=1; forward2(); delay_ms(1); } while(yflg!=0) //已到上起点起点,往右运动 { backward1(); delayms(3); } //output_high(PIN_C4 ) //关闭竖直电机制动 //--------------------------------------------------- #int rda void zidong() { for(i=0;i<12;i++) { str[i]=getc(); } delay_ms(5); disabIe_intcrrupts(GLOBAL); n_puIse=0; OPTION=0b10000000; //TMR0分频值取1:2 TMR0=211 ; //TMR0定时2*45us T2CON=0600000001: //TMR2定时方式,分频值取1:1 RCIF=O; if(str[0]!=’#'&&str[1]!=’#’) { putc('N'); goto END; } else { putc('Y'); if (str[2]=='E') reset(); else {dir=str[2]; distant=100*(str[3]-48)+10*(str[4]-48+(str[5]-48); //字符串转换为数值 pspeed=100*(str[6]-48)+10*(str[7]-48)+(str[8]-48); zspeed=100*(str[9]-48)+10*(str[10]-48)+(str[11]-48); n_pulse=distant*50; //完成行程总脉冲数 c_tmr0=11000/pspeed; //所需周期数的计算值 c_tmr2= 3750/zspeed; ctmr0=round(c_tmrO); //实际所用为四舍五入取整 ctmr2=round(c_tmr2); i = 0; j = 0; k = 0; output_high(PIN_C0); output_high(PIN_C1); output_high(PIN_C2); output_high(PIN_C3); qidong(); //启动 bward2=0; output_low(PIN_C4); //打开竖直电机制动 TMR20N=1; //开timer2 PR2=40; //TMR2定时40us while(i<=n_pulse) { if(TOIF==1) { TOIF=O; TMRO = 211; j++; } if(j==ctmr0) {. j=O; if(dir=='0') { if(zflg!=0) { Forward1(); i++; } } else {if(yflg!=0) {backwardl(); i++; } if(TMR2IF==1) { TMR2IF=0; k++; } if(k==ctmr2&&xflg!=0) { k=0; forward2(); } } output_high(PIN_CO); output_high(PIN_C1); output_high(PIN_C2); output_high(PIN_C3); } } output_high(PIN_C4); //关闭竖直电机制动 END: enable_interrupts(GLOBAL); //---------------------------------------------------------- main() ( setup(); enable_interrupts(int_rda); enable_interrupts(GLOBAL); while (1) { if((RB_1==0||(RB2 ==O||(RB_4==0||(RB_5= 0)) //有键按下为手动 {shoudong(); } else { i=0; } (4)直流无刷电机控制模块程序 #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 #define VOLOFF 0X49 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}; //状态寄存器表 (2)PIC16F877初始化子程序 void INIT877() { PORTC=0X0FF; //关断所有MOSFET TRISC=0X02; //设置C口输出 PIE1=0X00; //中断寄存器初始化,关断所有中断 TRISA=0XCF; //设置RA4,RA5 输出 TRISB=0XEF; //RB 口高3位输入,采集电机三相的霍尔信号 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为1分频 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部件开始工作 } 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"); } } } 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>1); CCPR1L=FULLDUTY; asm("CLRWDT"); }while(voltage>5); PORTC=new[state1]; //C口输出相应的信号触发2个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 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; } } } _1209066871.unknown
本文档为【PIC单片机应用开发典型模块各章程序第七章程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_519674
暂无简介~
格式:doc
大小:132KB
软件:Word
页数:23
分类:互联网
上传时间:2018-09-10
浏览量:6