下载

2下载券

加入VIP
  • 专属下载券
  • 上传内容扩展
  • 资料优先审核
  • 免费资料无限下载

上传资料

关闭

关闭

关闭

封号提示

内容

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

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

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

WindomZhong
2018-09-08 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《PIC单片机应用开发典型模块各章程序第七章程序doc》,可适用于IT/计算机领域

()步进电机稳压直流稳压电源模块程序#include<pich>unsignedcharRRRTXDATALEDFBJFCOUNTWdataunsignedinticonstchartable={xcxfxaxbxxxXDxxxFF}不带小数点的显示段码表constchartable={XXXXXXXXXXxFF}带小数点的的显示段码表unsignedchars定义一个显示缓冲数组把需要显示的数字装入显示缓冲数组voidsfz(){s=Rs=Rs=Rs=xA最后一个LED显示"DARK"}系统各寄存器初始化子程序voidinitial(){R=XR=XR=Xsfz()把需要显示的数字装入显示缓冲数组TXDATA=XLEDF=XBJF=XTRISB=TRISB=TRISB=TRISB=设置与键盘相关的各口的输入输出方式RB=RB=设置扫描初始条件}SPI方式显示初始化子程序voidSPIINIT(){PIR=SSPCON=xSSPSTAT=xC设置SPI的控制方式允许SSP方式并且时钟下降沿发送与"HC,当其SCLK从低到高跳变时串行输入寄存器"的特点相对应TRISC=xDSDO引脚为输出SCK引脚为输出TRISA=RA引脚设置为输出以输出显示锁存信号}IC初始化子程序voidicint(){SSPCON=X初始化SSPCON寄存器TRISC=设置SCL为输入口TRISC=设置SDA为输入口TRISA=SSPSTAT=X初始化SSPSTAT寄存器SSPADD=X设定IC时钟频率SSPCON=X初始化SSPCON寄存器di()关闭总中断SSPIF=清SSP中断标志RA=关掉HC的移位时钟使能以免HC移位数据输出与IC总线的数据线发生冲突SSPEN=SSP模块使能}软件延时子程序voidDELAY(){for(i=i)continue}键服务子程序voidkeyserve(){PORTB=XFDif(RB==)BJF=XS键按下步进加标志置PORTB=XFBif(RB==)BJF=XS键按下步进加标志清RB=恢复PORTB的值RB=}键扫描子程序voidKEYSCAN(){while(){while(){if(RB==)break}DELAY()若有键按下则软件延时if(RB==)break若还有键按下则终止循环扫描返回}}SPI传送数据子程序voidSPILED(data){SSPBUF=data启动发送do{}while(SSPIF==)SSPIF=}显示子程序voiddisplay(){SPIINIT()spi方式显示初始化RA=准备锁存for(COUNTW=COUNTW<COUNTW){data=sCOUNTWif(COUNTW==)data=tabledata第二位需要显示小数点elsedata=tabledataSPILED(data)发送显示段码}for(COUNTW=COUNTW<COUNTW){data=xFFSPILED(data)连续发送个DARK使显示美观}RA=最后给一个锁存信号代表显示任务完成}IC总线输出数据子程序voidicout(){icint()因为SPI输出和IC输出不能同时工作则需要不断在两种方式间切换SEN=产生IC启动信号for(i=xi)continue给予一定的延时保证启动do{RSEN=产生IC启动信号}while(SSPIF==)如果没能启动则反复启动直到启动为止SSPIF=SSPIF标志清SSPBUF=XIC总线发送地址字节do{}while(SSPIF==)等待地址发送完毕SSPIF=SSPIF标志清SSPBUF=XIC总线发送命令字节do{}while(SSPIF==)等待命令发送完毕SSPIF=SSPIF标志清SSPBUF=TXDATAIC总线发送数据字节do{}while(SSPIF==)等待数据发送完毕SSPIF=SSPIF标志清PEN=产生停止条件do{}while(SSPIF==)等待停止条件产生SSPIF=SSPIF标志清}步进加子程序voidBJADD(){RTXDATA=TXDATAif(R>){R=Rif(R>){R=R}}if((R==)(R==)(R==)){R=R=R=若RRR超过则又从计起TXDATA=}sfz()把需要显示的数字装入显示缓冲数组}步进减子程序voidBJSUB(){RTXDATA=TXDATAif(R==XFF){R=Rif(R==XFF){R=Rif(R==XFF){R=R=R=若RRR小于则又从计起TXDATA=XF}}}sfz()把需要显示的数字装入显示缓冲数组}主程序main(){initial()系统各寄存器初始化display()调用一次显示子程序while(){icout()调用IC子程序启动DA转换KEYSCAN()键盘扫描keyserve()若确实有键按下则调用键服务程序if(BJF==X)BJADD()若步进加标志为则调用步进加子程序elseBJSUB()若步进加标志为则调用步进减子程序display()调用一次显示子程序}}(步进电机驱动模块程序PCLEQUH定义PCL寄存器地址STATUSEQUH定义状态寄存器地址PORTCEQUH定义端口C的数据寄存器地址PORTDEQUH定义端口D的数据寄存器地址TRISCEQUH定义端口C的方向寄存器TRISDEQUH定义端口D的方向寄存器INTCONEQUBH定义INTCON控制寄存器CCPIFEQUH定义CCPIFCCPCONEQUH定义CCPCON控制寄存器CCPRLEQUEH定义CCPRL控制寄存器CCPRHEQUFH定义CCPRH控制寄存器PIREQUCH定义第一外设中断标志寄存器PIREQUDH定义第二外设中断标志寄存器TMRLEQUEH定义TMRLTMRHEQUFH定义TMRFADRESHEQUEH定义ADRESHADCONEQUFH定义数模转换器ADC的寄存器PIEEQUCH定义第一外设中断屏蔽寄存器PIEEQUDH定义第二外设中断屏蔽寄存器ADCONEQUFH定义数模转换器ADC的寄存器TCONEQUH定义TIMER控制寄存器RPEQUH定义状态寄存器中的页选位RPRPEQUH定义状态寄存器中的页选位RPZEQUH定义状态寄存器中的标志位ZCEQUH定义状态寄存器中的标志位CTMRIFEQUH定义第二外设中断屏蔽寄存器中的TMRIFDATAEQUH定义外循环变量DATAEQUH定义内循环变量TEMPEQUH定义临时变量存储端口D的输入WTEMPEQUH定义临时变量WTEMPSTEMPEQUH定义临时变量STEMPSCALEREQUH定义临时变量SCLEARADSTATUSEQUH定义临时变量ADSTATUSSIGNEQUH定义临时变量SIGNSUNEQUH定义临时变量SUNINDEXEQUH定义临时变量INDEXWBUFEQUH定义临时变量WBUFVALUEEQUH定义临时变量VALUENUMEQUH定义临时变量NUMCOUNTEQUAH定义存储外循环次数的变量COUNTEQUFFH定义存储内循环次数的变量***************************主程序开始*********************************ORGHNOP空指令GOTOMAINORGH中断向量的地址为HGOTOINT跳到中断子程序*****************************中断子程序开始****************************INTMOVWFWTEMPW寄存器的内容存储SWAPFSTATUS,将STATUS寄存器中高低字节交换MOVWFSTEMP交换后的结果存入STEMPBCFSTATUS,RP转到体BCFSTATUS,RPBTFSCPIR,TMRIF查看是否TMR中断GOTONEXT是GOTONEXT否NEXTBTFSCSIGN,察看SIGN的第位是否为GOTONEXT否BCFPORTC,是NEXTCOMFSIGN,SIGN取反BCFPIR,TMRIF清中断标志位CLRFTMRL对TMR重新输入值FHMOVLWFHMOVWFTMRHMOVLWHMOVWFTMRLNEXTSWAPFSTEMP,中断前的STATUS的内容重新装入MOVWFSTATUSSWAPFWTEMP,中断前的W的内容重新装入SWAPFWTEMP,RETFIE********************************主程序开始*****************************MAINCALLINITIAL调用初始化子程序LOOPCALLAAA调用AAA输出子程序NOPSBTFSSSIGN,SIGN为则转到SGOTOSSBTFSCSIGN,SIGN为则转到LOOPGOTOSGOTOLOOP***************************初始化子程序开始*********************************INITIALBCFSTATUS,RP转到体BCFSTATUS,RPCLRFWTEMP将各个临时寄存器清零CLRFWBUFCLRFSIGNBSFSTATUS,RP转到体BCFSTATUS,RPBCFTRISC,将端口C的RC设为输出BCFSTATUS,RP转到体BCFSTATUS,RPCLRFTCON清TCONMOVLWFH将TMR设为FHMOVWFTMRHMOVLWHMOVWFTMRLCLRFINTCON清中断标志BSFINTCON,中断使能BSFSTATUS,RP转到体BCFSTATUS,RPBSFPIE,TMR中断使能BCFSTATUS,RP转到体BCFSTATUS,RPCLRFPIR清中断标志BSFSTATUS,RP转到体BCFSTATUS,RPBSFTCON,开TMRBCFSTATUS,RP转到体BCFSTATUS,RPBSFINTCON,开第三梯队的中断BCFPORTC,对各个变量清零CLRFNUMCLRFVALUECLRFNUMCLRFINDEXRETURN**********************AAA输出子程序***********************AAABCFSTATUS,RP转到体BCFSTATUS,RPMOVFNUM,BTFSSSTATUS,ZNUM是否为零GOTOBBB不是跳转CLRFNUM将NUM清零BTFSCINDEX,INDEX是否大于CLRFINDEX是清零CALLTABLE否查表MOVWFVALUE查表的值存到VALUEINCFINDEX,INDEX加BBBMOVFVALUE,ADDWFNUM,VALUESUM存到W中BTFSCSTATUS,C测试是否有进位GOTONEXT有跳转BCFPORTC,无RETURNNEXTBSFPORTC,有RC=RETURNTABLEMOVFINDEX,WADDWFPCL,FRETLWHRETLWHRETLWHRETLWCHRETLWHRETLWHRETLWHRETLWHRETLWHRETLWHRETLWHRETLWCHRETLWHRETLWHRETLWHEND()步进电机控制模块程序#include<FH>#DEVICEICD=TRUE#DEVICEPICF*=ADC=#fusesXT,NONDT,NOPROTECT#usedelay(clock=)#bytePORTB=x#bytePORTC=x#bytePORTD=x#byteOPTION=x#byteINTCON=xB#byteTICON=x#bytePR=x#byteTCON=xtimer负责竖直方向运动#byteTMRO=xtimer负责水平方向运动#byteTMR=x#bytePR=x#bitRB=x力旋钮开关地址#bitRB=x#itRB=x#bitRB=x#bitRBPU=Ox#bitTOIF=OxOB#bitTMRIF=xOC#bitTMRN=x#bitRCIF=OxDC#bitfwardl=x脉冲发送脚地址#bitbwardl=x#bitfward=x#bitbward=x#bitRC=x#bitRC=x#bitzflg=x光电开关信号#bityflg=x#bitxflg=x#bitsflg=xlongintIintj,klongstr接收到的字符串chardir方向intalongintpspeed,zspeed,distant运动参数longintnpulse完成运动电平变换次数(脉冲数的倍intctmr水平方向电平变换所需timer定时周期数intctmr竖直方向电平变换所需timer定时周期数floatctmrO,ctmr所需周期数的计算值voidsetup(){RBPG=OPTION=bTMR定时方式分频值取:TCON=ObOOTMR定时方式分频值取:enableinterrupts(CLOBAL)enableinterrupts(intrda)RCIF=settrisB(b)settrisC(b)settrisD(Oblllllll)}longintround(floatx)四舍五入函数{longintnn=(longint)(x):if((xn)<)return(n)elsereturn(nl)}voidforward()(向左运动){fward=!fward}voidbackward()水平后退(向右运动){Bward=bward}voidforward()竖直步近电机运动{fward=!fward}voidshoudong(){OPTION=bTMR定时方式分频值取:TCON=bTMR定时方式分频值取:TMRON=TMR开始工作bward=CCW接地竖直向下i=TMR=TMR定时×outputhigh(PINC)outputhigh(PINC)outputhigh(PINC)outputhigh(PINC)while(){while(input(PINB)=zflg!=){if(TOIF==){TMR=TOIF=Forward()}}Fward=while(input(PINB)=yflg!=)后退{if(TOIF==){TMR=TOIF=Backward()}}bward=CCW接地竖直向下PR=定时*usoutputlow(PIN)while(input(PINB)==xflg!=){打开竖直电机制动if(TMRIF==){TMRIF=forward()}outputhigh(PINC)hward=CCW接高竖直向上PR=定时l×us,速度mmsOutputlow(PINC)while(input(PINB)==sflg!=){if(TMRIF==){TMRIF=forward()}}outputhigh(PINC)关闭竖直电机制动outputhigh(PINCO)outputhigh(PINC)outputhigh(PINC)outputhigh(PINC)nableinterrupts(GLOBAL)voidqidong(){outputlow(PlNC)while(RCIF!=){i=bward=while(sflg!=i<)以mm每秒的速度上升mm{forward()Delayus()i}outputlow(PINC)while(RCIF!=){i=bward=while(xflg!=<)以mms的速度下降mm撞击接触s{forward()delayus()i}delayms()i=bward=while(sflg!=i<)以mms的速度上升mm{forward()delayus()i}delayms()延时s等待上位机判断有无电流产生if(RCIF!=){bward=i=while(sflg!=i<)以mm每秒的速度上升mm{forward()Delayus()i}}}outputhigh(PINC)voidreset(){outputlow(PINC)打开竖直电机制动bward=竖直方向向上while(sflg!=yflg!=)右起点、上起点都没到{backward()forward()delayms()}while(sflg!=){bward=forward()delayms()}while(yflg!=)已到上起点起点往右运动{backward()delayms()}outputhigh(PINC)关闭竖直电机制动#intrdavoidzidong(){for(i=i<i){stri=getc()}delayms()disabIeintcrrupts(GLOBAL)npuIse=OPTION=bTMR分频值取:TMR=TMR定时*usTCON=:TMR定时方式分频值取:RCIF=Oif(str!=’#'str!=’#’){putc('N')gotoEND}else{putc('Y')if(str=='E')reset()else{dir=strdistant=*(str)*(str(str)字符串转换为数值pspeed=*(str)*(str)(str)zspeed=*(str)*(str)(str)npulse=distant*完成行程总脉冲数ctmr=pspeed所需周期数的计算值ctmr=zspeedctmr=round(ctmrO)实际所用为四舍五入取整ctmr=round(ctmr)i=j=k=outputhigh(PINC)outputhigh(PINC)outputhigh(PINC)outputhigh(PINC)qidong()启动bward=outputlow(PINC)打开竖直电机制动TMRN=开timerPR=TMR定时uswhile(i<=npulse){if(TOIF==){TOIF=OTMRO=j}if(j==ctmr){j=Oif(dir==''){if(zflg!=){Forward()i}}else{if(yflg!=){backwardl()i}if(TMRIF==){TMRIF=k}if(k==ctmrxflg!=){k=forward()}}outputhigh(PINCO)outputhigh(PINC)outputhigh(PINC)outputhigh(PINC)}}outputhigh(PINC)关闭竖直电机制动END:enableinterrupts(GLOBAL)main()(setup()enableinterrupts(intrda)enableinterrupts(GLOBAL)while(){if((RB==||(RB==O||(RB==||(RB=))有键按下为手动{shoudong()}else{i=}()直流无刷电机控制模块程序#defineANDxe状态采集位#defineCURAXa电流环比例和积分系数之和#defineCURBX电流环比例系数#defineTHLX电流环最大输出#defineFULLDUTYXFF占空比为时的高电平时间#defineSPEAXd转速环比例和积分系数之和#defineSPEBXc转速环比例系数#defineGCURHILOX转速环最大输出#defineGCURHX最大给定电流#defineGSPEHX最大转速给定#defineTSONX手柄开启电压VTSON×为刹车后手柄开启电压即V#defineVOLONXc#defineVOLOFFXvolatileunsignedcharDELAYH,DELAYL,oldstate,speed,speedcount,tsh,countts,countvol,gcur,currenth,voltage寄存器定义staticbitsp,spe,ts,volflag,spepid,lowpower,off,shutdown,curpid标志位定义staticvolatileunsignedcharnew={xaf,xbe,xff,xe,xcf,xff,xd,x,xff,xff}状态寄存器表()PICF初始化子程序voidINIT(){PORTC=XFF关断所有MOSFETTRISC=X设置C口输出PIE=X中断寄存器初始化关断所有中断TRISA=XCF设置RA,RA输出TRISB=XEFRB口高位输入采集电机三相的霍尔信号PORTC=new(PORTBAND)>>采集第一次霍尔信号并输出相应的信号导通两个MOS管TCON=XTMR分频CCPRL=XFF初始时PWM输出全高CCPCON=XFFCCP设置为PWM方式CCPCON=XBCCP设置为特殊方式以触发ADADCON=XAD时钟为分频且AD使能选择AN通道采集手柄电压TMR=XTMR寄存器初始化TMRH=XTMR寄存器初始化TMRL=XTCON=XTMR为分频CCPRH=XCCPRL=X电流采样周期设置为TAD=μsPR=XCPWM频率设置为kHzADCON=XAD结果左移OPTION=XFBINT上升沿触发TMRON=PWM开始工作INTCON=XD中断设置GIE=PEIE=RBIE=ADIE=AD中断使能speedcount=x转速计数寄存器speed=xf转速保持寄存器spe=低速标志位sp=低速标志位oldstate=xff初始状态设置区别于其他状态countts=x电流采样次,采集次手柄countvol=x采样次手柄,采集次电池电压ts=可以采集手柄值的标志位ADGO=AD采样使能TMRON=CCP部件开始工作}main(){for(){INIT()单片机复位后先对其进行初始化off=清复位标志for(off==){复位标志为零则执行下面程序否则复位if(curpid==)CURPI()电流PI运算elseif(spepid==)SPEPI()转速PI运算elseif(lowpower==)POWER()elseif(shutdown==)BREAKON()asm("CLRWDT")}}}voidBREAKON(){charxoff=off清零如果是干扰则不复位shutdown=if(RB==){如果刹车信号为真则停止输出电压ADIE=关AD中断INTE=关刹车中断CCPRL=FULLDUTY输出电压TMRON=关CCP不再触发ADfor(ADGO==)continue如正在采样则等待采样结束ADIF=ADIF位清零CHS=选择通道采样手柄CHS=x=DELAY(x)do{ADGO=for(ADIF==)continueADIF=CCPRL=FULLDUTYasm("CLRWDT")tsh=(ADRESH>>)}while(tsh>TSON||RB==)当手柄值大于V或刹车仍旧继续时,执行以上语句off=置复位标志}}voidPOWER(){charxlowpower=voltage>>=电压值换为位以利于单字节运算if(voltage<VOLOFF){电池电压小于*k(V)时保护ADIE=INTE=TMRON=CCPRL=FULLDUTYfor(ADGO==)continueADIF=CHS=CHS=x=DELAY(x)do{ADGO=for(ADIF==)continueADIF=voltage=(ADRESH>>)CCPRL=FULLDUTYasm("CLRWDT")}while(voltage<VOLON)电池电压小于V时继续保护off=置复位标志}}#pragmainterruptlevelvoidinterruptINTS(void){if(RBIF==){RBIF=sample()}elseif(ADIF==)AD()elseif(INTF==){shutdown=INTF=}刹车中断来置刹车标志}延时子程序#pragmainterruptlevelvoidDELAY(x)charx{DELAYH=x延时参数设置#asmDELAYMOVLWXMOVWFDELAYLDELAYDECFSZDELAYLGOTODELAYDECFSZDELAYHGOTODELAY#endasm}状态采集子程序voidsample(){charstate,state,state,xdo{x=state=(PORTBAND)霍尔信号采集DELAY(x)state=(PORTBAND)}while(statestate)当次采样结果不相同时继续采集状态if(stateoldstate!=)看本次采样结果是否与上次相同不同则执行{oldstate=state将本次状态设置为旧状态state=(oldstate>>)PORTC=newstateC口输出相应的信号触发个MOS管if(sp==){spe=sp=}else{如果转速很低则spe置spe=sp=speedcount<<=state=(TMRH>>)否则spe=,计转速speed=speedcountstatespeed寄存器为每μs加}speedcount=}}AD采样子程序voidAD(){charxADIF=清AD中断标志位if(ts==){如果为手柄采样则采样手柄值CHS=选择电流采样通道countvol=countvol电池采样计数寄存器spepid=置转速闭环运算标志ts=tsh=ADRESH存手柄值if(countvol==){如果电池采样时间到则选择AN通道采集电池电压CHS=CHS=volflag=x=DELAY(x)ADGO=}}elseif(volflag==){电池采样完毕进行相应的处理CHS=CHS=volflag=voltage=ADRESHlowpower=}else{否则中断为采样电流中断speedcount=speedcountspeedcount寄存器加作为测量转速用if(speedcount>xd)sp=如果转速低于μs(μs×eh×)则认为为低速状态currenth=ADRESHcurpid=countts=counttsif(countts==){如果手柄时间到则转入手柄采样通道CHS=countts=xts=x=DELAY(x)ADGO=}}}电流环运算子程序voidCURPI(){staticintcurep=x,curek=x,curuk=xuniondata{intpwmchara}b定义电流环运算寄存器curpid=清电流运算标志curep=curek*CURB计算上一次偏差与比例系数的积if(currenth<)currenth=如果采样电流为零则认为有一个小电流以利于使转速下降currenth>>=curek=gcurcurrenth计算本次偏差curuk=curukcurek*CURAcurep按闭环PI运算方式得到本次输出结果下面对结果进行处理if(curuk<x){如果输出小于零则认为输出为零curuk=CCPRL=FULLDUTYCCPX=CCPY=}elseif(curukTHL>=){如果输出大于限幅值则输出最大电压curuk=THLCCPRL=CCPX=CCPY=}else{否则按比例输出相应的高电平时间到CCPR寄存器bpwm=THLcurukbpwm<<=CCPRL=baCCPRL=(bpwm>>)xff将PWM寄存器的高半字节if(bpwmx!=)CCPX=elseCCPX=if(bpwmx!=)CCPY=elseCCPY=}}转速环运算子程序voidSPEPI(){staticintspeep=x,speek=x,speuk=xinttsh,speed转速寄存器定义spepid=清转速运算标志if(spe==)speed=x若转速太低则认为转速为零elsespeed=xfspeed否则计算实际转速if(speed<)speed=speep=speek*SPEBtsh=tshx得到计算用的手柄值speek=tshspeedif(tsh<){speuk=gcur=}当手柄值低于V时则认为手柄给定为零else{否则计算相应的转速环输出if(tsh>=GSPEH)限制最大转速tsh=GSPEHspeuk=speukspeek*SPEAspeep计算得转速环输出if(speuk<=X){speuk=xgcur=x}转速环输出处理elseif(speuk>GCURHILO){转速环输出限制即限制最大电流约Aspeuk=GCURHILOgcur=GCURH}else{调速状态时的输出gcur=(speuk>>)xff}}}unknown

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

评分:

/23

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利