请问各位高手,我要编一个C语言控制的无刷电机程序。

请问各位高手,我要编一个C语言控制的无刷电机程序。,第1张

#include<c8051f120.h>

#define uint unsigned int

#define uchar unsigned char

uchar num1 = 0

uint v_set = 40

xdata uint pcacap2

xdata uchar dutycycle

uint A=10//float D=0.04float C=5

//int xdata e0=0,e1=0,e2=0

float xdata PWM=0

bit isnewdata

bit DIRECTON

#define POSITIVE DIRECTON = 1

#define NEGATIVE DIRECTON = 0

void Oscillator_Init()

{

SFRPAGE = CONFIG_PAGE

OSCICN= 0x83

}

void Port_IO_Init()

{

SFRPAGE = 0x0F

XBR0 = 0xF7

XBR2 = 0x40

}

void PCA_Init()

{

SFRPAGE=0x00

PCA0CPM0=0x02

PCA0CPM1=0x02

PCA0CPM2=0x21

PCA0CPL2=0x00

PCA0CPH2=0x00

PCA0MD=0x00

PCA0CN=0x40

EIE1|=0x08

}

void PWM_set(uchar low)

{//占空比设置,高电平占空比为(256-low)/256

SFRPAGE = PCA0_PAGE

if (DIRECTON == 1) {PCA0CPH0 = lowPCA0CPM1 = 0x02PCA0CPM0 = 0x42}

else {PCA0CPH1 = lowPCA0CPM0 = 0x02PCA0CPM1 = 0x42}

}

void PCA_ISR(void) interrupt 9 using 1 {

static xdata uint tmpcnt=0

static xdata uint PCA0CP2=0

xdata uint tmpcnt2

if(CCF2){

tmpcnt2 = PCA0CPH2

tmpcnt2 = tmpcnt2<<8

PCA0CP2 = tmpcnt2 + PCA0CPL2

pcacap2 = PCA0CP2-tmpcnt

tmpcnt = PCA0CP2

CCF2=0

}

}

PID_SC(uint v)

{

int Uk_zint e

e = v - v_set

//e1 = v1 - v_set

//e2 = v2 - v_set

//v2 = v1

//v1 = v

Uk_z = A*e/*+ D*e0 + C*(e0 - 2*e1 + e2)*/

//Uk0 = Uk1 + Uk_z

//Uk1 = Uk0

//PWM = PWM - 256

dutycycle = 0.0256 * Uk_z

}

void main()

{

//Oscillator_Init()

WDTCN = 0x07

WDTCN = 0xDE

WDTCN = 0xAD

Port_IO_Init()

EA=1

num1=0

isnewdata=0

PCA_Init()

POSITIVE

while(1){PID_SC(pcacap2)PWM_set(dutycycle)}

}

4相4拍步进电机,步进角为7.5

步进电机驱动口连接在RA0-RA3

include<p16f877a.inc> 包含877A的头文件

__CONFIG _DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC

芯片配置字,看门狗关,上电延时开,掉电检测关饥圆碧,低压编程关,加密,4M晶体HS振荡

#define step1 9h 转动第1步驱动信号(不同的电机,可以引出线顺序不一样)

#define step2 0ch 转动第2步驱动信号(本程序以“常州市丰源微特电记有限公司的35BY48S053”电机为基础)

#define step3 6h 转动第3步驱动信号

#define step4 3h 转动第4步驱动信号

countequ 20h

org 00h 复位入口

nop ICD所需要的烂举空指令

goto main 跳转到主程序

org 05h

****************************主程序***************************

main

banksel adcon1

movlw 07h

movwf adcon1设置所有A口为普通数字口

banksel trisa

clrf trisa 设置A口为输出

clrf status

clrf porta

movlw .12电机旋转一周需循环次数 360/(7.5*4)

movwf count

loop

movlw step1 第1步

movwf porta

call delay

movlw step2 第2步

movwf porta

call delay

movlw step3 第3步

movwf porta

call delay

movlw step4 第4步

movwf porta

call delay

decfsz count,1是否旋转完一周

goto loop 否,继腔隐续转动

clrf porta 是,停止转动

goto $-1停机

*******************************延时程序********************************

控制输出的频率

delay

movfw 0FH

movwf 21h

movlw 0ffh

movwf 22h

decfsz 22h,1

goto $-1

decfsz 21h,1

goto $-5

return

******************************源程序结束*******************************

end

这个是完整的程序哦,建议你别用51,过时了,有些功能还有焊接扩展电路麻烦....

用AVR的吧

另外下面的程序是获奖的大学生电子设计作品一等奖呢,电路就不给了,要不你那就没啥意思了,快毕业了就点,有好处

#include<iom16v.h>

#include<macros.h>

#define uchar unsigned char

#define uint unsigned int

uchar senserflag=0//传感器状态标志

uchar count1=0

uchar jsflag=0//金属标志

uchar task=1 //任务标志

uint distancedata=0//路程值

uint distancecount=0//禅旦路程脉冲记数

//数码管字型表,对应0,1,2,3,4,5,6,7,8,9//#pragma data:code

#pragma data:code

const uchar Table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}

#pragma data:data

static uchar Data[3]={0,0,0} //显示初始值:0 0 0

uchar CNT=0 //初始计数值:0

uchar Timer[2]={1,10} //初始时间00:00

uchar disdata[3]={0,0,0}//路程初值0

//********************T/C0中断服务函数********************//

#pragma interrupt_handler Timer0:10

void Timer0(void)

{TCNT0=0x06

CNT++ //中断次数累加

if(CNT==125)

{CNT=0 //计数到125次,计数值复位

Timer[1]-- //秒加1

if(Timer[1]==255)

{Timer[1]=59

Timer[0]--} //分进位

if(Timer[0]==10)

Timer[0]=0} //计数到达最高位,计数复位

}

void DelayMs(uint i)

{

uint j

for(i!=0i--)

{for(j=4000j!=0j--){}}

}

void Display(uchar *p) //动蠢数态显示函数,参数p为待显示的数组名

{uchar i,sel

for(i=0i<3i++)

{sel=0x02

PORTB=~(sel<<i) //选通最右边的数码管

PORTC=Table[p[i]] //送字型码

DelayMs(1)//显示延时

PORTC=0x00

//移位以显示前一位

}

}

//计数值处理函数。参数p1:时间数组名;参数p2:显示数组名//

//功能:此函数用于将计数值拆分为BCD码的10分,分,10秒,秒//

void Process(uchar *p1,uchar *p2)

{

p2[0]=p1[0]%10

p2[1]=p1[1]/10

p2[2]=p1[1]%10

}

//*****************************************************

//*************处理传感器状态带袭首**************************

#pragma interrupt_handler readportA:9

void readportA(void)

{

if(task) js_jc()

if ((PINA&0X3f)==0X00) //没有,检测小车行驶状态

senserflag=0//不调整

else bianma()

}

//*************************************************

void js_jc(void)

{if(PINA&0x40)

jsflag=1

if((jsflag==1)&(!(PINA&0x40)))

jsflag=2

}

//*****************************************************

void bianma(void)

{uchar readtemp

readtemp=PINA&0x3f

switch (readtemp)

{case 0x20 : senserflag=1break// 过左偏

case 0x30 : senserflag=1break// 过左偏

case 0x28 : senserflag=1break// 过左偏

case 0x38 : senserflag=1break// 过左偏

case 0x01 : senserflag=2break// 过右偏

case 0x03 : senserflag=2break// 过右偏

case 0x05 : senserflag=2break// 过右偏

case 0x07 : senserflag=2break// 过右偏

case 0x10 : senserflag=1break//大左偏

case 0x02 : senserflag=2break//大右偏

case 0x18 : senserflag=3break//左偏

case 0x06 : senserflag=4break//右偏

case 0x08 : senserflag=5break//微左偏

case 0x04 : senserflag=6break//微右偏

default :senserflag=0break

}

}

//****************timer1 initial**************************

void TIMER1_init(int temp_timsk ,int temp_ccra,int temp_ccrb )

{ uchar sreg

sreg=SREG

_CLI()

TIMSK=temp_timsk

TCCR1A= temp_ccra

TCCR1B= temp_ccrb

SREG=sreg

}

//*************write OCR1A***************

void set_ocr1A(int tempocr)

{ uchar sreg

sreg=SREG

_CLI()

OCR1A=tempocr

SREG=sreg

}

//************write OCR1B*******************

void set_ocr1B(int tempocr)

{ uchar sreg

sreg=SREG

_CLI()

OCR1B=tempocr

SREG=sreg

}

//************long delay*********************

void delay(int k)

{int i,j

for(i=0i<=ki++)

{for(j=0j<=5000j++)}

}

//***********初始化*************************

void system_set ()

{

DDRA=0X80 //PA7输出,其他输入

PORTA=0X00

DDRB=0XFE //PORTB0输入,其它输出

PORTB=0X0E

DDRC=0x7f

PORTC=0x7f

DDRD=0xf0

PORTD=0xc0

set_ocr1A(200)

set_ocr1B(200)

TIMER1_init( 0X04, 0XA1, 0X03 )

TCNT1=0Xff

_SEI()

}

//***********timer0 initial******************//

void timer0_init(uchar temp_tcnt0,uchar temp_tccr0)

{TCNT0=temp_tcnt0

TCCR0=temp_tccr0

}

//**************校偏***********************

void speed_revise(void)

{

switch (senserflag)

{case 0: {set_ocr1A(250)set_ocr1B(250)}break//无偏,向前走

case 1: {set_ocr1B(255)set_ocr1A(0)}break//大左偏,右电机减速

case 2: {set_ocr1A(255)set_ocr1B(0)}break//大右偏,左电机减速

case 3: {set_ocr1A(80)set_ocr1B(255)}break//左偏,右电机减速

case 4: {set_ocr1A(255)set_ocr1B(80)}break// 右偏,左电机减速

case 5: {set_ocr1B(255)set_ocr1A(150)}break//微左偏,右电机减速

case 6: {set_ocr1B(150)set_ocr1A(255)}break//微右偏,左电机减速

default:{set_ocr1A(250)set_ocr1B(250)} break

}

}

//****************停车倒转函数************************

void stop_roll_rob()

{uchar temp=0

if(jsflag==1)

{

PORTA^=0x80

}

if(jsflag==2)

{_CLI()

set_ocr1A(0)//如果jsflag==2停车

set_ocr1B(0)

task=0

PORTA^=0x80

display_data()//显示数据处理

timer0_init(0x06,0x04)

TIMSK=0x01

_SEI()

do

{Process(Timer,Data) //计数值处理

Display(Data) //动态扫描显示

}while((Timer[0]!=0)|(Timer[1]!=0))

PORTC=0

PORTB=0X0E

_CLI()

TIMSK=0x04

timer0_init(0,0x06)

PORTD=0x40 //旋转180度

set_ocr1A(150)

set_ocr1B(150)

do

{temp=TCNT0

}

while (temp<26)

set_ocr1A(0)

set_ocr1B(0)

delay(100)

if(PINC&0x80)

{timer0_init(0,0x06)

PORTD=0X80//反向旋转360度

set_ocr1A(150)

set_ocr1B(150)

do

{temp=TCNT0

}

while (temp<55)

}

PORTD=0xc0

set_ocr1A(0)

set_ocr1B(0)

delay(500)

jsflag=3

_SEI()

}

}

//****************停车扫描函数********************

void stop_scan(void)

{uchar temp

if(PIND&0x04)

{_CLI()

set_ocr1A(0)

jsflag=4

while(1)

{

if(PIND&0x08)

{set_ocr1B(0)break

}

}

delay(200)

timer0_init(0,0x06)

set_ocr1A(100)

set_ocr1B(100)

do

{temp=TCNT0

}

while (temp<18)

set_ocr1A(0)

set_ocr1B(0)

while(1)

{Display(disdata)}

}

}

//*************路程测量***********************

void distance(void)

{

if(TIFR&0X01)

{TIFR|=0x01

TCNT0=0

distancecount+=256

}

}

//***********路程计算显示数据处理***********************

void display_data(void)

{distancecount+=TCNT0

distancedata=distancecount*53/100

disdata[0]=distancedata/100

disdata[1]=(distancedata%100)/10

disdata[2]=distancedata%10

}

//************主函数***************************

void main(void)

{OSCCAL=0xBA

delay(200)

system_set ()

timer0_init(0,0x06)

while(1)

{if(jsflag!=4)

speed_revise()

if(task)

stop_roll_rob()

if(jsflag==3)

stop_scan()

if(!jsflag)

distance()

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12305677.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存