与PIC单片机实用C语言程序设计与典型实例书籍配套的光盘实例,包括原理图和C语言程序文件,希望对大家有所帮助!
单片机源程序如下:
- #include <p18cxxx.h>
- #include "16x2LCDDriver.h"
- unsigned char LCDBuffer_0[]={"STOP 00% DIR +"};
- unsigned char LCDBuffer_1[]={"Get Spd 0000 RPM"};
- struct TMR1COUNTER_STRUCT
- {
- unsigned char HighCounter;
- unsigned int LowCounter;
- unsigned char ChangeFlag;
- };
- struct TMR1COUNTER_STRUCT MyTMR1,MyTMR3,GetTMR1,GetTMR3;
- void OSCillator_Initize(void)
- {
- OSCCON=0x70;//选择内部8MHz的主振荡器
- OSCTUNE=0x40;//使能4xPLL--->Fosc=32MHz
- }
- void PIC_PortDir_Initize(void)
- {
- ADCON1=0x0F;//RA和RE端口全为数字IO口
- TRISD=0x00;//RD端口置输出方向
- TRISE=0x00;//RE端口置输出方向
- TRISCbits.TRISC1=0;
- TRISCbits.TRISC2=0;
- TRISCbits.TRISC3=0;
- }
- void PIC_TMR0_Initize(void)
- {
- T0CONbits.TMR0ON=0;//TMR0停止工作
- T0CONbits.T08BIT=0;//选择16位的定时/计数器
- T0CONbits.T0CS=0;//选择内部CLKO时钟源作为定时
- T0CONbits.PSA=0;//选择预分频器
- T0CONbits.T0PS2=1;//预分频比为1:256
- T0CONbits.T0PS1=1;
- T0CONbits.T0PS0=1;
- TMR0H=(65536-31250)/256;//先写高字节
- TMR0L=(65536-31250)%256;//再写低字节
- T0CONbits.TMR0ON=1;//开始定时工作
- }
- void PIC_TMR1_Initize(void)
- {
- //此处TMR1的预分频比为1:1
- T1CONbits.RD16=1;//允许一次性读写16位
- T1CONbits.TMR1CS=1;//选择外部时钟源,TMR1用作外部计数
- TMR1H=0;//TMR1数据寄存器清0
- TMR1L=0;
- T1CONbits.TMR1ON=1;//允许TMR1开始工作
- }
- void PIC_TMR3_Initize(void)
- {
- //此处TMR1的预分频比为1:8
- T3CONbits.T3CKPS1=1;
- T3CONbits.T3CKPS0=1;
- T3CONbits.RD16=1;//允许一次性读写16位
- T3CONbits.TMR3CS=0;//选择内部时钟源,TMR3用作内部计数
- TMR3H=0;//TMR3数据寄存器清0
- TMR3L=0;
- T3CONbits.TMR3ON=1;//允许TMR3开始工作
- }
- void PIC_Interrupt_Initize(void)
- {
- INTCONbits.TMR0IF=0;//TMR0溢出标志位清0
- INTCONbits.TMR0IE=1;//TMR0溢出中断允许
-
- PIR1bits.TMR1IF=0;//TMR1溢出标志位清0
- PIE1bits.TMR1IE=1;//TMR1溢出中断允许
- IPR1bits.TMR1IP=0;//低优先级
-
- PIR2bits.TMR3IF=0;//TMR1溢出标志位清0
- PIE2bits.TMR3IE=1;//TMR1溢出中断允许
- IPR2bits.TMR3IP=0;//低优先级
-
- INTCONbits.INT0IF=0;//清INT0中断标志位
- //INTCONbits.INT0IE=1;//INT0中断允许
- INTCON2bits.RBPU=0;//允许内部弱上拉
- INTCON2bits.INTEDG0=1;//上边沿触发中断
-
- RCONbits.IPEN=1;//允许中断优先级位
- INTCONbits.GIE=1;//CPU全局中断使能允许
- INTCONbits.PEIE=1;//CPU第二梯队中断使能允许
- }
- void PIC_CCPForPWM_Initize(void)
- {
- TRISCbits.TRISC1=0;//RC1置输出方向
- TRISCbits.TRISC2=0;//RC2置输出方向
- LATCbits.LATC1=0;//RC1引脚输出为0
- LATCbits.LATC2=0;//RC2引脚输出为0
- CCP1CON=0x0F;//CCP1设置为PWM模式
- CCP2CON=0x0F;//CCP2设置为PWM模式
- T2CON=0x03;//TMR2的预分频为1:16
- T2CONbits.TMR2ON=1;//TMR2开始工作
- PR2=249;//PWM周期为2000Hz,FOSC=32MHz
- CCPR1L=0;//PWM1的占空比为0
- CCPR2L=0;//PWM2的占空比为0
- }
- unsigned char CycleFlag;
- unsigned char FreqFlag;
- #define RUNSTOPKEY PORTBbits.RB3
- #define PWMKEY PORTBbits.RB4
- #define DIRKEY PORTBbits.RB5
- unsigned char MotorRunStatus;
- unsigned char MotorDirection;
- unsigned char MotorPWMData;
- unsigned char RunStopKeyFlag;
- unsigned int RunStopKeyCounter;
- unsigned char DirKeyFlag;
- unsigned int DirKeyCounter;
- unsigned char PWMKeyFlag;
- unsigned int PWMKeyCounter;
- void SystemVariant_Initize(void)
- {
- MotorPWMData=0;
- }
- void Motor_Control(unsigned char Direction,
- unsigned char Speed)
- {
- switch(Direction)
- {
- case 0:
- CCPR1L=0;
- CCPR2L=0;
- CCPR1L=Speed;
- break;
- case 1:
- CCPR2L=0;
- CCPR1L=0;
- CCPR2L=Speed;
- break;
- }
- }
- //-------------------------------------------------------------------
- void PIC18F_High_isr(void);//高优先级中断函数声明
- #pragma code high_vector_section=0x8
- void high_vector (void)
- {
- _asm goto PIC18F_High_isr _endasm
- }
- void SystemInterruptISR(void);//低优先级中断函数声明
- #pragma code low_vector=0x18//低中断优先级
- void low_interrupt(void)
- {
- _asm goto SystemInterruptISR _endasm
- }
- #pragma code
- //-------------------------------------------------------------------
- void main(void)
- {
- unsigned long temp;
- unsigned char i;
-
- OSCillator_Initize();//CPU系统时钟初始化内部时钟源8MHz,经过4xPLL
- PIC_PortDir_Initize();//PIC单片机的使用到的I/O口方向初始化
- PIC_TMR0_Initize();//PIC单片机的TMR0定时器初始化为内部定时方式
- PIC_TMR1_Initize();//PIC单片机的TMR1定时器初始化为外部计数方式
- PIC_TMR3_Initize();
- PIC_CCPForPWM_Initize();
- PIC_Interrupt_Initize();
- initize_lcd();
-
- while(1)
- {
- if(0==RUNSTOPKEY)//判断启动按键是否按下
- {
- if(0==RunStopKeyFlag)//检测启动按键是否成功按下标志
- {
- RunStopKeyCounter++;//软件计数器,用于按键去抖动
- if(4000==RunStopKeyCounter)//按键去抖动延时到
- {
- RunStopKeyCounter=0;//清软计数器为0
- if(0==RUNSTOPKEY)//再判断启动按键是否真得按下
- {
- RunStopKeyFlag=1;//置启动按键成功按下标志为1
- if(0==MotorRunStatus)//如果电机是处理停止状态
- {//则启动电机运转
- MotorRunStatus=1;//同时置电机状态为1
- LCDBuffer_0[0]='R';//LCD显示屏上显示"RUN"
- LCDBuffer_0[1]='U';
- LCDBuffer_0[2]='N';
- LCDBuffer_0[3]=' ';
- LCDBuffer_0[4]=' ';
- temp=MotorPWMData;//读取设置电机速度的变量
- temp<<=1;//转换成占空比送到LCD上显示
- temp/=5;
- LCDBuffer_0[5]=(temp/10)+0x30;
- LCDBuffer_0[6]=(temp%10)+0x30;
- LCDBuffer_0[7]='%';
- LCDBuffer_0[8]=' ';
- LCDBuffer_0[9]='D';
- LCDBuffer_0[10]='I';
- LCDBuffer_0[11]='R';
- LCDBuffer_0[12]=' ';
- if(0==MotorDirection)//根据电机运转的方向
- {//来设置电机是正转还是反转,并在LCD上显示
- CCPR1L=0;
- CCPR2L=0;
- CCPR1L=MotorPWMData;//使RC1引脚输出PWM信号
- LCDBuffer_0[13]='+';//表示电机正转
- }
- else
- {
- CCPR2L=0;
- CCPR1L=0;
- CCPR2L=MotorPWMData;//使RC2引脚输出PWM信号
- LCDBuffer_0[13]='-';//表示电机反转
- }
- }
- else//如果电机是在运转中,则这时按下该键可以停止电机运转
- {
- MotorRunStatus=0;//置电机运动状态为0
- LCDBuffer_0[0]='S';//LCD屏上显示"STOP"
- LCDBuffer_0[1]='T';
- LCDBuffer_0[2]='O';
- LCDBuffer_0[3]='P';
- LCDBuffer_0[4]=' ';
- LCDBuffer_0[5]='0';
- LCDBuffer_0[6]='0';
- CCPR1L=0;//RC1和RC2引脚不输出PWM信号
- CCPR2L=0;
- }
- lcd_displaystr(0,0,LCDBuffer_0);//将字符串送到LCD上显示
- }
- }
- }
- }
- else
- {
- if(1==RUNSTOPKEY)//等待按键释放处理过程
- {
- if(1==RunStopKeyFlag)
- {
- RunStopKeyFlag=0;//清启动按键上次成功按下标志
- RunStopKeyCounter=0;//消抖动延时计数器清0
- }
- }
- }
-
- if(0==DIRKEY)//判断电机运转方向切换键是否按下
- {
- if(0==DirKeyFlag)//判断方向切换键的标志是否成功
- {
- DirKeyCounter++;//去抖动计数器加1
- if(4000==DirKeyCounter)//去抖动延时时间到
- {
- DirKeyCounter=0;//计数器清0
- if(0==DIRKEY)//判断是否真得按下
- {
- DirKeyFlag=1;//置成功按下标志成立
- if(0==MotorDirection)//电机是正转方向吗?
- {
- MotorDirection=1;//置反向运转方向状态
- LCDBuffer_0[13]='-';//LCD显示屏显示"-"
- CCPR2L=0;
- CCPR1L=0;
- CCPR2L=MotorPWMData;//启动RC2输出PWM信号
- }
- else
- {
- MotorDirection=0;//置正向运转方向状态
- LCDBuffer_0[13]='+';//LCD显示屏上显示"+"
- CCPR1L=0;
- CCPR2L=0;
- CCPR1L=MotorPWMData;//启运RC1输出PWM信号
- }
- lcd_displaystr(0,0,LCDBuffer_0);//将字符串送到LCD上显示
- }
- }
- }
- }
- else
- {
- if(1==DIRKEY)//等待按键释放
- {
- if(1==DirKeyFlag)//如果上次按键按下标志成功,则
- {
- DirKeyFlag=0;//清按键按下标志
- DirKeyCounter=0;//清计数器为0
- }
- }
- }
-
- if(0==PWMKEY)//判断电机速度调节键是否按下
- {
- if(0==PWMKeyFlag)//判断按键按下标志是否为0
- {
- PWMKeyCounter++;//去抖动计数器加1
- if(4000==PWMKeyCounter)//支抖动延时时间到
- {
- PWMKeyCounter=0;//清计数器为0
- if(0==PWMKEY)//再判断电机速度调节键是否真得按下
- {
- PWMKeyFlag=1;//置本次按键按下标志成功
- temp=MotorPWMData;//读取PWM变量的内容
- temp<<=1;//将其转换成0-100之间的占空比
- temp/5;
- temp++;//占空比加1
- if(100==temp)temp=0;//到100归0
- LCDBuffer_0[5]=(temp/10)+0x30;//送到LCD缓冲区
- LCDBuffer_0[6]=(temp%10)+0x30;
- temp*=5;//再将其转换成0-250之间的PWM数据
- temp>>=1;
- MotorPWMData=temp;//装入PWM变量中
- if(0==MotorDirection)//如果电机方向是正转
- {
- LCDBuffer_0[13]='+';//LCD上显示"+"
- CCPR1L=0;
- CCPR2L=0;
- CCPR1L=MotorPWMData;//PWM变量内容送到CCP1
- }
- else
- {
- LCDBuffer_0[13]='-';
- CCPR2L=0;
- CCPR1L=0;
- CCPR2L=MotorPWMData;//PWM变量送到CCP2
- }
- lcd_displaystr(0,0,LCDBuffer_0);//将字符串送到LCD上显示
- }
- }
- }
- }
- else
- {
- if(1==PWMKeyFlag)//等待按键释放
- {
- PWMKeyFlag=0;//清按键按下标志
- PWMKeyCounter=0;//计数器清0
- }
- }
-
- if((1==FreqFlag)&&(0==CycleFlag))//1S的测频标志成立
- {
- FreqFlag=0;//清测频标志
- temp=MyTMR1.HighCounter;//读取经过测频的计数脉冲
- temp<<=16;
- temp|=MyTMR1.LowCounter;
- //电机速度小于1000RPM,切换到测周法
- if(temp<1000)
- {
- INTCONbits.INT0IE=1;//允许INT0中断允许
- INTCONbits.INT0IF=0;//清INT0中断标志位
- MyTMR3.ChangeFlag=0;//清测周所用变量标志位
- }
- else//否则就用测频法计算电机速度
- {
- INTCONbits.INT0IE=0;//禁止INT0中断允许
- INTCONbits.INT0IF=0;//清INT0中断标志位
- //将测量的结果显示在LCD显示屏上
- for(i=8;i<12;i++)LCDBuffer_1[i]=0x30;
- i=11;
- while(temp)
- {
- LCDBuffer_1[i]=(temp%10)+0x30;
- temp/=10;
- i--;
- }
- MyTMR1.HighCounter=0;//清TMR1使用的相关变量
- MyTMR1.LowCounter=0;
- T1CONbits.TMR1ON=1;
- lcd_displaystr(1,0,LCDBuffer_1);//将测量的结果送到LCD上显示
- }
- }
-
- if((1==CycleFlag)&&(0==FreqFlag))
- {
- CycleFlag=0;
- temp=MyTMR3.HighCounter;
- temp<<=16;
- temp|=MyTMR3.LowCounter;
- temp=1000000/temp;
- //将测量的结果显示在LCD显示屏上
- for(i=8;i<12;i++)LCDBuffer_1[i]=0x30;
- i=11;
- while(temp)
- {
- LCDBuffer_1[i]=(temp%10)+0x30;
- temp/=10;
- i--;
- }
- MyTMR3.HighCounter=0;
- MyTMR3.LowCounter=0;
- T1CONbits.TMR1ON=1;
- lcd_displaystr(1,0,LCDBuffer_1);//将测量的结果送到LCD上显示
- }
- }
- }
- //-------------------------------------------------------------------
- #pragma interrupt PIC18F_High_isr
- void PIC18F_High_isr(void)
- {
- unsigned long temp;
-
- if(1==INTCONbits.INT0IF)
- {
- INTCONbits.INT0IF=0;
- if(MyTMR3.ChangeFlag)
- {
- INTCONbits.INT0IE=0;
- MyTMR3.ChangeFlag=0;//如果标志为1,则置0
- MyTMR3.LowCounter=TMR3L;//读取TMR3寄存器的内容
- MyTMR3.LowCounter=TMR3H;
- MyTMR3.LowCounter<<=8;
- MyTMR3.LowCounter|=TMR3L;
- FreqFlag=0;
- CycleFlag=1;
- }
- else
- {
- MyTMR3.ChangeFlag=1;//如果标志为0,则置1
- MyTMR3.HighCounter=0;//清相关变量
- MyTMR3.LowCounter=0;
- }
- }
-
- if(1==INTCONbits.TMR0IF)//定时1S时间到
- {
- INTCONbits.TMR0IF=0;//TMR0溢出标志位清0
- TMR0H=(65536-31250)/256;//先写高字节
- TMR0L=(65536-31250)%256;//再写低字节
-
- T1CONbits.TMR1ON=0;//TMR1计数器停止工作
- MyTMR1.LowCounter=TMR1L;
- MyTMR1.LowCounter=TMR1H;
- MyTMR1.LowCounter<<=8;
- MyTMR1.LowCounter|=TMR1L;
- CycleFlag=0;
- FreqFlag=1;
- }
- }
- //-------------------------------------------------------------------
- //---低优先中断服务程序函数
- #pragma interruptlow SystemInterruptISR
- void SystemInterruptISR(void)
- {
- if(1==PIR1bits.TMR1IF)//如果TMR1溢出
- {
- PIR1bits.TMR1IF=0;//清TMR1溢出标志位
- MyTMR1.HighCounter++;//TMR1软计数器加1
- }
-
- if(1==PIR2bits.TMR3IF)//如果TMR3溢出
- {
- PIR2bits.TMR3IF=0;//清TMR3溢出标志位
- MyTMR3.HighCounter++;//TMR3软计数器加1
- }
- }
复制代码
所有资料51hei提供下载:
PIC单片机实用C语言程序设计与典型实例(光盘).rar
(327.06 KB, 下载次数: 218)
|