/****************************************Copyright (c)**************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.embedtools.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: Main.c
** Last modified Date: 2006-11-18
** Last Version: v1.0
** Description: PID算法控制直流电机主文件
**
**------------------------------------------------------------------------------------------------------
** Created By: Zhou Shaogang
** Created date: 2006-11-18
** Version: v1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#include "Config.H"
/************************* GPIO 定义 *************************/
/*************************************************************/
#define LED_PIN1 GPIO_PIN_7
#define LED_PIN2 GPIO_PIN_5
#define LED1_ON() GPIOPinWrite(GPIO_PORTD_BASE, LED_PIN1, ~LED_PIN1)
#define LED1_OFF() GPIOPinWrite(GPIO_PORTD_BASE, LED_PIN1, LED_PIN1)
#define LED2_ON() GPIOPinWrite(GPIO_PORTC_BASE, LED_PIN2, ~LED_PIN2)
#define LED2_OFF() GPIOPinWrite(GPIO_PORTC_BASE, LED_PIN2, LED_PIN2)
#define BUZ_PIN GPIO_PIN_5 //PB2
#define BUZ_ON() GPIOPinWrite(GPIO_PORTA_BASE, BUZ_PIN, ~BUZ_PIN)
#define BUZ_OFF() GPIOPinWrite(GPIO_PORTA_BASE, BUZ_PIN, BUZ_PIN)
#define SPEED_PIN1 GPIO_PIN_0
#define SPEED_PIN2 GPIO_PIN_1
#define SPEED_NUM_MAX 30
long SpeedCnt=0; //转速计数器
long ExpSpeed=3000; //期望转速,分/转
long CurDuty=DutyBase; //当前占空比
uint8 TsmpCnt=10; //采样计数器
uint32 UartTimeout; //串口超时计数器
uint32 SpeedNum=1; //转速记录数
uint8 DirClockwise=1; //转速方向
uint16 CompCnt=0; //比较器计数器
uint8 OverCur=0; //过流标志
uint8 Speed_Queue[SPEED_NUM_MAX*4+20];
uint8 UartData[SPEED_NUM_MAX*4+100];
uint8 Auto_Rec_Speed=0;
long Bytes_To_Long(uint8 *Buffer) //4个字节合成一个长整型数
{
long lTemp;
lTemp=(long) (Buffer[0]+(Buffer[1]<<8)+(Buffer[2]<<16)+((Buffer[3]& 0x7F)<<24));
if(Buffer[3] & 0x80)
return( lTemp*(-1) );
else
return(lTemp);
}
void Long_To_Bytes(long LongData, uint8 *Buffer) //长整型数分成4个字节
{
long lTemp;
lTemp=LongData;
if(lTemp<0)
{
lTemp=lTemp*(-1);
Buffer[3]=( (uint8)( (lTemp>>24) & 0x7F ) ) | 0x80;
}
else
{
Buffer[3]=( (uint8)( (lTemp>>24) & 0x7F ) );
}
Buffer[0]=(uint8)( lTemp & 0xFF );
Buffer[1]=(uint8)( (lTemp>>8) & 0xFF );
Buffer[2]=(uint8)( (lTemp>>16) & 0xFF );
}
void Delay(uint32 n) //延时函数
{
while(n--);
}
/****************************GPIO*****************************/
/*************************************************************/
void GPIOInit(uint8 PA_Prio)
{
//设置LED1、LED2、蜂鸣器设置为输出
GPIODirModeSet(GPIO_PORTD_BASE, LED_PIN1, GPIO_DIR_MODE_OUT);
GPIODirModeSet(GPIO_PORTC_BASE, LED_PIN2, GPIO_DIR_MODE_OUT);
GPIODirModeSet(GPIO_PORTA_BASE, BUZ_PIN, GPIO_DIR_MODE_OUT);
//设置中断
IntEnable(INT_GPIOD);
IntPrioritySet(INT_GPIOD, PA_Prio);
GPIODirModeSet(GPIO_PORTD_BASE, SPEED_PIN1 | SPEED_PIN2, GPIO_DIR_MODE_IN);
GPIOIntTypeSet(GPIO_PORTD_BASE, SPEED_PIN1 | SPEED_PIN2, GPIO_FALLING_EDGE);
GPIOPinIntEnable(GPIO_PORTD_BASE, SPEED_PIN1 | SPEED_PIN2);
}
void GPIO_Port_D_ISR(void)
{
static uint8 DirStep=0;
static uint16 Dir_T1;
static uint16 Dir_T2;
if( !GPIOPinRead(GPIO_PORTD_BASE, SPEED_PIN1) ) //SPEED1低电平,转速计数器加一
{ SpeedCnt++; }
switch(DirStep)
{
case 0: //第0步
if( !GPIOPinRead(GPIO_PORTD_BASE, SPEED_PIN1) ) //SPEED1低电平
{
TimerLoadSet(TIMER0_BASE, TIMER_B, 0xFFFF); //复位定时器0B
DirStep++; //下一步
}
break;
case 1: //第1步
if( !GPIOPinRead(GPIO_PORTD_BASE, SPEED_PIN2) ) //SPEED2低电平
{
//读出第一个SPEED1下降沿和SPEED2下降沿之间的时间
Dir_T1=(uint16)TimerValueGet(TIMER0_BASE, TIMER_B);
TimerLoadSet(TIMER0_BASE, TIMER_B, 0xFFFF);
DirStep++;
}
break;
case 2: //第2步
if( !GPIOPinRead(GPIO_PORTD_BASE, SPEED_PIN1) ) //SPEED1低电平
{
//读出SPEED2下降沿和第二个SPEED1下降沿之间的时间
Dir_T2=(uint16)TimerValueGet(TIMER0_BASE, TIMER_B);
DirStep=0;
if(Dir_T1>Dir_T2)
{ DirClockwise=1; } //电机正转中
else
{ DirClockwise=0; } //电机反转中
}
break;
default:
DirStep=0;
break;
} //switch
GPIOPinIntClear(GPIO_PORTD_BASE, SPEED_PIN1 | SPEED_PIN2);
}
/************************PWMA & Timer0B************************/
/*************************************************************/
void InitPwmTmr(uint16 CycleNum, uint16 DutyNum)
{
//PB0为PWM输出
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_0);
//定时器0A产生PWMA,定时器0B为16位计时器
TimerConfigure(TIMER0_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PERIODIC);
///PWMA的占空比为低电平有效
TimerControlLevel(TIMER0_BASE, TIMER_A, false);
//设定周期
TimerLoadSet(TIMER0_BASE, TIMER_A, CycleNum);
///设定占空比
TimerMatchSet(TIMER0_BASE, TIMER_A, DutyNum);
//定时器0B使用6倍分频
TimerPrescaleSet(TIMER0_BASE, TIMER_B, 6);
//使能定时器0A和0B
TimerEnable(TIMER0_BASE, TIMER_BOTH);
}
#define AdjDutyA(DutyA) TimerMatchSet(TIMER0_BASE, TIMER_A, DutyA)
/****************************Timer1***************************/
/*************************************************************/
void Timer1Init(uint8 Prio)
{
//定时器1为32位
TimerConfigure(TIMER1_BASE, TIMER_CFG_32_BIT_PER);
//设定超时中断时间
TimerLoadSet(TIMER1_BASE, TIMER_A, (uint32)(Tsmp*Ftmr1));
//使能定时器1系统中断
IntEnable(INT_TIMER1A);
//设定优先极
IntPrioritySet(INT_TIMER1A, Prio);
//使能定时器1中断
TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
//使能定时器1
TimerEnable(TIMER1_BASE, TIMER_A);
}
void Timer1A_ISR(void)
{
static uint8 TickCnt=0;
long lTemp;
uint8 Buf[10];
if(CompCnt<100) //比较器延时计数器加一
{ CompCnt++; }
TickCnt++; //PID计时器加一
if(TickCnt<TsmpCnt) //时间未到,清除中断标志,退出中断
{ TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); return; }
TickCnt=0;
lTemp=(long) ( SpeedCnt * ((60/Tsmp)/(TsmpCnt*4 )) ); //计算转速大小
if(!DirClockwise) //设定转速正负号
{ lTemp=lTemp*(-1); }
SpeedCnt=0;
if( Auto_Rec_Speed ) //要求记录转速
{
Long_To_Bytes(lTemp, Buf); //把long型的转速拆成4个byte
QueueWriteN(Speed_Queue, Buf, 4); //转速入队列
}
lTemp = ExpSpeed-lTemp; //转速误差
lTemp = CurDuty + PID_DltDuty(lTemp); //调用PID函数算出当前PWM的占空比
if(CurDuty != lTemp)
{
CurDuty=lTemp;
if(CurDuty>=PWM_Cycle) //占空比的时间大于周期
{ CurDuty=PWM_Cycle-1; }
else if(CurDuty<=0) //占空比小于零
{ CurDuty=1; }
AdjDutyA( (uint16) CurDuty );
}
UartTimeout++; //
评论2