方波信号发生器实例
/************************************************** ; CPU类型: PIC12F629 ; 内部RC振荡器: 4MHz ; C编译器: HT-PICC ; 集成开发环境: MPLAB v8.01 ; 方波信号发生器实例
**************************************************/ #include
#define GPIO2_STATUS GPIO2 #define GPIO4_STATUS GPIO4 #define GPIO5_STATUS GPIO5 #define GPIO2_ON GPIO2=1 #define GPIO2_OFF GPIO2=0 #define GPIO4_ON GPIO4=1 #define GPIO4_OFF GPIO4=0 #define GPIO5_ON GPIO5=1 #define GPIO5_OFF GPIO5=0
unsigned char Hz50_Count=0;//产生50Hz频率的软计数器变量 unsigned char Hz1_Count=0;//产生1Hz频率的软计数器变量
void System_Init(void) {
CMCON = 0x00;//将GP0、GP1初始化为数字I/O引脚
ANSEL = 0x07;//将GP0、GP1、GP2、GP4初始化为数字I/O引脚 TRISIO2=0;//置GP2为输出 TRISIO4=0;//置GP4为输出 TRISIO5=0;//置GP5为输出
GPIO2 = 0;//GP2输出为低电平 GPIO4 = 0;//GP4输出为低电平 GPIO5 = 0;//GP5输出为低电平
T0CS = 0;//选择内部Fosc/4时钟源,作为定时 PSA = 0;//将预分频器分配给Timer0模块 PS2 = 0;//初始化预分频比为1:2 PS1 = 0; PS0 = 0;
TMR0=256-250;//初始化定时500uS的初值 }
void main(void) {
System_Init();//调用系统初始化函数 while(1) {
if(1==T0IF)//判断T0IF溢出标志是否为1 {
T0IF=0;//清T0IF溢出标志
TMR0=256-250;//重新装入定时500uS初值
if(1==GPIO2_STATUS)GPIO2_OFF;//如果GP2引脚电平为高电平,则输出低电平 else GPIO2_ON;//否则输出高电平;此处是产生1KHz方波信号从GP2引脚输出
Hz50_Count++;//产生50Hz方波信号变量加1
if(20==Hz50_Count)//判断是否满足产生50Hz计数条件 {
Hz50_Count=0;//清计数值变量
if(1==GPIO4_STATUS)GPIO4_OFF;//如果GP4引脚电平为高电平,则输出低电平 else GPIO4_ON;//否则输出高电平;此处是产生50Hz方波信号从GP4引脚输出
Hz1_Count++;//产生1Hz方波信号变量加1
if(50==Hz1_Count)//判断是否满足产生1Hz计数条件 {
Hz1_Count=0;//清计数值变量
if(1==GPIO5_STATUS)GPIO5_OFF;//如果GP5引脚电平为高电平,则输出低电平 else GPIO5_ON;//否则输出高电平;此处是产生1Hz方波信号从GP5引脚输出 } } } } }
PIC单片机控制的电动自行车驱动系统
#i nclude #i nclude
//电动车双闭环程序,采用双闭环方式控制电机,以得到最好的zh转速性能,并且可以 //限制电机的最大电流。本应用程序用到两个CCP部件,其中CCP1用于PWM输出,以控 //制电机电压;CCP2用于触发AD,定时器TMR2、TMR1,INT中断,RB口电平变化中断, //看门狗以及6个通用I/O口
#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 //低电压保护重开电压3.0 V即33 V #define VOLOFF 0X49 //低电压保护关断电压2.86 V即31.5 V 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}; //状态寄存器表 //------------PIC16F877初始化子程序------------ void INIT877() {
PORTC=0X0FF; //关断所有MOSFET TRISC=0X02; //设置C口输出
PIE1=0X00; //中断寄存器初始化,关断所有中断 TRISA=0XCF; //设置RA4,RA5 输出
TRISB=0XEF; //RB 口高三位输入,采集电机三相的霍尔信号
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为 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部件开始工作 }
//------------延时子程序--------------- #pragma interrupt_level 1 void DELAY1(x) char x; {
DELAYH=x; //延时参数设置 #asm
DELAY2 MOVLW 0X06 MOVWF _DELAYL DELAY1 DECFSZ _DELAYL GOTO DELAY1 DECFSZ _DELAYH GOTO DELAY2 #endasm }
//-----------状态采集子程序---------------------- void sample() {
char state1,state2,state3,x; do {
x=1;
state1=(PORTB&AND); //霍尔信号采集 DELAY1(x);
state2=(PORTB&AND);
}while(state1-state2); //当三次采样结果不相同时继续采集状态 if(state1-oldstate!=0) //看本次采样结果是否与上次相同,不同 //则执行
{oldstate=state1; //将本次状态设置为旧状态 state1=(oldstate>>5);
PORTC=new[state1]; //C口输出相应的信号触发两个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;