电机速度控制PIC课设报告程序Word文件下载.docx
《电机速度控制PIC课设报告程序Word文件下载.docx》由会员分享,可在线阅读,更多相关《电机速度控制PIC课设报告程序Word文件下载.docx(15页珍藏版)》请在冰豆网上搜索。
unsignedcharD;
//占空比10倍
unsignedHT;
//高电平时间(us)
unsignedintN0_MIN=150;
unsignedintN0_MAX=2048;
unsignedintN0;
//期望转速值
unsignedintN;
//实际测速值
unsignedcharDN;
//转速误差
unsignedlongn;
charWW,QW,BW,SW,GW;
unsignedcharT0N;
unsignedintDN_OLD;
unsignedintT=0;
unsignedintN1;
unsignedintN2;
intAD_SUB(void);
voidCSH(void);
voidDISP_N0_DN(unsignedint,unsignedchar);
voidDISP_N_D(unsignedint,unsignedchar);
voidCAP_CSH(void);
voidPWM_CSH(unsignedint);
voidDUTY_SET(unsignedint);
voidAD_CSH(void);
voidLCD_CSH(void);
voidLCD_WRITE_4(char,char);
voidLCD_WRITE(char,char);
voidLCD_BUSY(void);
charLCD_READ(void);
voidDISP_C(char);
voidDISP_MENU(constchar*A);
voidBCD(unsignedint);
voidDELAY(unsignedint);
voidDELAY_I(unsignedint);
voidDELAY_US(char);
voidinterruptINT_ISR(void);
voidchange(void);
//unsignedintDN_GET(void);
//宏定义:
清屏
#defineCLR_LCD()\
LCD_WRITE(0b00000001,COM);
\
DELAY
(2)
//AD转换,期望转速N0取值N0_MIN~N0_MAX,并放大100倍
voidmain(void)
unsignedinti;
CSH();
DISP_MENU(*MENU0);
DELAY(100);
//DELAY(400);
CLR_LCD();
while
(1)
{
N0=AD_SUB();
DISP_N0_DN(N0,DN);
//显示期望转速和转速误差允许值
DISP_N_D(N,D);
change();
//显示实际转速和占空比
while(KEY.FLAG==0)
{DELAY
(1);
i++;
if(i>
200)LED=0;
400)break;
}
DN_OLD=DN;
while(KEY.FLAG==1)
{
if(KEY.SET==1)//进入修改,字符闪
LCD_WRITE(DN_POSITION,COM);
//确定字符闪的位置
LCD_WRITE(0b00001111,COM);
//字符闪
if(KEY.SETINT==1)
{if(KEY.SET==1)
N1=ND[T];
DELAY_US(3);
KEY.SETINT=0;
T++;
if(T>
10)T=0;
KEY.CHANGE=1;
}
if(KEY.INC==1)
{if(KEY.SET==1)DN++;
KEY.INC=0;
KEY.CHANGE=1;
}
if(KEY.DEC==1)
{if(KEY.SET==1)DN--;
KEY.DEC=0;
if(KEY.CHANGE==1)//如果有修改,刷新显示
{DISP_N0_DN(N0,DN);
KEY.CHANGE=0;
if(KEY.SET==1)//刷新后重新开字符标闪
LCD_WRITE(DN_POSITION,COM);
LCD_WRITE(0b00001101,COM);
if(DN_OLD!
=DN)
EEPROM_WRITE(1,DN);
//写入速度控制的回差值,在EEPROM的地址1
}
}
voidchange(void)
{unsignedintj;
if(N>
N0+DN)
{
HT--;
if(HT>
1000)HT=1000;
DUTY_SET(HT);
DELAY(300);
}
elseif(N<
N0-DN)
HT++;
1000)HT=0;
LED=1;
j=0;
voidCSH(void)
ANSELH=0;
//关闭B口模拟引脚,设为I/O引脚
TRISB=0b00001111;
OPTION=0b00010111;
//B口上拉,且下降沿中断
INTCON=0b11010000;
//GIE=1;
PEIE=1;
INTE=1;
RBIE=1;
IOCB=0b00001110;
//B口电平变化中断控制寄存器,RB1、RB2电平变化产生中断,在RBIE=1的前提下
KEY.FLAG=0;
KEY.SET=0;
TMR1H=TMR1L=0;
T1CON=0b00110001;
//1:
8分频
TRISD=0b00000000;
TRISC=0b00100000;
HT=EEPROM_READ(0);
DN=EEPROM_READ
(1);
LCD_CSH();
CAP_CSH();
PWM_CSH(HT);
AD_CSH();
intAD_SUB(void)
{GODONE=1;
while(GODONE==1);
ADIF=0;
AD_RESULT.AD[0]=ADRESL;
AD_RESULT.AD[1]=ADRESH;
n=AD_RESULT.AD_TEMP;
n*=350;
N2=n/1023+N1;
returnN2;
voidDISP_N0_DN(unsignedintSTART_N0,unsignedcharDELTA_N)
{LCD_WRITE(0b00001100,COM);
//不闪
LCD_WRITE(LINE2,COM);
//即第2行的第0个字符
BCD(START_N0);
//将要显示的起动占空比值做BCD转换
LCD_WRITE('
N'
DAT);
//在当前位置显示字符'
0'
='
:
'
LCD_WRITE(QW+0x30,DAT);
//显示千位
LCD_WRITE(BW+0x30,DAT);
//显示百位
LCD_WRITE(SW+0x30,DAT);
//显示十位
LCD_WRITE(GW+0x30,DAT);
//显示个位
r'
p'
/'
m'
m
'
//在当前位置显示空格'
BCD(DELTA_N);
//将要显示的转速n控制回差量做BCD转换
D'
n'
voidDISP_N_D(unsignedintR1,unsignedcharDUTY)//速度在R1,占空比DUTY
LCD_WRITE(0b00001100,COM);
BCD(R1);
LCD_WRITE(LINE1,COM);
//DDRAM地址,第1行的第5个字符
BCD(DUTY);
//将要显示的转速n控制回差量做BCD转换
%'
//显示字符'
voidCAP_CSH(void)
TRISC2=1;
CCP1CON=0b00000110;
T1CON=0b00110001;
CCP1IF=0;
CCP1IE=1;
GIE=1;
PEIE=1;
voidinterruptINT_ISR(void)
longX;
unsignedintTZ;
if(CCP1IF==1)
{
TMR1H=TMR1L=0;
TZ=(CCPR1H<
<
8)|CCPR1L;
X=7500000;
N=X/TZ;
CCP1IF=0;
if(INTF==1)
{DELAY_I(30);
INTF=0;
KEY.SET+=1;
KEY.FLAG=1;
if(KEY.SET>
1)
{KEY.SET=0;
KEY.FLAG=0;
RBIE=0;
//TMR1ON=1;
RBIE=1;
//PEIE=1;
//GIE=1;
T0IE=1;
TMR0=0;
T0IF=0;
T0N=0;
if(RBIF==1)
if(RB3==0&
&
KEY.FLAG==1)
{KEY.SETINT=1;
T0N=0;
if(RB2==0&
KEY.FLAG==1)
{KEY.DEC=1;
if(RB1==0&
{KEY.INC=1;
RBIF=0;
if(T0IF==1)
{T0IF=0;
T0N++;
if(T0N>
100)//约6S
{KEY.FLAG=0;
KEY.SET=0;
T0IE=0;
//设置周期为1000US的PWM输出
voidPWM_CSH(unsignedintht)
{
PR2=249;
DUTY_SET(ht);
//X=0b0011001000;
T2CON=0b00000101;
//预分频比为1:
4
//设置PWM波的高电平时间
voidDUTY_SET(unsignedintht)
{
CCPR2L=(ht>
>
2)&
0x0FF;
CCP2CON=((ht<
4)&
0x30)|0x0C;
D=ht/10;
//由高电平时间计算占空比
voidAD_CSH(void)
TRISA0=1;
ANSEL=0x01;
ADCON1=0b10000000;
//A/D结果右对齐,参考电压GND,VDD
ADCON0=0b10000001;
//AD转换时钟8us(32Tosc),AD通道AN0,GODONE=0;
AD模块使能;
DELAY_US
(2);
//延时20us
AD_SUB();
//AD转换
voidLCD_CSH(void)
DELAY(20);
LCD_WRITE_4(0b0011,COM);
DELAY
(1);
DELAY_US(10);
LCD_WRITE_4(0b0010,COM);
LCD_BUSY();
LCD_WRITE(0b00101000,COM);
//4位数据格式,2行,5*7点阵
//打开显示,光标不显示,不闪烁
LCD_WRITE(0b00000110,COM);
//光标右移,不整体移动
//将R1低4位写入LCD,FLAG选择写命令(0)或者写数据
(1)
voidLCD_WRITE_4(charR1,charFLAG)
LCD_RW=0;
NOP();
//写模式
LCD_RS=FLAG;
//选择写命令还是写数据
PORTD&
=0xF0;
//RD低4位清零
LCD_E=1;
//LCD使能
PORTD|=(R1&
0x0F);
//将R1低4位送到D端口低4位
LCD_E=0;
//使能端形成下降沿,开始送数据
LCD_RS=0;
//默认为写命令状态
PORTD&
//LCD4位数据输入端清零
//将一字节的R1写入LCD,FLAG选择写命令(0)或者写数据
(1)
//写之前先检查是否忙,写完后延时100us,分两次写4位数据/命令
voidLCD_WRITE(charR1,charFLAG)
{
charR2;
R2=(R1>
4)&
0x0F;
//先写入高4位
LCD_WRITE_4(R2,FLAG);
R2=R1&
//后写入低4位
//延时100us
voidLCD_BUSY(void)
unsignedcharR1;
R1=LCD_READ();
//读寄存器
if((R1&
0x80)==0x00)//最高位为忙标志位
break;
charLCD_READ(void)
TRISD|=0xF0;
//D口低4位为输入
//选择命令
LCD_RW=1;
//写命令模式
NOP();
//LCD使能
R1=0;
R1=PORTD&
R1=(R1<
0xF0;
//读数据的高4位给R1高4位
//使能端形成下降沿
R1|=PORTD&
//读数据的低4位给R1低4位
TRISD&
=0x0F;
//D口低4位恢复为向LCD输出
returnR1;
voidDISP_C(charline)
chari;
LCD_WRITE(line,COM);
for(i=0;
i<
16;
i++)
LCD_WRITE(DD[i],DAT);
voidDISP_MENU(constchar*A)
chari,j;
2;
for(j=0;
j<
j++)
DD[j]=*A++;
A++;
DISP_C(LINE[i]);
//从R1双字节数转换为十进制数万位-个位:
WW,QW,BW,SW,GW
voidBCD(unsignedintR1)
//延时nms
voidDELAY(unsignedintn)
voidDELAY_I(unsignedintn)
//延时(n*10)us
voidDELAY_US(charn)